PASのブログ

PASの中の人が書く雑記ブログです。

セーブ機能を作る アナマル.16

多分ですが次回でスケッチ編の最終回です。
隅から隅まで、ややこしいことを極力省き書くのは大変自分の勉強になりました。

ここまで書いてお気づきの方も多いかと思いますが、このシリーズは全く前準備なく、書きながらソースを書くという無謀なことをしてます。
GPIO処理がほとんどなので可能なんですが、今後別のシリーズをやるとしたら(読者さんも自分自身も)かなり力がつく気がします。
では前回の続きです。

BANK_DATA [ ] に保存する(揮発)

まずは、プログラムモードで参照するBANK_DATA [ ]に、設定をしたchの情報を記憶させます。
但し、これは揮発性と言いまして、電源を切ると消えるタイプの「記憶」です。
次のステップで「消えない領域に記憶」させます。

    int ch_data = 0;

    //ch_dataに4ビットで格納
    ch_data = 0; //ch_dataをリセット
    if (!digitalRead(LED[0]))ch_data = ch_data | 0b0001;
    if (!digitalRead(LED[1]))ch_data = ch_data | 0b0010;
    if (!digitalRead(LED[2]))ch_data = ch_data | 0b0100;
    if (!digitalRead(LED[3]))ch_data = ch_data | 0b1000;
    ch_data &= 0x000f;
    BANK_DATA[ch] = ch_data;

|というのはor、論理和と言いまして、AとBがそれぞれ0,0のときは0、それ以外は1になる論理演算です。
一旦、ch_dataを0にして、LED[0]から[4]までをorで挿し込んでいき、4桁の2進数にします。
最後に、(今回の場合は基本的には不必要ですけど) 0xfとandをして、2進数4桁にします。
UNOの場合、intは2バイトなので2進数で言えば16桁です。何らかの要因で5bit目から16bit目に1が入らないように、0x000fでandすることで5bit目から16bit目を確実に0にしておきます。

BANK_DATA[ch] = ch_data;とすることで、揮発する保存は完了です。
実際のイメージとしては、PRGset()は高速でwhileしてますので、SW0-SW4のどれを押しても、随時揮発性保存されています。
これは逆に言うと、今まで使っていたデータが消えるということですので、扱いは面倒かもしれませんが、スイッチとLEDを増やさない前提でこうすることにしました。
ディスプレイを付けたり、スイッチやLEDを増やすという方向になったときに、随時揮発性保存するのではなく、保存ボタンを押したら揮発性保存する、など改造すれば良いかもしれません。

EEPROMに保存する(不揮発)

EEPROMというのは、電源を落としても消えない保存領域です。
Arduinoには、標準ライブラリにEEPROMを制御するライブラリがあるので、それを利用して、EEPROMに保存することにします。

インクルードする

インクルードとは、あるファイルの中に別のファイルに記述された内容を追加する機能のことです。
端的に言うと、他の(ある処理を完成した形で書いた)プログラムを、参照できるように紐付けする機能ですね。

f:id:pas_fx:20200623011954p:plain スクショのようにすると、

#include <EEPROM.h>

とスケッチの先頭に記述されます。
これで準備完了です。

for文

forは、繰り返しをする命令です。
whileでも似たようなことが出来ますが、単純な繰り返しに使うことが多いですね。

for (初期化; 条件式; 加算) {
 //実行される文;
}

今回のスケッチの場合は2つの関数で使用します。

void save()
{
  for (int i = 0; i < 4; i++)
  {
    EEPROM.update(i, BANK_DATA[i]);
  }
}

void load()
{
  for (int i = 0; i < 4; i++)
  {
    BANK_DATA[i] = EEPROM.read(i);
  }
}

forの部分を人間の言葉で書く(←何?この表現)とこうです。

1.iを0にする

2.i < 4になるまで{ } の中身を繰り返す

3. iを+1する

4.I < 4を満たさなくなったら(iが4になったら)処理しないで抜ける

EEPROM.update(i, BANK_DATA[i]);

EEPROM.update(address, value)は、EEPROMに1biteぶん保存します。他にも似たような関数にEEPROM.write(address, value)があります。
両者の違いは、前者は書き込もうとした番地に、同じことが書かれていたら書かず、後者は、無条件で書きます。

addressは、番地のことで、arduino UNOには0-1023の1023番地があります。
1番地あたり8bit = 1biteの情報を格納できます。
先程、揮発性保存のソースで、1つの変数あたり4bitにしているのはこの処理で1biteを超えないための保険です。

valueは、実際に保存したいデータです。
今回の場合は、
BANK_DATA[0]→EEPROMアドレス0
BANK_DATA[1]→EEPROMアドレス1
BANK_DATA[2]→EEPROMアドレス2
BANK_DATA[3]→EEPROMアドレス3
に保存するので、

void save()
{
  for (int i = 0; i < 4; i++)
  {
    EEPROM.update(i, BANK_DATA[i]);
  }
}

こうなります。

BANK_DATA[i] = EEPROM.read(i);

EEPROM.read(address)は、addressで指定したbiteから1biteぶんのデータを呼び出します。 それをBANK_DATA[i]に格納しています。