20210420_monitor
Dependencies: mbed SB1602E TextLCD MSCFILESytem FatFileSystemCpp
main.cpp
00001 00002 //20210722モニタリングシステム kikkawa //積算発電積算消費 00003 00004 #include "mbed.h" // 必須 00005 #include "stdio.h" // ファイル操作 00006 #include "SB1602E.h" // デカ文字LCD 00007 #include "TextLCD.h" // 4*20LCD 00008 #include "MSCFileSystem.h" // USBメモリ 00009 #include <string> // 文字列操作 00010 00011 /* タイマの設定 */ 00012 Timer tm1; // タイマー時間の初期化(処理時間計測に使用) 00013 Timer time0t5s; // main関数での処理に使用 00014 Timer time0t2s; // main関数での処理に使用 00015 00016 //Ticker tick; // 繰り返しタイマ割り込みの初期化 00017 TextLCD lcd1(p15,p16,p17,p18,p19,p20); // 4行LCDのポート設定(RS,E,DB4,DB5,DB6,DB7) 00018 SB1602E lcd2(p28,p27); // デカ文字LCDのポート設定(SDA,SCL) 00019 Serial pc(USBTX,USBRX); // USBシリアルポートの設定 00020 Serial im920(p13, p14); // p13(tx),p14(rx)をIM920とのシリアル通信ポートに設定 00021 CAN can(p30, p29); // CANのポート設定 00022 00023 DigitalOut led1(LED1); // LPC1768ボード上1番目のLEDの設定 00024 DigitalOut led2(LED2); // LPC1768ボード上2番目のLEDの設定 00025 DigitalOut led3(LED3); // LPC1768ボード上3番目のLEDの設定 00026 DigitalOut led4(LED4); // LPC1768ボード上4番目のLEDの設定 00027 00028 /* 変数の宣言 */ 00029 bool LED = 1; // 1のときLPC1768ボード上のLED(1~4)の点灯・点滅処理を実行. 0のとき点灯・点滅させない 00030 int MPPTerror=0; // MPPT1のエラー信号を格納する変数 00031 int MPPTerror_2=0; // MPPT2のエラー信号を格納する変数 00032 int direc=0; // 進行方向(direction)を格納する変数 00033 float Vmot=0, Cmot=0, Pmot=0; // 消費電圧、電流、電力を格納する変数 00034 float Vsol=0, Csol=0, Psol=0; // 発電電圧・電流・電力を格納する変数 00035 float Vbat=0, Cbat=0, Pbat=0; // バッテリ電圧・電流・電力を格納する変数 00036 float VcelMax=0,VcelAve=0,VcelMin=0; // セル最大・平均・最小電圧を格納する変数 00037 float speed=0; // 走行速度を格納する変数 00038 signed char duty=0; // スロットル開度を格納する変数 00039 00040 int cntTera = 0; 00041 00042 /* ユーザ定義関数の宣言 */ 00043 void init(void); // 初期化を行う関数を宣言 00044 void printTera(void); // Teraterm表示を行う関数を宣言 00045 00046 //灯火類の設定 00047 /* 00048 DigitalIn indiR_IN(p15); // 方向指示器(右)の入力の設定 00049 DigitalIn indiL_IN(p14); // 方向指示器(左)の入力の設定 00050 DigitalIn head_IN(p13); // ヘッドライトの入力の設定 00051 DigitalIn horn_IN(p12); // ホーンの入力の設定 00052 DigitalIn brake_IN(p11); // ブレーキランプの入力の設定 00053 00054 PwmOut indiR_OUT(p20); // 方向指示器(右)の出力の設定 00055 PwmOut indiL_OUT(p19); // 方向指示器(左)の出力の設定 00056 PwmOut headt_OUT(p18); // ヘッドライトの出力の設定 00057 DigitalOut horn_OUT(p17); // ホーンの出力の設定 00058 DigitalOut brake_OUT(p16); // ブレーキランプの出力の設定 00059 */ 00060 /* IM920(テレメトリ)の設定 */ 00061 int cntIM920 = 0; 00062 void printIM920(void); // PC(teraterm), IM920(テレメトリシステム), LCDへのprintf処理を行う関数 00063 00064 /* LCDの設定 */ 00065 int cntLCD=0; 00066 void printLCD(void); // LCDにデータ表示する関数 00067 00068 /* CAN通信の設定 */ 00069 char cntCAN = 0; // CAN受信でカウントアップする変数 00070 CANMessage bufCAN; // CAN受信用バッファの初期化(バッファ(buf): データを一時的に格納するためのメモリー領域) 00071 //void readCAN(void); 00072 00073 /* USBメモリ(MSC:マスストレージクラス)の設定 */ 00074 MSCFileSystem msc("usb"); // Mount flash drive under the name "usb" 00075 char *str1 = "/usb/log"; // 保存先("usb")とファイル名の一部(log)を指定 00076 char *str2 = ".csv"; // ファイルの拡張子を指定 00077 char fileName[30]; // ファイル名を格納する配列 00078 char oxMSC; // 接続有無("o"か"x")を格納する変数(1文字用) 00079 int cntMSC=0; // 処理を行うごとにカウントアップする変数 00080 void initMSC(void); // MSC(USB Mass Storage Class)の初期設定関数 00081 void saveMSC(void); // MSCへデータを書き込む関数 00082 FILE *fp2; // ファイル構造体の定義 00083 00084 void initMSC(){ // USBメモリの初期設定関数 00085 FILE *fp1; // ファイル構造体を定義 00086 int fileNumber = 0; // csvファイル命名に使用する変数を宣言 00087 00088 fp1 = fopen( "/usb/fileNumber.txt", "r" ); // USBメモリ内の"fileNumber.txt"を読み取りモードで開く 00089 if( fp1 == NULL ){ // アクセスできなかったとき, ...error( "Could not open main0\n\r" );を入れても良い 00090 pc.printf("USB init error\n\r" ); // teratermに"USB ini error"を表示 00091 oxMSC = 'x'; // MSCが接続されていないため"x"を格納(1文字なのでシングルクォーテーション) 00092 } 00093 else { // アクセスできたとき ...sbhost_lpc17xx.cppでの処理につながる 00094 oxMSC = 'o'; // 1文字だからシングルクォーテーションで囲む 00095 fscanf( fp1,"%d",&fileNumber ); // "fileNumber.txt"の数字を読み取り,変数"fileNumber"に格納する 00096 fclose( fp1 ); // "fileNumber.txt"を閉じる 00097 00098 fp1 = fopen( "/usb/fileNumber.txt", "w" ); // "fileNumber.txt"を書き込みモードで開く //exit(1);でBlueLightsOfDeath 00099 fprintf( fp1,"%d\n", fileNumber+1 ); // 読み込んだ数値に+1してfileNumber.txtに書き込み 00100 fclose(fp1); 00101 00102 sprintf(fileName,"%s%d%s\n", str1, fileNumber, str2); // 文字列の結合(データログ用ファイル名の作成) 00103 pc.printf( "\n\rUSB fileName: %s\n\r", fileName ); // 作成したファイル名をteratermに表示 00104 00105 fp2 = fopen( fileName, "w" ); // ファイルの新規作成後書き込み, ファイルがある場合上書き 00106 if(fp2 != NULL){ // NULLじゃないとき(ファイルを開けた時) 00107 fprintf( fp2,"Speed(km/h),dutyCycle,Vmot(V),Cmot(A),Pmot(W),Vsol(V),Csol(A),Psol(W),Vbat(V),Cbat(A),Pbat(W),VcelMax(V),VcelAve(V),VcelMin(V)\n" ); //ファイル書き込み 00108 fclose(fp2); // csvファイル1行目にデータ項目を入力してファイルを閉じる 00109 } 00110 } 00111 } 00112 00113 void saveMSC(){ // 処理時間50ms以上(MBED Timerで計測,データ量による) 00114 ++cntMSC; // MSCカウンタをインクリメント 00115 if( cntMSC >= 255){ cntMSC = 0; } // 255になったらリセット 00116 if( oxMSC == 'o' ){ 00117 fp2 = fopen( fileName, "a"); // ファイルを上書きモードで開く(ファイルがなければ新規作成) 00118 if ( fp2 == NULL ){ // ファイルを開けなかったとき, 00119 oxMSC = 'x'; // MSCが接続されていないため"x"を格納(1文字なのでシングルクォーテーション) 00120 }else { // USBメモリ内のファイルを開くことができたとき, 00121 fprintf( fp2,"%5.1f,%3d,%5.1f,%5.1f,%6.1f,%5.1f,%5.1f,%6.1f,%5.1f,%5.1f,%6.1f,%5.3f,%5.3f,%5.3f\n", 00122 speed, duty, Vmot, Cmot, Pmot, Vsol, Csol, Psol, Vbat, Cbat, Pbat, VcelMax, VcelAve, VcelMin ); 00123 fclose(fp2); // データを書き込んだ後,ファイルを閉じる 00124 pc.printf("MSC: %d\n", cntMSC); // 00125 } 00126 } 00127 } 00128 00129 void readCAN(){ // CANデータを受信したときに実行される関数(特定ID選択:https://os.mbed.com/questions/74230/about-ID-selectable-CAN-receive/, filter関数でも) 00130 ++cntCAN; // CANカウンタをインクリメント 00131 if( cntCAN >= 255 ){ cntCAN = 0; } // 255を超えたらリセット 00132 00133 if( can.read(bufCAN) ){ // モタコンからデータが来たとき, 00134 if( bufCAN.id == 0x20 ){ // MPPTからデータがきたとき, 00135 if( LED ){ led2 = !led2; } // led2を点滅させる処理. !はNOTの意味 00136 Vsol = ( (float)( (bufCAN.data[0]*100) + bufCAN.data[1]) ) / 10; 00137 Csol = ( (float)( (signed int)((signed char)bufCAN.data[2]*100) + (signed char)bufCAN.data[3] ) + ((signed char)bufCAN.data[6]*100) + (signed char)bufCAN.data[7] ) / 100; 00138 MPPTerror = bufCAN.data[4]; 00139 MPPTerror_2 = bufCAN.data[5]; 00140 Psol = Vsol * Csol; 00141 } 00142 else if( bufCAN.id == 0x10 ){ 00143 if( LED ){ led1 = !led1; } // led1を点滅させる(!はNOT) 00144 Vmot = ( (float)( (bufCAN.data[0]*100) + bufCAN.data[1]) ) / 10; // 15 43を1500 43にして足すと「1543」となり、÷10すると154.3 [V] 00145 Cmot = ( (float)( ((signed char)bufCAN.data[2]*100) + (signed char)bufCAN.data[3] ) ) / 100; 00146 // 5 54を500 54にして足すと5「554」となり、÷100すると5.54 [A] 00147 Pmot = Vmot * Cmot; 00148 speed = ( (float)( (bufCAN.data[4]*100) + bufCAN.data[5]) ) / 10; //「856」を85.6[km/h]にするため,÷10する 00149 duty = (signed char)bufCAN.data[6]; // アクセル開度は0~100表示のため,そのまま 00150 direc = (int)bufCAN.data[7]; 00151 } 00152 00153 else if( bufCAN.id == 0x30 ){ // BMSからデータが来たとき, 00154 if( LED ){ led3 = !led3; } // led3を点滅させる処理. !はNOTの意味 00155 Vbat = ( (float)( (bufCAN.data[0]*100) + bufCAN.data[1]) ) / 10; 00156 Cbat = ( (float)( (signed int)((signed char)bufCAN.data[2]*100) + (signed char)bufCAN.data[3] ) ) / 100; 00157 Pbat = Vbat * Cbat; 00158 VcelMin = ( (float)( (bufCAN.data[4]*100) + bufCAN.data[5] ) ) / 100; 00159 VcelMax = ( (float)( (bufCAN.data[6]*100) + bufCAN.data[7] ) ) / 100; 00160 VcelAve = Vbat / 27; // バッテリ電圧をセルの直列数(20200807現在、27直列)で割って平均電圧を算出する 00161 } 00162 00163 } 00164 } 00165 void printLCD(){ // LCDにデータを表示する関数 00166 ++cntLCD; // IM920カウンタをインクリメント 00167 if( cntLCD >= 255){ cntLCD = 0; } // 255以上でリセット 00168 00169 lcd1.locate(0, 0); // 4行LCDの1行目1番目に表示位置を指定し, 00170 lcd1.printf("%5.3fv %5.3fv %5.3fv", VcelMax, VcelAve, VcelMin); // バッテリセルの最大・平均・最小の電圧を表示 00171 lcd1.locate(0, 1); // 4行LCDの2行目1番目に表示位置を指定し, 00172 lcd1.printf("B:%5.1fv%5.1fA%5.0fw", Vbat, Cbat, Pbat); // バッテリ電圧・電流・電力を表示 00173 lcd1.locate(0, 2); // 4行LCDの3行目1番目に表示位置を指定し, 00174 lcd1.printf("M:%5.1fv%5.1fA d:%d", Vmot, Cmot, direc); // モータ電圧・電流, 進行方向を表示 00175 lcd1.locate(0, 3); // 4行LCDの4行目1番目に表示位置を指定し, 00176 if( MPPTerror || MPPTerror_2 ){ // MPPTからエラー信号を受け取っていたとき, 00177 if( MPPTerror ){ // MPPT1がエラーなら 00178 lcd1.printf("S:X%2.1fv%5.1fA", Vsol, Csol); // 先頭に"X"を入れて発電電圧・電流を表示 00179 }else{ // MPPT2がエラーなら 00180 lcd1.printf("S:XX%1.1fv%5.1fA", Vsol, Csol); // 先頭に"XX"を入れて発電電圧・電流を表示 00181 } 00182 }else{ // MPPTからエラー信号を受け取っていないとき 00183 lcd1.printf("S:%5.1fv%5.1fA", Vsol, Csol); // 発電電力・電流を表示 00184 } 00185 lcd1.locate(15, 3); // 4行LCDの4行目16番目に表示位置を指定し, 00186 lcd1.printf("USB:%c", oxMSC); // USBの接続状態を表示("o"か"x") 00187 lcd2.printf( 0, "%5.1fkm/h %5.1fv\r", speed, Vmot ); // デカ文字LCDの1行目1番目に表示(速度,システム電圧) 00188 lcd2.printf( 1, "%5.0fw %4.0fw %3d\r", Pmot, Psol, duty ); // デカ文字LCDの1行目2番目に表示(消費電力,発電電力,スロットル開度) 00189 pc.printf("LCD:%d\n",cntLCD); // 無線送信処理を行ったことをPC(teraterm)へ知らせる 00190 } 00191 00192 void printIM920(){ // 処理時間16ms~(MBED Timerで計測) 00193 ++cntIM920; // IM920カウンタをインクリメント 00194 if( cntIM920 >= 255 ){ cntIM920 = 0; } // 255以上でリセット 00195 im920.printf("TXDA%.1f,%.3f,%.3f,%.3f,%.1f,%.1f,%.1f,%.1f,%d,%d\r", 00196 Vmot, VcelMax, VcelAve, VcelMin, Cbat, Cmot, Csol, speed, duty, cntIM920); 00197 // TXDAに続く文字が無線送信される. データ間を","で区切る. 最後に"\r"必須 00198 pc.printf("IM920:%d\n",cntIM920); // 無線送信処理を行ったことをPC(teraterm)へ知らせる 00199 } 00200 00201 void printTera(){ 00202 ++cntTera; // Teratermカウンタをインクリメント 00203 if( cntTera >= 255){ cntTera = 0; } // 255以上でリセット 00204 //pc.printf("Tera:%d\n",cntTera); // 無線送信処理を行ったことをPC(teraterm)へ知らせる 00205 pc.printf("SP:%.1f DT:%d Vm:%.1f Im:%.2f Pm:%.1f Vs:%.1f Is: %.2f Ps:%.1f\n\r", speed, duty, Vmot, Cmot, Pmot, Vsol, Csol, Psol ); 00206 pc.printf("Vb:%.1f Cb:%.2f Pb:%.1f max:%.3f avg:%.3f min:%.3f\n\r", Vbat, Cbat, Pbat, VcelMax, VcelAve, VcelMin ); 00207 } 00208 00209 void init(){ // 初期化(初期設定)を行う関数 00210 pc.baud(115200); // pcとのシリアル通信ボーレートを115200bpsに設定(数字が大きい方が通信速度高い) 00211 pc.printf("main() start\n"); 00212 wait(3); // MBED電源投入から安定するまで3秒待つ(待たないと電源再投入後にUSBメモリの初期化・ファイル作成ができない) 00213 im920.baud(19200); // IM920とのシリアル通信ボーレートを19200bpsに設定(19200はIM920の初期値) 00214 initMSC(); // USBマスストレージクラス(USBメモリ)を初期化する関数を実行 00215 } 00216 00217 int main() { 00218 init(); // 初期化関数を実行 00219 00220 MPPTerror_2 = 0; 00221 Vmot=0; 00222 Cmot=0; 00223 Pbat=0; 00224 00225 tm1.start(); 00226 time0t5s.start(); //https://os.mbed.com/media/uploads/yueee_yt/text_h24csee.pdf(p.21) 00227 time0t2s.start(); //https://os.mbed.com/media/uploads/yueee_yt/text_h24csee.pdf(p.21) 00228 00229 can.attach(&readCAN, CAN::RxIrq); //CAN受信割り込みの設定 00230 while(1) { 00231 //readLights(); 00232 if( time0t5s.read() < 0.5 ){ 00233 //readCAN(); // CANデータを読み込む関数を実行 00234 if( time0t2s.read() >= 0.2 ){ 00235 time0t2s.reset(); // time0t2sをリスタートさせる 00236 printLCD(); // LCDの表示を更新する関数を実行 00237 printTera(); // Teratermに表示する関数を実行 00238 } 00239 } 00240 if( time0t5s.read() >= 0.5 ){ // 0.5秒毎に実行する処理 00241 time0t5s.reset(); // time0t5sをリスタートさせる 00242 if( LED ){ led4 = !led4; } // led4を点滅させる(!はNOT) 00243 pc.printf("TheTime: %d(us)\n", tm1.read_us()); // 処理時間確認用プログラム(1/2) 00244 tm1.reset(); // 処理時間確認用プログラム(2/2) 00245 saveMSC(); // MSCにデータを保存する関数を実行 00246 printIM920(); // IM920に無線送信させる関数を実行 00247 } 00248 00249 } 00250 }
Generated on Sat Jul 23 2022 17:17:01 by 1.7.2