前回完成した大きな電卓のアカウント(パスワード)管理機能のデータバックアップについてですが、色々考えてバックアップメディアにSDカードを使うのが良さそうという結論に至りました。SDならAVRで簡単に扱えるので、SDからデータを読み出してEEPROMに書き戻すのも難しくなさそうです。
しかし、今回作成した大きな電卓+ATmega328Pデバイスには空いているピンがほとんど無いのが問題です。ArduinoのSDライブラリはSPI通信でカードの読み書きを行うのですが、大きな電卓ではSPIに使用するピンの一部をLCDの制御に使ってしまっているのです。当初SPI通信を使うつもりがなかったので、あまり深く考えずにピンの配置を決めてしまっていたんですね。
バックアップ操作中にLCDが使えない(実は大きな電卓のICSPスケッチ書き込のときにLCDに■が表示され続けています)のはちょっとこまりますよね。
現状、通信に使えるのはEEPROMをつないでいるI2C端子だけです。結局、I2CにスレーブとなるデバイスをつないでSDカードの読み書きを行わせるしかないようです。
したがってこのデバイスではI2CとSPI両方の通信を行う必要があります。そこでSparkFun Pro Miniを使うことにしました。ArduinoはI2CとSPI両方を同時に使えるというのを聞いたことがあったからです。
でも、いきなり大きな電卓のハードを使って開発を行うのはちょっと面倒なので、大きな電卓で使用しているのと同じAVRのATmega328PにPro Miniをつないでテスト環境を構築してみました。
テスト環境はこんな感じです。
左端のATmega328Pとその右にあるPro Mini(互換機)をI2Cで接続して、Pro MiniのSPI端子にSDカードをつないであります。ただしこのPro Miniは5V動作のものなので3.3V動作のSDカードを直接つなぐのはよくありません。そこで今回は5V電圧を3.3Vに変換するために、サンハヤトのロジックレベル変換モジュールMM-TXS01を使いました。
このモジュールを使ったのは、必要になると思って購入したのにあまり活用することがなかったので、無理にでも何かに利用したかったからです。普通は抵抗で分圧するだけで十分でしょう。変換モジュールの側にある三端子レギュレータは秋月電子のTA48033Sで、Pro Miniの5V電源を3.3Vにして変換モジュールとSDカードに供給するためのものです。
書き込みに使用するSDカードは、長年使われることもなくほったらかしになっていた256MBのものを利用しました。こんなカードでも32KBのEEPROMのデータを扱うには十分すぎる容量です。
Pro MiniとSDカードの接続は以下のようになります。
Pro Mini ←→ SDカード
10 SS − 1
11 MOSI − 2
12 MISO − 7
13 SCK − 5
VCC − 4
GND − 3,6
実際はそれぞれの端子間にMM-TXS01が入っていて、VCCは3.3Vに変換しています。
Arduino IDEのSDサンプルではSDカードの1番(チップセレクト)の制御にArduinoの4番のピンを使っていますが、今回はデフォルトであるハードウェアSSピンの10ピンを使ってみました。このときスケッチのSD.begin()の引数は省略できます。
ATmega328PとPro MiniはI2Cで接続していますが、I2Cには大きな電卓と同様に1kΩのプルアップ抵抗をつなげました。ATmega328PがI2CのマスターでPro MiniがI2Cのスレーブとなります。
テストのために作成したスケッチは以下のようになりました。
I2CSDmaster.ino
I2CSDslave.ino
I2CSDmaster.inoはマスターとなるATmega328P向けで、I2CSDslave.inoはスレーブのPro Mini用です。ArduinoのWireライブラリはI2Cピンを内部抵抗でプルアップするらしいので、Pro MiniのスケッチではI2C初期化後に、
pinMode(SDA, INPUT);
pinMode(SCL, INPUT);
を付け加えてプルアップを無効にしています。ATmega328P側はこの処理をしなくてもI2C通信は行えました。
Wireライブラリでは、I2Cスレーブ側は割り込み処理でマスターの要求を受けます。そこでちょっと困るのはSDカードのファイルオープンとクローズのタイミングです。いつ来るかわからない割り込み処理のために、常にファイルオープンにしておくとSDカードの抜き差しに困りますし、I2Cの通信にファイルオープンとクローズのコマンドを付け加えるのも割り込み処理が複雑になるのでやりたくありません。
また、SDライブラリではSDカードにすでに存在するファイルに書き込みを行うと、上書きではなく追加書き込みになるのもちょっと困りました。上書きさせるオプションもなさそうです。バックアップファイルを更新するのに追加書き込みをされると、後でデータ切り離すのか面倒です。
対策としてファイル書き込みの要求が来るたびに、ファイルのオープン・クローズを行うことにしました。WireライブラリでI2C通信に使えるバッファは32バイトなので、32バイトのデータが送られてくるごとにファイルオープン・クローズを繰り返すことになります。最善の方法ではないかもしれませんが、割り込みの処理は簡単になりました。
ファイルの上書きの方はどうしようもないので、送られてきた32バイトのデータの先頭の値が0の空データのときは古いファイルがあれば削除して新しいファイルを作り直すようにしました。
ファイル読み出しのときも同じように割り込みがかかるたびにファイルのオープン・クローズを行います。読み出すデータはseekコマンドで選択しています。
デバッグ表示に使用しているLCDは以前作成したPICベースのものですので、もしこのスケッチを利用する場合には表示部分はお好きなデバイス用に書き換えて下さい。
これで上手くバックアップできそうなのであとはスケッチを大きな電卓に移植するだけなのですが、もう1つ考えなければならないことがありました。
大きな電卓のバスワード管理機能ではHD44780日本仕様のLCDで扱える半角カナ文字が入力できます。バックアップデータに書き出したはカナ文字は1バイトのデータですが、日頃使用しているUbuntuのUTF-8のコード(Windowsも同じですが)では半角カナ文字を1バイトでは扱いません。したがってバックアップしたデータをPCなどで修正するには、コード変換を行う必要があります。
Arduinoで出来ないこともないのですが、Ubuntu側で変換プログラムを作る方が簡単そうです。後でUTFのコード表をながめながら作成してみようと思います。
※コメント投稿者のブログIDはブログ作成者のみに通知されます