/****************************************************************************************** * メイン・プログラム:グラフ表示気圧・温湿度計テスト_4 * * GLCD:ノキア液晶5110 * 温湿度センサ:HDC1000 * 大気圧センサ:LPS25H * * 原典参考先: * @ トラ技2006年3月号 山本さんの記事 * A 「太田さんのホームページ」の記事 * * ※ Test_4:グラフ表示気圧計にしてみる。 *       プロット範囲(Y軸:48dot)は、983〜1030hPaとし、分解能は、1hPa/dotとした。 * * Condition: * 8MHz Internal RC oscillator * Fcy=8MHz/2=4MHz, Tcy=250ns (電池駆動を想定し、最高速:16M/4で使用) * * CPU: PIC24FJ64GA002 * * 2017.1.11-2 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 // 主発振器:使用しない ) /// 漢字ドット・パターン・テーブル // 「気圧」の上半分 unsigned char const font_kiatsuH[] = { 0x20,0x90,0x88,0xAE,0xAA,0xA8,0xA8,0xA8,0xA8,0xA8,0xA8,0x8C,0x08,0x00,0x00,0x00, 0x00,0x00,0xFC,0x04,0x04,0x04,0x04,0x04,0xF4,0x14,0x04,0x84,0x04,0x06,0x04,0x00 }; // 「気圧」の下半分 unsigned char const font_kiatsuL[] = { 0x00,0x80,0x84,0x44,0x48,0x28,0x18,0x26,0x42,0x00,0x00,0x1F,0x60,0xC0,0xB0,0x00, 0x80,0x60,0x1F,0x40,0x41,0x41,0x41,0x41,0x7F,0x41,0x41,0x41,0x41,0x60,0x40,0x00 }; #define GRAPH_LOOP_MAX 60 #define PRES_HIST_MAX 45 #define PRES_GET_NONEXT (-1) #define PRES_GET_EMPTY (-2) /// リングバッファ用 int pres_hist[PRES_HIST_MAX]; // pres_hist[45]:気圧値データ履歴バッファで、グラフX軸間のドット数(45dot)分の要素数を持つ。 int pres_hist_head = 0; int pres_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_pres(int); int get_pres(int, int *); 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_kiatsuH; LCD_set_data(pc, 32); LCD_locate(0, 1); pc = (unsigned char *)font_kiatsuL; LCD_set_data(pc, 32); /// 気圧センサーから、気圧値を読出し、液晶表示する。 PressureRead() ; // 結果は、Press(フロート型)に格納されている sprintf((char *)buf,"%.1f ",Press) ; // 小数点以下1桁で表示のつもり LCD_locate(0,3) ; LCD_ROMstr(buf) ; // 気圧(hPa)の表示 LCD_locate(18,4) ; LCD_ROMstr("hPa") ; //// 1分ごとの気圧を保存する(リングバッファによる気圧履歴の管理処理) ++graph_count; if (graph_count >= GRAPH_LOOP_MAX) { graph_count = 0; /// 気圧データをリングバッファに格納 add_pres((int)Press); } 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 * *******************************************************************************/ 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 - PRES_HIST_MAX - 2; /// 縦線を表示 for (y = 0; y < 6; y++) { LCD_locate(x, y); LCD_set_data(&c, 1); LCD_locate(x + PRES_HIST_MAX + 1, y); LCD_set_data(&c, 1); } /// 10hPaごとの刻みを表示 for (y = 0; y <= LCD_MAX_Y; y += 10) { draw_point(x-1, y); draw_point(x + PRES_HIST_MAX + 2, y); } } /*********************************** * 気圧値履歴グラフを表示 ************************************/ void print_graph() { int pres_hist_val; int pres, p, col; p = -1; col = 0; while ((p = get_pres(p, &pres_hist_val)) != PRES_GET_EMPTY) { pres = pres_hist_val; draw_point(LCD_MAX_X - col - 2, pres-983); // y座標目盛りの最小は、983hPaなので、-983する。 if (p < 0) break; ++col; } } //// 以下は、リングバッファ用関数------------------------------------------------------------------------- /**************************************************** * 気圧データをリングバッファに格納 *****************************************************/ void add_pres(int pr) { pres_hist[pres_hist_head] = pr; // 気圧データ履歴バッファ(pres_hist[0]から順)に、気圧値を格納 ++pres_hist_head; // バッファアドレスをインクリメント if (pres_hist_head >= PRES_HIST_MAX) { // pres_hist[44]まで(つまり、PRES_HIST_MAX=45)格納したら pres_hist_full = 1; // fullフラグをセットし、 pres_hist_head = 0; // headフラグをリセット } } /**************************************************** * リングバッファから気圧データを取得 *****************************************************/ int get_pres(int p, int *pr) { int i; if (!pres_hist_full && (pres_hist_head == 0)) { *pr = 0; return PRES_GET_EMPTY; } if (p < 0) { i = pres_hist_head; } else { i = p; } --i; if (i < 0) { i = PRES_HIST_MAX - 1; } *pr = pres_hist[i]; if (pres_hist_full) { if (i == pres_hist_head) return PRES_GET_NONEXT; else return i; } else { if (i == 0) return PRES_GET_NONEXT; else return i; } }