Arduinoのメモリ消費を抑える
最近、ATtiny2313を使って、MAX31855Kを利用したK型熱電対のディスプレイを作製しようとしていました。
MAX31855KはAdafruitにArduino用のサンプルライブラリがあり、これを利用しない手はありません。ですので、表示部としてキャラクタ液晶を使うとして、公式のLiquidCrystalライブラリと、Adafruitのライブラリを利用してしまえば簡単にできるでしょう。
と思っていましたが、一筋縄ではありませんでした。tiny2313はメモリがプログラムメモリで2kByte、SRAMが128Byteしかありません。実にArduino Unoの1/16です。この問題についてある程度スケッチを書いてコンパイルしてから気づいたのですが、一度乗りかかった船、何とかならないものかとがんばってみました。
なお、Arduinoでtiny2313を利用するために、kosakalabさんの記事のものを利用しています。Arduino1.6では若干の修正が必要ですが、その件の解説は行いません。
浮動小数点を使わない
これは公式にも書かれている手法ですが、必須です。
Adafruitのライブラリにはdoubleが利用されているため、修正します。
MAX31855Kは符号付き14bitの値を返し、生の値に0.25を掛けたものが実際の値になります。
これを読んだ値がすでに4倍されたものとすることにし、
/* uint32_t v = spiread32()>>18; // となっているような状態で*/ if (v & 0x2000) { // 負の値の時 lcd.write('-'); temp ^= 0x3fff; // 補数表現を戻す temp += 1; } lcd.write('0'+((v/4000)%10); // 1000の位 lcd.write('0'+((v/400)%10); // 100の位 lcd.write('0'+((v/40)%10); // 10の位 lcd.write('0'+((v/4)%10); // 1の位 lcd.write('.'); lcd.write('0'+(((v&3)*25)/10); // 0.1の位 lcd.write('0'+((v&1)*5); // 0.01の位
などと書くことができます…
EEPROMを使う
Arduinoではグローバル変数を用いて定数を利用している例がたまにありますが、そういうものはEEPROM上に書き込み、その都度読み出すのが良いです。プログラムメモリの節約と、SRAMの節約が期待できます。
tiny2313では128Byteありますので、うまく使えばかなり余裕ができます。
例として、LiquidCrystalのCustomCharacterサンプルの場合、
// make some custom characters: byte heart[8] = { 0b00000, 0b01010, 0b11111, 0b11111, 0b11111, 0b01110, 0b00100, 0b00000 };
と宣言し、setup関数内で
// create a new character lcd.createChar(0, heart);
と利用していますが、heartはこれ以降利用されません。
このheartのデータをあらかじめEEPROMに書き込んでおき、以下のようにEEPROMを読んで利用してやると良いです。
byte temp[8]; for (int i = 0; i < 8; i++) { temp[i] = EEPROM.read(i); } lcd.createChar(0, temp);
Printを利用しない
LiquidCrystalライブラリはPrintクラスを継承していますが、少しサイズが大きめです。
下記のようにコメントアウトします。
/* クラス定義 */ class LiquidCrystal{// : public Print {
/* using部分 */ // using Print::write;
この変更によって、Printが利用できなくなりますので、
void printStr(uint8_t* str){ for(;(*str)!='\0';str++) lcd.write(*str); } printStr("helloworld.");
などと書く必要があります。
ポートを直接制御する
I/OにはpinMode,digitalWrite,digitalRead等を利用しますが、これらの関数はそれぞれ100Byteほどプログラムメモリを消費しています。ライブラリ内を含むすべての呼び出し部分を編集する必要があり、ハードウェアへの依存が大きくなってしまいますが、仕方ありません。