<EEPROM.h>を参照すると EEPROMClassが実際に呼びだされている。
read、writeの他、以下の定義が気になったので試してみました。
結論から書くと、read→get、write→putの置き換えで、構造体の操作の箇所のコードは短くなりますが、スケッチサイズは20バイトほど増えました。
自前の関数を作らなくていいので自分としては許容範囲。
EERef operator[]( const int idx ) { return idx; } void update( int idx, uint8_t val ) { EERef( idx ).update( val ); } template< typename T > T &get( int idx, T &t ){ EEPtr e = idx; uint8_t *ptr = (uint8_t*) &t; for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e; return t; } template< typename T > const T &put( int idx, const T &t ){ EEPtr e = idx; const uint8_t *ptr = (const uint8_t*) &t; for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ ); return t; }
●書き換えた内容
読み込み(read→get)
byte* p = (byte*) &lightSet; unsigned int adr = 0; for (unsigned int i = 0; i < sizeof(lightSet); i++) *p++ = EEPROM.read(adr++)↓
EEPROM.get(0, lightSet);
byte* p = (byte*) &lightSet; unsigned int adr = 0; for (unsigned int i = 0; i < sizeof(lightSet); i++) EEPROM.write(adr++, *p++);↓
EEPROM.put(0, lightSet);
sprintf_P(ch, PSTR( "%02X ") ,EEPROM.read(adr));↓
sprintf_P(ch, PSTR( "%02X ") , *EEPROM[adr]);
●追加(updateでEEPROMを0xFFで初期化)
// 0xFFで初期化 Serial.print("EEPROM初期化"); for(unsigned int adr = 0; adr < EEPROM.length(); adr++) { EEPROM[adr].update( 0xFF ); } Serial.println(" ->初期化完了");添字でアドレスを指定して、updateの引数に値を指定する。
updateはEERefのupdateを呼び出している。定義を見ると↓の様になっていて値が同じなら更新しない動作となっている。
EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; }
書き込み回数の寿命が10万回なので、無駄な書き込みをしないように考慮しているんですね。
EEPROM.putも書き込みにはupdateを使っているので、こちらを使う方がよさそうです。
●最終的なソース
#include <EEPROM.h> /* 制御用のパラメータ定義 */ struct LightSetting_t { unsigned int offWaitSec; /* 消灯時間(sec) */ unsigned int border; /* 検出距離(cm) */ } lightSet; /* EEPROM用の操作ボタン */ int statusPin2 = HIGH; /* 書き込み */ int statusPin3 = HIGH; /* 読み込み */ int statusPin4 = HIGH; /* ダンプ出力 */ int statusPin8 = HIGH; /* 初期化 */ /* * 設定更新 */ void updateSetting() { if (LOW == digitalRead(4)) { if (statusPin4 == HIGH) { statusPin4 = LOW; dumpEEPROM(); } } else { statusPin4 = HIGH; } if (LOW == digitalRead(3)) { if (statusPin3 == HIGH) { statusPin3 = LOW; // EEPROM読み込み EEPROM.get(0, lightSet); Serial.println("設定値"); Serial.print("消灯時間(sec)=");Serial.println(lightSet.offWaitSec); Serial.print("検出距離(cm) =");Serial.println(lightSet.border); if (lightSet.offWaitSec == 0x0000 || 0xFFFF == lightSet.offWaitSec ) { Serial.println("設定値初期化"); lightSet.offWaitSec = 10; lightSet.border = 5; Serial.print("消灯時間(sec)=");Serial.println(lightSet.offWaitSec); Serial.print("検出距離(cm) =");Serial.println(lightSet.border); } } } else { statusPin3 = HIGH; } if (LOW == digitalRead(2)) { if (statusPin2 == HIGH) { statusPin2 = LOW; // それぞれ+1する lightSet.offWaitSec++; lightSet.border++; Serial.print("設定書き込み"); // EEPROM書き込み EEPROM.put(0, lightSet); Serial.println(" ->書き込み完了"); } } else { statusPin2 = HIGH; } if (LOW == digitalRead(8)) { if (statusPin8 == HIGH) { statusPin8 = LOW; // 0xFFで初期化 Serial.print("EEPROM初期化"); for(unsigned int adr = 0; adr < EEPROM.length(); adr++) { EEPROM[adr].update( 0xFF ); } Serial.println(" ->初期化完了"); } } else { statusPin8 = HIGH; } } void dumpEEPROM() { unsigned int adr = 0; unsigned int adrLength; byte data; char ch[6]; Serial.print(F("EEPROM size=")); Serial.println(EEPROM.length()); adrLength = 32; // 最初の32バイトまで表示 for(adr = 0; adr < adrLength; adr++) { if ((adr % 16) == 0) { sprintf_P(ch, PSTR("%04X:"), adr); Serial.print(ch); } sprintf_P(ch, PSTR( "%02X ") , *EEPROM[adr]); Serial.print(ch); if ((adr % 16) == 15) { Serial.println(); } } } void setup() { /* EEPROMのダンプ出力、読み込み、書き込み用のボタン */ pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP); pinMode(4, INPUT_PULLUP); pinMode(8, INPUT_PULLUP); Serial.begin(115200); } void loop() { updateSetting(); delay(100); }
0 件のコメント:
コメントを投稿