チープなI2Cデバイス
電子工作を始めた頃、I2C機能を持たないAVR ATTiny2313を、USIを用いてI2Cスレーブ機能を実装したデバイスを何点か製作した。
残念なことにArduinoでは問題なく動作したのだが、Raspberry Piでは動作しなかった。
この前、秋月で商品を購入したときにACM1602NIというI2C LCDをついでに購入していた。まだ使ってないのでネットで調べてみると、あまり評判の良いものではなく拙作のI2C LCDと同じようなトラブルを抱えるてるのを確認した。秋月のACM1602NIも、拙作のI2C LCD等もPICとAVRの違いはあれ半ソフトウェアでI2Cデバイスを実装してるようなのだ。
ネットで調べた皆さんのACM1602NIの対処方法は”I2Cのパケット毎にウェイトを入れる“というものだ。つまり問題点はチープなため通信速度に処理が追いついてないということなのだ。拙作のI2Cスレーブデバイスも同様な対処方法をとれば動くようになる可能性がある。
mbed LPC1114FN28でI2C LCDを駆動
mbedではACM1602NIを対処したソースがあったので、それに習い修正するこにとした。肝はパケットひとつ送信する毎にウェイトを入れるということだ。こんな感じだ。
int MyLCD::writeBytes(const char *data, int length, bool repeated) { wait_us(i2c_bit_wait_us); _i2c->start(); wait_us(i2c_bit_wait_us); if (_i2c->write(i2c_addr) != 1) { wait_us(i2c_bit_wait_us); _i2c->stop(); return _i2cFAILURE; } for (int i = 0; i < length; i++) { wait_us(i2c_bit_wait_us); if (_i2c->write(data[i]) != 1) { wait_us(i2c_bit_wait_us); _i2c->stop(); return _i2cFAILURE; } } if (!repeated) { wait_us(i2c_bit_wait_us); _i2c->stop(); } return _i2cSUCCESS; }
この関数を用いてArduinoのライブラリィを移植して動作確認できた。それがこれである。
mbed LPC1114FN28でI2C 7SEGを駆動
次はI2C 7SEG(Charlieplexing 7SEG LED)だ。これもArduinoのライブラリィから移植した。
そしてこれが動作してるところだ。これは一応時間を表示してるつもり。
チープなI2Cデバイス
チープなI2Cデバイス秋月のACM1602NIや拙作I2C LCDはArduinoでは問題なく動く。これはArduinoのI2Cには相当ウェイトが入ってるのだろうと想像できる。
それにしても、AVR ATTiny2313で作ったI2Cスレーブデバイスは自作なのでチープなI2Cデバイスと呼んでもよいものだが、秋月のACM1602NIって一応商品なんだけどどうなんだろね。
こんにちは。PICKIT3が使えず自作不調のnobchaです。
ちょっと前のブログなのですが、ちょっと思い出してコメントします。
SC1602(16字2行LCD)をVOをマイナス電源で引っ張って、ニッスイ2.5Vで使ってます。そうするとLCD制御用LSIの内部RC発振器が遅くなって内部シーケンサが回らなくなります。そのため、PIC16F1827基板でLCDを使うニッスイ2本電源方式ではLCD関連シーケンスには__delay_ms()を入れまくりました。
これの対策なんですが、Read Busy Flag and AddressコマンドでBF待ちにすればよいように思います。先輩方の試作でもLCDのR/Wはライト専用でグランドに落としてあるため、BFを読めません。
一方i2cではこのコマンドは生きているはずなので、while(BF)で待ちを入れればよいのかもと思います。そういったところで、自分で作成したスレーブにこいつを入れてないのを思い出しました。R/Wは制御してませんから。
ではでは、失礼しました。
毎度です。ばんとです。
2.5Vで運用するとLCD制御用LSIの処理速度が遅くなりすぎる…
ありそうですね。
拙作のI2C LCDは3.3Vでの運用も想定して設計してるのですが、
この電圧ではディレイを入れなくても問題無く動作してます。
と言っても5Vのところを3.3Vという低電圧で動かしてるのです
から、たまたま動いてるのかも知れません。
貴重な情報ありがとうございます。