/****************************************/ /* LEDランプ寿命テストプログラム */ /****************************************/ // Arduino 1.6.5でコンパイル,確認 // 照度センサーBH1603のアナログ出力をA/D変換 // 毎日0時に照度を内蔵EEPROMに記録 最大500日分 // A/D値をEEPROM(1kバイト)に記録 // 2018-02-15 開始 // 17 とりあえず // ピン割り当て // PD0 RXD in - (pull up) // PD1 TXD out データ送信 // PD2 IO2 out - // PD3 IO3 out - // PD4 IO4 out - // PD5 IO5 out - // PD6 IO6 in 測定開始/停止スイッチ // PD7 IO7 in データ送信スイッチ // PB0 IO8 out LCD RS // PB1 IO9 out LCD E // PB2 IO10 out LCD D4 // PB3 IO11 out LCD D5 // PB4 IO12 out LCD D6 // PB5 IO13 out LCD D7 // PC0 AD0 in 照度センサA/D入力 // PC1 AD1 out - // PC2 AD2 out - // PC3 AD3 out - // PC4 AD4 out - // PC5 AD5 out - /***** ライブラリ ****/ #include #include #include #include #include #include "wiring_private.h" // sbi,cbi命令用 // http://www.arduino.cc/en/Tutorial/LiquidCrystal #include // 8文字×2行液晶を4bitモードで使用 /***** タイトル *****/ const char pgm_ttl1[] PROGMEM = "LED Lamp tester "; const char pgm_ttl2[] PROGMEM = " 2018-02-17" ; // 0123456789012345 /***** 液晶ピン指定 *****/ #define LCD_RS 8 // デジタルピン指定 #define LCD_E 9 // 4bitモードで使用 #define LCD_D4 10 #define LCD_D5 11 #define LCD_D6 12 #define LCD_D7 13 // initialize the library with the numbers of the interface pins LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); /***** 配列のデータ数を返すマクロ *****/ #define DIMSIZ(a) (sizeof(a)/sizeof(*a)) typedef unsigned long ulong; // unsigned longの略 /***** ピン指定 *****/ // SW入力 on,offチェック(onで1) #define INP_SWON ((~PIND) & (1 << PORTD6)) // 測定開始スイッチ #define INP_SWTX ((~PIND) & (1 << PORTD7)) // 送信スイッチ // SWコード (0でオフ) #define SW_ON 1 // PD6 測定開始/停止 #define SW_RST 2 // 測定データ初期化して待機 (長押し) #define SW_TX 3 // PD7 データ送信 #define SW_TIM 4 // 時刻設定(長押し) // テストピン #define PD2_H (sbi(PORTD,PORTD2)) // (!!!) PD2 4pin #define PD2_L (cbi(PORTD,PORTD2)) // #define PD3_H (sbi(PORTD,PORTD3)) // (!!!) PD3 5pin #define PD3_L (cbi(PORTD,PORTD3)) // #define PD4_H (sbi(PORTD,PORTD4)) // (!!!) PD4 6pin #define PD4_L (cbi(PORTD,PORTD4)) // #define PD5_H (sbi(PORTD,PORTD5)) // (!!!) PD5 11pin #define PD5_L (cbi(PORTD,PORTD5)) // /***** データ指定 *****/ #define LOG_SIZE 500 // 500日分の照度変化を記録 // ATmeg328のEEPROMは1024バイト // 照度データは2バイト /***** EEPROMデータ *****/ // ATmega328は1024バイト // 参考:https://projectgus.com/2010/07/eeprom-access-with-arduino/ // http://forum.arduino.cc/index.php?topic=128816.0 #define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block(dst_p, (void *)offsetof(__eeprom_data, eeprom_field), MIN(dst_size, sizeof((__eeprom_data*)0)->eeprom_field)) #define eeprom_read(dst, eeprom_field) eeprom_read_to(&dst, eeprom_field, sizeof(dst)) #define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block(src_p, (void *)offsetof(__eeprom_data, eeprom_field), MIN(src_size, sizeof((__eeprom_data*)0)->eeprom_field)) #define eeprom_write(src, eeprom_field) { typeof(src) x = src; eeprom_write_from(&x, eeprom_field, sizeof(x)); } #define MIN(x,y) ( x > y ? y : x ) // EEPROM保存データ struct __eeprom_data { word ep_mgcnbr; // 0 magic number 0x1234 byte ep_meson; // 2 測定中フラグ word ep_logcnt; // 3 LOGデータ数 0なら記録無し word ep_pwrdown; // 5 記録中のリセット起動回数 word ep_log[LOG_SIZE]; // 7 照度ログデータ }; #define MGCNBR 0x1234 // EEPROM初期化のmagic number // 注:eeprom_write(d, hoge[n])という書式は使えない // だもんで、hoge[n]のアドレスを計算してEEPROM.put(adrs, d)を用いる /***** ログデータアドレスの計算 *****/ // n:データ番号(ep_log[n]) // ret : EEPROMのアドレス word epadrslog(word n) { word p; p = offsetof(__eeprom_data, ep_log); // ep_logの先頭 p += sizeof(*((__eeprom_data*)0)->ep_log) * n; // [n]の位置 return p; } /***** 測定データ *****/ byte f_meson; // 測定on/off byte f_logrec; // 24時間経過で記録開始フラグ byte f_tmstop; // 計時停止指令 word log_cnt; // 記録数 0~LOG_SIZE byte pwr_down; // 測定中の電源投入回数 // タイマー byte tm_sec; // 秒 0~59 byte tm_min; // 分 0~59 byte tm_hour; // 時 0~23 byte f_speedup; // TX SW 押しながら起動だと測定タイミング加速 byte f_tmdisp; // 時間表示要求フラグ /******************************/ /* スイッチ入力 */ /******************************/ // SWスキャンデータ SWは2コ // PD6 SW_ON : 測定開始/停止SW // SW_RST : 長押しで初期化開始 // PD7 SW_TX : データ送信 // SW_TIM : 長押しで時刻設定 // bit0,1にデータが入る byte sw_chk[10]; // onエッジチェックデータ byte sw_inp; // SWのon/off状態 byte sw_on; // onエッジ 1でon // 長押しスイッチの有無 const byte sw_longp PROGMEM = 0b00000011; // 長押しSW位置 // |+--- PD6 // +---- PD7 byte sw_tmlongp[2]; // 長押し検出タイマー // 10mSでダウンカウント byte sw_flongp; // 長押し検出フラグ // ビット位置が1で処理中 // スイッチ コード データ struct st_swcode{ const byte sht PROGMEM; // ちょん押し const byte lng PROGMEM; // 長押し }; const st_swcode sw_code[] PROGMEM = { SW_ON, SW_RST, // 0: 測定開始終了  初期化 SW_TX, SW_TIM, // 1: データ送信 時刻設定 }; /***** スイッチ入力 *****/ // PD6とPD7 onでL byte swinp(void) { byte d = 0; // SW on/off if(INP_SWON) d |= 0b00000001; // 0:測定開始/停止スイッチ if(INP_SWTX) d |= 0b00000010; // 1:データ送信スイッチ return d; } /***** スイッチ入力スキャン *****/ // 1mSサイクルで10回チェック, onエッジを見つける // タイマー割り込み内で処理 void swscan(void) { static byte p = 0; // 最新入力書き込み位置 static byte t = 0; // 10mSカウンタ byte i; byte m, d0, d1; sw_chk[p] = swinp(); // 最新SWデータ Hでon d0 = 0x00; // Lチェック d1 = 0xFF; // Hチェック (1bit) for(i = 0; i < DIMSIZ(sw_chk); i++){ // H,L安定確認 d0 |= sw_chk[i]; d1 &= sw_chk[i]; } m = (~d0) | d1; // 1のところが安定データ d0 = sw_inp; // 1ms前の状態 sw_inp = (d0 & (~m)) | (sw_chk[p] & m); // 確定 sw_on |= (~d0) & sw_inp; // onエッジをチェック p++; // 次書き込み位置 if(p >= DIMSIZ(sw_chk)) p = 0; // ポインタ一周 // 10msカウント t++; // 1ms +1 if(t >= 10){ // 10mS ? t = 0; for(i = 0; i < DIMSIZ(sw_tmlongp); i++){ if(sw_tmlongp[i]) sw_tmlongp[i]--; // 長押し検出タイマー } } } /***** SW 長押しチェック *****/ // ちょん押しと長押し(1.5秒)を検出 // n : スイッチビット番号 0~7 // ret : 0=onスイッチ無し 1~SWコード byte swlongp(byte n) { byte r = 0; // リターンコード byte m; m = 1 << n; // ビット位置 if((pgm_read_byte(&sw_longp) & m) != 0){ // 長押しSW ? if(sw_flongp & m){ // 長押し処理中? if(sw_tmlongp[n] == 0){ // 長押しタイマー=0? sw_flongp &= ~m; // 処理中フラグクリア r = pgm_read_byte(&sw_code[n].lng); // 長押しSW } else{ // タイマー計時中 if(!(sw_inp & m)){ // offしたらちょん押し sw_flongp &= ~m; // 処理中フラグクリア r = pgm_read_byte(&sw_code[n].sht); // 短押しSW } } } else{ // 初めてのonをチェック if(sw_on & m){ sw_on &= ~m; // onフラグクリア sw_tmlongp[n] = 150; // 長押しタイマー 1.5秒 sw_flongp |= m; // 処理中フラグon } } } return r; } /***** SW on チェック *****/ // オフなら0、オンならswコードを返す // sw_onのbit 1,0をチェック byte swonchk(void) { byte m, i; byte r = 0; // 0:SW onなし for(i = 0; i < 2 ;i++){ // SWは2つ r = swlongp(i); // 長押しチェック if(r) break; // 有効SWあり m = 1 << i; // bit0から if(sw_on & m){ // SW on? sw_on &= ~m; r = pgm_read_byte(&sw_code[i].sht); // 短押しSW break; } } return r; // SWコード } /******************************/ /* 1ms タイマー割り込み */ /******************************/ /***** タイマーデータ *****/ volatile byte tm_1ms; // 1msタイマー volatile byte tm_10ms; // 計時用ダウンカウント volatile word tm_1scnt; // 1秒カウンタ volatile byte f_1sec; // 1秒確定フラグ volatile byte f_blink; // 点滅表示タイミングフラグ // 0.5秒に1回オン volatile byte f_blank; // 点滅表示 表示/ブランクフラグ // 1:ブランクに /***** 割り込み実行 *****/ void int1ms(void) { static byte cnt10 = 0; static byte cntbl = 0; PD4_H; // (!!!) 6pin if(tm_1ms) tm_1ms--; // 1msダウンカウント // スイッチ入力スキャン swscan(); // SW onエッジを見つける // 10msタイマー cnt10++; if(cnt10 >= 10){ cnt10 = 0; if(tm_10ms) tm_10ms--; // 10mS ダウンカウント // 点滅処理 cntbl++; // 点滅フラグ+10ms if(f_blank){ // ブランク中 if(cntbl >= 20){ // 0.2秒 f_blink = 1; // 表示タイミング f_blank = 0; // 表示に cntbl = 0; } } else{ if(cntbl >= 80){ // 0.8秒 f_blink = 1; // 表示タイミング f_blank = 1; // ブランクに cntbl = 0; } } } // 1secタイマー tm_1scnt++; if(tm_1scnt >= 1000){ // 1秒? tm_1scnt = 0; f_1sec = 1; } // 内蔵A/D開始 ADCSRA |= (1 << ADSC); // A/D変換開始 PD4_L; // (!!!) 6pin } /******************************/ /* 内蔵A/D処理 */ /******************************/ /**** A/D データ *****/ // A/D変換チャンネル (ADMUX) const byte ad_mpx[] PROGMEM ={ 0b11000000, // ch 0 照度センサー }; // ||| ++++---- MPX // ||+--------- ADLAR // ++---------- 内部1.1V AREF接続 // AD ch0 : 照度センサー volatile word ad_avr[1]; // A/D変換データ 0~1023 // 平均処理された結果 volatile ulong ad_add[1]; // A/D平均処理用加算データ volatile byte f_adok; // A/D変換完了フラグ // 割り込みでセット // 10bit A/D値 割り込み禁止してad_avrをコピー word ad_lux; // A/D ch0 照度データ // loopで読み出したA/D値 0~1023 byte f_addisp; // A/Dデータ確定フラグ /***** A/D割り込み処理 *****/ // タイマー割り込みでA/D変換開始 // 256回(256ms)で平均値算出 ISR(ADC_vect) { word d; static byte ch = 0; // A/D変換チャンネル static word cnt = 0; // A/D変換平均回数 PD5_H; // (!!!) 11pin d = (word)ADCL; // d |= (ADCH & 0x03) << 8; // 符号なしで 0~3FF // 測定値 ad_add[ch] += (ulong)d; // 平均用に加算 // 次変換チャンネル ch++; // ch0だけ if(ch >= 1){ ch = 0; // 0に戻す cnt++; // 平均加算回数 if(cnt >= 256){ // 256回? cnt = 0; ad_avr[0] = word(ad_add[0] / 256L); // 平均 ad_add[0] = 0; // 次加算データクリア f_adok = 1; // 変換完了 } } ADMUX = pgm_read_byte(&ad_mpx[ch]); // 次ch PD5_L; // (!!!) 11pin } /**************************/ /* 液晶表示 */ /**************************/ /***** キャラジェネ設定 *****/ #define CG_OHM 8 // Ω記号 #define CG_DO 9 // ℃記号 /***** キャラジェネ設定 *****/ void lcdcgset(void) { static byte cg8[] = { // Ω 0b01110, // 0 0b10001, // 1 0b10001, // 2 0b10001, // 3 0b01010, // 4 0b01010, // 5 0b11011, // 6 0b00000, // 7 }; static byte cg9[] = { // ℃ 0b11000, // 0 0b11000, // 1 0b00000, // 2 0b01111, // 3 0b10000, // 4 0b10000, // 5 0b01111, // 6 0b00000, // 7 }; lcd.createChar(CG_OHM, cg8); lcd.createChar(CG_DO, cg9); } /***** 書式付液晶表示 *****/ void lcdprintf(const char *s, ...) { va_list vp; char bff[40]; // バッファを確保 va_start(vp,s); vsprintf(bff,s,vp); lcd.print(bff); va_end(vp); } /***** 1行消去 *****/ // n : 0,1 行 void lcdclrline(byte n) { byte i; lcd.setCursor(0, n); for(i = 0; i < 16; i++){ lcd.write(' '); } } /***** メッセージ出力 *****/ void lcdputs(char *s) { char c; while(1){ c = *s; if(c == '\x0') break; lcd.write(c); s++; } } /***** メッセージ出力 *****/ void lcdputs_P(PGM_P s) { char c; while(1){ c = pgm_read_byte(s); if(c == '\x0') break; lcd.write(c); s++; } } /**************************/ /* シリアル入出力 */ /**************************/ /***** 書式付シリアル出力 *****/ void txprintf(const char *s, ...) { va_list vp; char bff[40]; // バッファを確保 va_start(vp,s); vsprintf(bff,s,vp); Serial.print(bff); va_end(vp); } /***** メッセージ出力 *****/ void txputs_P(PGM_P s) { char c; while(1){ c = pgm_read_byte(s); if(c == '\x0') break; Serial.write(c); s++; } } /******************************/ /* セットアップ */ /******************************/ /***** セットアップ *****/ // ATmega328Pのレジスタを直接制御 void setup() { // I/Oイニシャル PORTB = 0b00000000; // out data, pull up DDRB = 0b00111111; // portI/O // |||||+---- PB0 IO8 out LCD RS // ||||+----- PB1 IO9 out LCD E // |||+------ PB2 IO10 out LCD D4 // ||+------- PB3 IO11 out LCD D5 // |+-------- PB4 IO12 out LCD D6 // +--------- PB5 IO13 out LCD D7 PORTC = 0b00000000; // out data, pull up DDRC = 0b00111110; // portI/O // |||||+---- PC0 AD0 in 照度センサーA/D入力 // ||||+----- PC1 AD1 out - // |||+------ PC2 AD2 out - // ||+------- PC3 AD3 out - // |+-------- PC4 AD4 out - // +--------- PC5 AD5 out - PORTD = 0b11000011; // out data, pull up DDRD = 0b00111110; // portI/O // |||||||+---- PD0 RXD in // ||||||+----- PD1 TXD out データ送信 // |||||+------ PD2 IO2 out - // ||||+------- PD3 IO3 out - // |||+-------- PD4 IO4 out - // ||+--------- PD5 IO5 out - // |+---------- PD6 IO6 in 測定開始/停止スイッチ // +----------- PD7 IO7 in データ送信スイッチ // A/D割り込み ADMUX = 0b11000000; // 内蔵A/D // ||| ++++---- ch0 照度センサー入力 // ||+--------- ADLAR // ++---------- 内部1.1V AREF接続 ADCSRA |= (1 << ADEN); // A/D許可 ADCSRA |= (1 << ADIE); // A/D割り込み有効 // シリアル Serial.begin(9600); // シリアル通信 // タイマー割り込み MsTimer2::set(1, int1ms); // 1ms割り込み MsTimer2::start(); // 割り込み処理開始 // LCD lcd.begin(16, 2); // 16文字×2行 lcdcgset(); // キャラジェネ設定 } /***** 照度A/D値表示 *****/ void dispad(void) { lcd.setCursor(0, 1); lcdprintf("%4d", ad_lux); // 10bit A/D値 } /***** 時間表示 *****/ // 23:59:59でタイマーを表示 void disptime(void) { lcd.setCursor(8, 0); lcdprintf("%02d:%02d:%02d", tm_hour, tm_min, tm_sec); } /***** 記録データ数表示 *****/ // "xxxxday"で日数として表示 void dispday(void) { lcd.setCursor(0, 0); lcdprintf("%4dday", log_cnt); } /***** 測定中の電源断回数を表示 *****/ void disppwrdown(void) { lcd.setCursor(12, 1); if(pwr_down == 0) lcd.print(F(" ")); else lcdprintf("[%2d]", pwr_down); } /*****************************************/ /* 制御実行処理 */ /*****************************************/ /***** 制御実行区分 *****/ byte r_exc; // 実行区分 #define R_STBY 3 // スタンバイ #define R_TX 4 // データ送信 #define R_TMSET 5 // タイマーセット // 照度データ送信カウンタ word log_tx; // log_cntの数だけ出力 // 時刻合わせ用データ byte tms_pos; // 0:時,1:分,2:秒 struct st_tms{ byte *tmd; // タイマーデータ byte lim; // +1するリミット値 byte cur; // 表示カーソル位置 }; st_tms tms_data[] = { &tm_hour, 24, 8, // 時 &tm_min, 60, 11, // 分 &tm_sec, 60, 14, // 秒 }; /***** タイトル表示 *****/ // 装置名,バージョン表示 void rttl1(void) { word d1, d2, d3; byte b1; // EEPROMチェック eeprom_read(d1, ep_mgcnbr); // ダミーをリード eeprom_read(d2, ep_logcnt); // 測定データ数 eeprom_read(d3, ep_pwrdown); // 測定中の電源投入回数 eeprom_read(b1, ep_meson); // 測定中フラグ txprintf("%04X %4d\r\n", d1, d2); if((d1 != MGCNBR) || // チェックデータ以外は初期化 (d2 > LOG_SIZE) || // データ数異常 (d3 > 99) || // 測定中電源投入回数超え (b1 > 2)){ // フラグは0,1 d1 = MGCNBR; eeprom_write(d1, ep_mgcnbr); // チェックデータ eeprom_write(0, ep_logcnt); // 記録数 eeprom_write(0, ep_pwrdown); // 測定中の電源投入 eeprom_write(0, ep_meson); // 測定on/off } else{ // OK eeprom_read(log_cnt, ep_logcnt); // 記録数 eeprom_read(pwr_down, ep_pwrdown); // 測定中の電源投入 eeprom_read(f_meson, ep_meson); // 測定on/off } // 測定中のリセット起動をチェック 液晶右下に回数を表示 if(f_meson){ // 測定していた if(pwr_down < 99){ // 0~99回 pwr_down++; eeprom_write(pwr_down, ep_pwrdown); // 測定中の電源投入回数 } } // タイトル lcd.setCursor(0, 0); // タイトル lcdputs_P(pgm_ttl1); lcd.setCursor(0, 1); lcdputs_P(pgm_ttl2); tm_10ms = 200; // 2.0秒 r_exc++; // 次exc } /***** タイトル表示 #2 *****/ // TX SW 押しながら起動すると測定タイミングを加速 void rttl2(void) { if(tm_10ms == 0){ lcd.clear(); if(INP_SWTX){ // TX SW 押しながら起動 f_speedup = 1; // 測定タイミング加速 lcd.setCursor(0, 0); lcd.print(F("Speed up!")); tm_10ms = 200; // 2.0秒 } r_exc++; // 次exc } } /***** タイトル表示 #3 *****/ void rttl3(void) { if(tm_10ms == 0){ lcd.clear(); tm_sec = 0; // タイマークリア tm_1scnt = 0; // 1秒カウンタクリア f_1sec = 0; sw_on = 0; // SW入力onフラグクリア r_exc++; // 次exc } } /***** スタンバイ *****/ // 記録するタイミングと表示,スイッチのチェック void rstby(void) { // 24時間経過で照度を記録 if(f_logrec){ // 記録指令 f_logrec = 0; if((f_meson) && // 測定中 (log_cnt < LOG_SIZE)){ // バッファサイズok EEPROM.put(epadrslog(log_cnt), ad_lux); // 照度書き込み log_cnt++; // 記録数+1 eeprom_write(log_cnt, ep_logcnt); // EEPROMに保持 f_tmdisp = 1; // 時間,照度表示を f_addisp = 1; } } // 表示実行 if(f_addisp){ // A/Dデータあり f_addisp = 0; dispad(); // 照度A/D値表示 } if(f_tmdisp){ // 時間表示? f_tmdisp = 0; dispday(); // LOGデータ数表示 disptime(); // 経過時間表示 disppwrdown(); // 測定中の電源断回数を表示 lcd.setCursor(5, 1); // スタンバイ/測定中表示 if(f_meson == 0) lcd.print(F("Stnby")); else lcd.print(F("-LOG-")); } // スイッチ チェック switch(swonchk()){ case SW_ON: // 測定開始/中断 f_meson ^= 1; // 測定 on/off eeprom_write(f_meson, ep_meson); // EEPROMに状態を f_tmdisp = 1; // 表示指令 break; case SW_RST: // 長押しで新測定の準備 log_cnt = 0; // 記録データ数クリア pwr_down = 0; // 停電回数クリア f_logrec = 0; // 記録指令は0時を待つ f_meson = 0; // 測定は待機状態 f_tmdisp = 1; // 時間表示 eeprom_write(f_meson, ep_meson); // 測定onをEEPROMに eeprom_write(log_cnt, ep_logcnt); // 記録数 eeprom_write(pwr_down, ep_pwrdown); // 測定中の電源投入 break; case SW_TX: // データ送信 if(log_cnt){ // 照度データあり? lcd.clear(); lcd.setCursor(0, 0); lcd.print(F("LOG data TX")); Serial.print(F("#Day A/D\r\n")); log_tx = 0; // 最初から r_exc = R_TX; // データ送信へ } break; case SW_TIM: // 時刻設定へ(送信SW長押し) lcd.clear(); lcd.setCursor(0, 0); lcd.print(F("TM set")); f_tmstop = 1; // 計時停止 f_meson = 0; // いったん計測中断 tms_pos = 0; // 時から設定を始める disptime(); // 経過時間表示 r_exc = R_TMSET; // 時刻設定へ break; } } /***** 記録した照度データを送信 *****/ void rlogtx(void) { word p, d; if((log_tx >= log_cnt) || // 出力完了? (sw_on != 0)){ sw_on = 0; // SW入力onフラグクリア lcd.clear(); f_addisp = 1; // A/Dデータ確定 f_tmdisp = 1; // 時間確定フラグ r_exc = R_STBY; // スタンバイへ } else if(tm_1ms == 0){ p = epadrslog(log_tx); // ログデータ位置 EEPROM.get(p, d); // 記録した照度読み出し txprintf("%4d %4d\r\n", log_tx, d); tm_1ms = 50; // wait lcd.setCursor(0, 1); lcdprintf("%4d/%4d:%4d", log_tx, log_cnt, d); log_tx++; // 次データ } } /***** 時刻合わせ *****/ // 時、分、秒の順で時刻を設定 // 設定位置が点滅 // 測定/停止SWで +1、送信SWで時→分→秒→スタンバイ // 送信長押しで 23時59分50秒にセット void rtmset(void) { byte *p; if(f_blink){ // 表示タイミング f_blink = 0; lcd.setCursor(tms_data[tms_pos].cur, 0); if(f_blank) lcd.print(F(" ")); else lcdprintf("%02d", *tms_data[tms_pos].tmd); } // スイッチ チェック switch(swonchk()){ case SW_ON: // 数値+1 p = tms_data[tms_pos].tmd; *p += 1; // 時分秒+1 if(*p >= tms_data[tms_pos].lim) *p = 0; // max? f_blink = 1; // 表示指令 break; case SW_TX: // 次タイマー位置 disptime(); // 経過時間表示 tms_pos++; if(tms_pos >= DIMSIZ(tms_data)){ // おわり? lcd.clear(); f_logrec = 0; // 記録開始クリア tm_1scnt = 0; // 1秒カウンタクリア f_1sec = 0; f_addisp = 1; // 表示のためにA/Dデータ確定 f_tmdisp = 1; // 時間確定フラグ f_tmstop = 0; // 計時再開 eeprom_read(f_meson, ep_meson); // 測定on/off戻す r_exc = R_STBY; // スタンバイへ } break; case SW_TIM: // 時刻設定へ(送信SW長押し) tm_hour = 23; // 23時59分50秒 tm_min = 59; tm_sec = 50; disptime(); // 経過時間表示 f_blink = 1; // 表示指令 break; } } /********************************/ /* 制御実行テーブル */ /********************************/ /***** 制御実行 *****/ void (*rexc[])(void)={ rttl1, // 0:タイトル表示 rttl2, // 1:タイトル表示 #2 rttl3, // 2:タイトル表示 #3 rstby, // * 3:スタンバイ rlogtx, // * 4:記録データ送信 rtmset, // * 5:タイマー設定 }; /******************************/ /* ループ */ /******************************/ /***** LOOP *****/ void loop() { // 照度データ if(f_adok){ // A/D変換完了 f_adok = 0; cli(); // 割込禁止 ad_lux = ad_avr[0]; // 内蔵A/D ch0 0~1023 sei(); // 割込許可 f_addisp = 1; // A/Dデータ確定 } // 時間計測 if(f_1sec){ f_1sec = 0; // 1秒フラグをクリア if(f_tmstop == 0){ // タイマー計時中 if(f_speedup == 0){ // speed upなし tm_sec++; // +1秒 if(tm_sec >= 60){ tm_sec = 0; tm_min++; // +1分 if(tm_min >= 60){ tm_min = 0; tm_hour++; // +1時 if(tm_hour >= 24){ // 24時間経過 tm_hour = 0; if(f_meson) f_logrec = 1; // 測定中なら記録開始 } } } } else{ // speed upした時 tm_hour += 10; // +10時間 if(tm_hour >= 24){ tm_hour = 0; if(f_meson) f_logrec = 1; // 測定中なら記録開始 } } } f_tmdisp = 1; // 時間表示フラグon } // 制御実行 rexc[r_exc](); // 制御実行区分 } /*==== end of "led_lamp_test1.ino" ====*/