/**************************************************************************** * メイン・プログラム:グラフ表示気圧・温湿度計テスト_3 * * GLCD:ノキア液晶5110 * 温湿度センサ:HDC1000 * 大気圧センサ:LPS25H * * 原典参考先: * @ トラ技2006年3月号 山本さんの記事 * A 「太田さんのホームページ」の記事 * * ※ Test_3:グラフ表示湿度計にしてみる。 * * Condition: * 8MHz Internal RC oscillator * Fcy=8MHz/2=4MHz, Tcy=250ns (電池駆動を想定し、最高速:16M/4で使用) * * CPU: PIC24FJ64GA002 * * 2017.1.11 N.Ishii *****************************************************************************/ #include "p24FJ64GA002.h" #include "stdio.h" #include "nokiaGlcdlib.h" #include "skI2C_PIC24F_lib.h" // I2C通信用ライブラリ #include "skHDC_PIC24F.h" // HDC1000用関数ライブラリ #include "skLPS25H_PIC24F.h" // LPS25H用関数ライブラリ #define HDC1000_ADRS 0x40 // HDC1000のI2Cアドレス #define LPS25H_ADRS 0x5D // LPS25HのI2Cアドレス(SDO/SAO is HIGH) /// コンフィギュレーション ビットの設定 _CONFIG1( JTAGEN_OFF // JTAGの使用:無効 & GCP_OFF // コードプロテクト:しない & GWRP_OFF // 書き込みプロテクト:しない & BKBUG_OFF // バックグラウンドデバッグ:無効 & COE_OFF // クリップオンエミュレーション:無効 & ICS_PGx1 // EMUC/EMUDをPCG1/PGD1と共用 & FWDTEN_OFF // WDT:無効 ) /// Fosc = FRC (8MHz) _CONFIG2( IESO_OFF // 2速度スタートアップ:無効 & FNOSC_FRC // 発振器の選択:FRCを選択する & FCKSM_CSDCMD // クロック切り替え・クロックモニタ:供に無効 // & OSCIOFNC_OFF // OSCOピン機能:OSCOまたはFosc/2の出力する & OSCIOFNC_ON // OSCOピン機能:RA3ポートとする 161118 & IOL1WAY_OFF // RPレジスタプロテクト:プロテクトしない & I2C1SEL_PRI // I2C1のピン選択:主ピンを使用する & POSCMOD_NONE // 主発振器:使用しない ) /// 漢字ドット・パターン・テーブル // 「湿度」の上半分 const unsigned char font_situdoH[] = { 0b00000000, 0b00010000, 0b01100000, 0b00000001, 0b00000110, 0b00000000, 0b00000000, 0b01111110, 0b01001010, 0b01001010, 0b01001010, 0b01001010, 0b01001010, 0b01111110, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b11111100, 0b00100100, 0b00100100, 0b00100100, 0b11111100, 0b10100100, 0b10100111, 0b10100100, 0b11111100, 0b00100100, 0b00100100, 0b00100100, 0b00000000, }; // 「湿度」の下半分 const unsigned char font_situdoL[] = { 0b00000000, 0b11000000, 0b00110000, 0b00001100, 0b01000011, 0b01000000, 0b01000001, 0b01111110, 0b01000000, 0b01111111, 0b01000000, 0b01111111, 0b01000000, 0b01110000, 0b01001100, 0b01000011, 0b00000000, 0b10000000, 0b01100000, 0b10011111, 0b10000000, 0b10000010, 0b01000010, 0b01000110, 0b00101010, 0b00010010, 0b00110010, 0b01001010, 0b01000110, 0b10000000, 0b10000000, 0b00000000, }; #define GRAPH_LOOP_MAX 60 #define HUMI_HIST_MAX 45 #define HUMI_GET_NONEXT (-1) #define HUMI_GET_EMPTY (-2) /// リングバッファ用 char humi_hist[HUMI_HIST_MAX]; // humi_hist[45]:湿度値データ履歴バッファで、グラフX軸間のドット数(45dot)分の要素数を持つ。 int humi_hist_head = 0; int humi_hist_full = 1; int graph_count = GRAPH_LOOP_MAX; unsigned char *pc; // "湿度"タイトル文字フォント格納用 // 浮動小数変数 double Humi ; // 湿度の値を保存する変数 double Temp ; // 温度の値を保存する変数 double Press ; // 大気圧の値を保存する変数 // 関数のプロトタイプ宣言 void PressureRead() ; void HDC_Read() ; //void print_temp(char Temperature, char temp_sign); void print_Yaxis(void); void print_graph(void); void add_humi(char); int get_humi(int, char *); void main(void) { int ans1,ans2 ; char buf[12] ; //// I/O設定 AD1PCFG = 0xFFFF; // A/D Digi 選択:全デジタルI/Oに設定 CLKDIV = 0x0000; // System Clock devider 1:1 /// Setup PORT In/Out TRISB = 0x000F; // RB0,1:プロット間隔設定ピン入力、他は出力 // RB2 is SDA2 (Hi), RB3 is SCL2 (Hi) /// Set Pull Up CNPU1 = 0x0030; // Pull Up Port is RB0(ピン1), RB1(ピン2) /// Initialize I2C2 I2C2BRG = 0x27; // (Fcy/Fscl-FCY/10E6)-1=(4E6/100E3-4E6/10E6)-1=38.6=39 I2C2CON = 0x8000; // Enable I2C2 TRISAbits.TRISA3= 0; // 赤LED:デバッグ用 TRISAbits.TRISA4= 0; // 緑LED:デバッグ用 LATAbits.LATA3 = 1; // 赤LED消灯 LATAbits.LATA4 = 1; // 緑LED消灯 /// 液晶表示器の初期化と開始メッセージ表示 LCD_init(); LCD_locate(0,0); // 原点(左上)に設定 LCD_clear(LCD_WIDTH * LCD_BANKS); // 全画面クリア LCD_ROMstr("Start Test !!"); // 開始メッセージ表示 delay_ms(3000); // 3秒後に開始 LCD_clear(LCD_WIDTH * LCD_BANKS); // 全画面クリア LCD_locate(0,0); /// 両センサの初期化を行う ans1 = HDC_Init(HDC1000_ID,HDC1000_ADRS) ; // 湿度センサーの初期化を行う ans2 = PressureInit(LPS25H,LPS25H_ADRS) ; // 大気圧センサーの初期化を行う if ((ans1 == 0) && (ans2 == 0)) { LCD_ROMstr("Init OK") ; delay_ms(1000) ; // データレートが1Hzなので1秒後から開始する } else { LCD_ROMstr("Init NG") ; while(1) ; // プログラム終了 } while(1) { LCD_clear(LCD_WIDTH * LCD_BANKS); // 全画面クリア LCD_locate(0,0); /// タイトル:"湿度"を表示 LCD_locate(0, 0); pc = (unsigned char *)font_situdoH; LCD_set_data(pc, 32); LCD_locate(0, 1); pc = (unsigned char *)font_situdoL; LCD_set_data(pc, 32); /// 温湿度センサーから湿度・温度値を読出し、液晶表示する HDC_Read() ; sprintf((char *)buf,"%.2f ",Humi) ; LCD_locate(0,3) ; LCD_ROMstr(buf) ; // 湿度(%)の表示 LCD_locate(24,4) ; LCD_char('%') ; /* sprintf((char *)buf,"%.2f",Temp) ; LCD_locate(0,3) ; LCD_ROMstr(buf) ; // 温度(℃)の表示 LCD_locate(18,4) ; LCD_ROMstr("゚C") ; /// 気圧センサーから、気圧値を読出し、液晶表示する。 PressureRead() ; // 結果は、Press(フロート型)に格納されている sprintf((char *)buf,"%.2f ",Press) ; buf[8] = 'h' ; buf[9] = 'P' ; buf[10] = 'a' ; LCD_locate(0,4) ; LCD_ROMstr(buf) ; // 大気圧(hPa)の表示 */ //// 1分ごとの湿度を保存する(リングバッファによる湿度履歴の管理処理) ++graph_count; if (graph_count >= GRAPH_LOOP_MAX) { graph_count = 0; /// 湿度データをリングバッファに格納 add_humi((char)Humi); } print_Yaxis(); // グラフのY軸を表示 print_graph(); // 湿度値履歴グラフを表示 delay_ms(1000) ; } } /******************************************************************************* * ans = HDC_Read() * * 湿度・温度を読込む処理 * * 読み込まれた湿度(%)はHumi変数に、温度値(℃)はTemp変数に其々格納されます。 * * この処理は約15ms程時間が掛かります。 * * ans : 0=正常 1=異常(相手からACKが返ってこない) * * ============================================================================ * * * * PIC24F用に改修 * * 2017/1/2 N.Ishii * *******************************************************************************/ void HDC_Read() { union { unsigned int i ; unsigned char c[2] ; } data ; // 湿度データを受信する HDC_Receive(HUMI_ADRS,(unsigned char *)data.c) ; Humi = (double)data.i / 65536.0 ; Humi = Humi * 100.0 ; // 温度データを受信する HDC_Receive(TEMP_ADRS,(unsigned char *)data.c) ; Temp = (double)data.i / 65536.0 ; Temp = (Temp * 165.0) - 40.0 ; } /******************************************************************************* * ans = PressureRead() * * 圧力・温度を読込み気圧値を計算する処理 * * 計算された気圧値(hPa)はPress変数に、温度値(℃)はTemp変数に其々格納されます。* * ans : 0=正常 1=異常(相手からACKが返ってこない) * * ============================================================================ * * * * PIC24F用に改修 * * 2017/1/2 N.Ishii(今回は未使用:170111) * *******************************************************************************/ void PressureRead() { unsigned char data[6] ; // 圧力と温度データを受信する(このデータはデバイス内部で移動平均化されています) PressureReceive(PRESS_OUT_ADRS,&data[0],3) ; // 圧力値 PressureReceive(TEMP_OUT_ADRS,&data[3],2) ; // 温度値 // 大気圧の計算を行う Press = ((unsigned long)data[2]<<16) + ((unsigned long)data[1]<<8) + data[0] ; Press = Press / 4096.0 ; // hPa /* // 温度の計算を行う→ 温度は、HDC1000の方で行うので、コメントアウト Temp = (int)(1 + ~((unsigned int)data[4]<<8 | data[3])) * -1 ; Temp = 42.5 + (Temp / 480.0) ;// ℃ */ } /************************** * グラフのY軸表示 ***************************/ void print_Yaxis(void) { int x, y; unsigned char c; c = 0xff; x = LCD_MAX_X - HUMI_HIST_MAX - 2; /// 縦線を表示 for (y = 0; y < 6; y++) { LCD_locate(x, y); LCD_set_data(&c, 1); LCD_locate(x + HUMI_HIST_MAX + 1, y); LCD_set_data(&c, 1); } /// 20%ごとの刻みを表示 for (y = 0; y <= LCD_MAX_Y; y += 10) { draw_point(x-1, y); draw_point(x + HUMI_HIST_MAX + 2, y); } } /*********************************** * 湿度値履歴グラフを表示 ************************************/ void print_graph() { char humi_hist_val; int humi, p, col; p = -1; col = 0; while ((p = get_humi(p, &humi_hist_val)) != HUMI_GET_EMPTY) { humi = (int)humi_hist_val; draw_point(LCD_MAX_X - col - 2, humi/2); // y座標は、2%/dot分解能なので、1/2する。 if (p < 0) break; ++col; } } //// 以下は、リングバッファ用関数------------------------------------------------------------------------- /**************************************************** * 湿度データをリングバッファに格納 *****************************************************/ void add_humi(char h) { humi_hist[humi_hist_head] = h; // 湿度データ履歴バッファ(humi_hist[0]から順)に、湿度値を格納 ++humi_hist_head; // バッファアドレスをインクリメント if (humi_hist_head >= HUMI_HIST_MAX) { // humi_hist[44]まで(つまり、HUMI_HIST_MAX=45)格納したら humi_hist_full = 1; // fullフラグをセットし、 humi_hist_head = 0; // headフラグをリセット } } /**************************************************** * リングバッファから湿度データを取得 *****************************************************/ int get_humi(int p, char *h) { int i; if (!humi_hist_full && (humi_hist_head == 0)) { *h = 0; return HUMI_GET_EMPTY; } if (p < 0) { i = humi_hist_head; } else { i = p; } --i; if (i < 0) { i = HUMI_HIST_MAX - 1; } *h = humi_hist[i]; if (humi_hist_full) { if (i == humi_hist_head) return HUMI_GET_NONEXT; else return i; } else { if (i == 0) return HUMI_GET_NONEXT; else return i; } }