ラベル LCD の投稿を表示しています。 すべての投稿を表示
ラベル LCD の投稿を表示しています。 すべての投稿を表示

2021年8月24日火曜日

6809SBCボードやFM-7にArduinoを接続してRTCやLCDを制御

 6809SBCボードとFM-7にArduinoを接続してRTCやLCDを制御してみました

現在では様々なセンサー等が気軽に入手できて、電子工作好きには楽しい時代ですが、シングルボードマイコンやFM-7などにもそれらのセンサーを接続してみたいと考えていました。

今までにも、6809/6802Dualボードに搭載しているPIA(6821)を利用してRTC(ZS-042)を接続して、Flex9の起動時に時刻を自動的に読み込ませて、起動時の時刻の手入力を省略したりしていましたが(下記のブログで紹介)、もっと他のセンサーなども接続したいと思うようになりました。

  2018年11月3日のブログ「PIAのみでRTCからの時刻の読み書きができました」

上記のPIAにRTCを接続した際には、I2Cによる通信プログラムをアセンブラで作成しましたのでかなり時間がかかりました。センサー毎にアセンブラによるプログラムを作成するのは非現実的ですので、間にArduinoのようなマイコンを挟めばよいのではないかと思いつきました。手持ちには数種類のマイコンがありますが、とりあえず最も手軽そうなArduinoで始めて性能に不満が出たら他のマイコンに置き換えれば良いと思って始めましたが、思ったよりも難しくて一ヶ月余りもかかってしまいました。

難しかったのは、6809側ではアセンブラによるプログラムでI2C通信するのですが、それに対するArduino側のC++(?)のプログラムの応答との関係が良く分からないことでした。

とりあえず、Arduinoを通してRTCとLCDを制御できましたので報告します。

全体の接続を下に示します。6821PIAとArduino間をハードI2Cで通信し、Arduinoと各センサー間はソフトI2Cで通信します。ソフトI2CではArduinoがマスターにしかなれないのでこのような構成となりました。



接続図

(1)ハードの設定

実際の実験の様子です。上部に見えるのが6809/6802Dualボードで、下にあるのがArduinoとセンサーです。


実験風景

ブレッドボード上の中央がRTC(ZS-042)、右が8桁x2行のLCD(AQM0802A)で、RTCから読んだ日時を表示しています。どちらも5V版なので、Arduinoに直結できています。またI2Cのプルアップ抵抗は、ハードI2C側は6821内部の抵抗を、ソフトI2C側はArduino内部の抵抗を利用していますので、単純にセンサーをArduinoに接続するだけで済んでいます。
(左のセンサーは他の実験のもので無関係です。)

センサー部のアップ


6809/6802Dualボードに接続した場合の結果です。アセンブラによるプログラムでArduinoに指示を送り、ArduinoがRTCを読んで結果を送ってきています。(とりあえずの実験なので単純にデータを順に表示していますが、左から年月日と時分秒です。)


6809/6802Dualボードによる結果


続いて、FM-7でも同様な実験を行ってみました。


右に装着されているのが6821PIAボード



使用したのは、以前報告したブログ「FM-7/77用拡張PIAボードとP-ROMライタ」(2020年6月26日)で製作したP-ROMライタ用の6821PIAボードです。



FM-7用6821PIAボード


6809ボードで用いたアセンブラプログラムをサブルーチン化して、F-BASICのプログラムから呼び出す形で使用しています。F-BASICのプログラムはサブルーチンを呼び出すことと結果を表示するためだけに用いています。

FM-7による結果


(2)プログラム作成

プログラム作成上で私が引っかかった点を列挙します。

1.ソフトI2CではArduinoはマスターにしかなれず、スレーブにはなれない。

 → 最初は6809側をソフトI2Cで、センサー側をハードI2Cでと考えていたのですが、結局、逆にせざるを得ませんでした。

2.RTC(ZS-042)の制御ICであるDS3231用のライブラリDS3231.hはI2Cのアドレスを決め打ちしておりソフトI2Cには対応していない(ようです)。

 → ライブラリを使わずに直接DS3231のレジスタを操作することになりました。

3.Arduinoで標準のWire.hでの割り込み関数 Wire.onRequest(requestEvent); や Wire.onReceive(receiveEvent); を6809ボードからのアセンブラプログラムでどうしたら起動させることができるか。また、Wire.requestFrom(ID, no); は使えないが、その代わりにどのようにしたらリクエストできるのか。

 → 6809側からArduinoに何かのデータを書き込むと onReceive関数が反応するので、この receiveEvent関数内で送られてきたデータを読み込んで(必要がないので)捨てる。6809側にデータを送り返す作業は onRequest関数で呼び出される requestEvent関数内で行うという形で通信することができました。(receiveEvent関数では6809側に送り返すことはできませんでした。)


参考までに6809側のプログラムのソースを示します。

 


以上、あちこち引っかかりながらも何とか目的を達することができましたが、次に何とかしたいと考えているのは、Windows側からUSBを通してArduinoにデータを送り、それをさらに6809/6802DualボードやFM-7に送ることです。

とりあえず、現在の状態でのプログラム(6809側のSBC_I2C.txtとそのバイナリ、Arduino側のsbc_i2c.ino、FM-7用のFBI2C、FBI2CSUBとその保存形式のFBI2CSUB2の6本)をOneDriveに上げておきます。


2018年11月17日土曜日

I2C通信でLCD表示器に文字表示ができましたが...

LCD表示器に文字表示ができましたが、標準の書き方ではなく...


使用したのはスイッチサイエンスで購入した8文字2行表示のAQM0802A(5V版)です。
5V版なので、10月27日に公開したRTCの回路にそのまま追加しました。

接続図


コマンド・データの書き込み手順


コントロールICはST7032iで、そのマニュアルによると、コマンドやデータはいずれもコントロールバイトとデータバイトの2バイトのセットで書き込むようになっています。

コマンドの場合 複数連続して書き込む場合 :$80+1byte(コマンドコード)
        単独又は最後に書き込む場合:$00+1byte(コマンドコード)
データの場合 複数連続して書き込む場合 :$C0+1byte(データコード)
       単独又は最後に書き込む場合:$40+1byte(データコード)

$00+1byteや$40+1byteの後には必ずI2Cのストップコンディションが続いて終了することになっています。


連続書き込みでは$80や$C0を毎回書くのですが...


実際にプログラムを作って試してみると、
S+ADR+($80+CmdCode)+($80+CmdCode)+...+($00+CmdCode)+P

S+ADR+($C0+Data)+($C0+Data)+($C0+Data)+...+($40+Data)+P
 (S:スタートコンディション、ADR:スレーブアドレス、P:ストップコンディション)
という書式で確かに書き込みができました。

しかし、ネット検索をしてみますと、$80や$C0を用いて連続書き込みをするのではなく、$00や$40を用いて1byteずつ書き込む例も結構見られます。例えばArduinoのC言語であれば、Wireライブラリを用いて、

コマンド書き込みの場合は
Wire.beginTransmission()とWire.endTransmission()で挟んで
Wire.write()で$00と1byteのコマンドを書く。

データ書き込みの場合は
Wire.beginTransmission()とWire.endTransmission()で挟んで
Wire.write()で$40と1byteのデータを書く。

というような形式です。(この例のbeginTransmission()とendTransmission()はそれぞれS+ADRとPだと思われます。)


もう少し効率的に連続書き込みをする方法がありました


確かに、1文字の書き込みなら$00や$40を用いるのがマニュアル通りの書き方なので良いのですが、複数バイトのコマンドやデータを書き込みたい場合には、スタートコンディション、スレーブアドレス、ストップコンディションを1byte毎に書くことになり、いかにも非効率です。
かといって、連続書き込み用の$80や$C0を1byte毎に書くのもあまり効率が良いとは言えません。スタートコンディション、スレーブアドレス、ストップコンディションは1回で済むという利点はありますが。(これしか方法がないのなら仕方がないのですが)

他の書き込み方はないのかと色々と試行錯誤した結果、下記のような書式で書き込めることを確認しました。

コマンド書き込みの場合
S+ADR+$00+(複数のコマンドコードを順に)+P

データ書き込みの場合
S+ADR+$40+(複数のデータを順に)+P


この書き方は、明らかにマニュアルで説明されている書式とは異なっているのですが、画像のようにちゃんと書き込めています。

AQM0802A表示例


最後に

なぜST7032iのマニュアルに載っていない書式で連続書き込みができるのかは分かりませんし、マニュアルを熟読すればどこかに記載されているのかもしれませんが、あくまでもAQM0802Aの一使用例として見ていただければと思います。
何か勘違いや間違い等ありましたらご指摘いただけるとありがたいです。

6809のアセンブラでLCDWR.TXT,LCDWR1.TXT,LCDWR2.TXTの3つのプログラムを作成し、いずれも正常に書き込みできることを確認しました。

LCDWR.TXTの書式(最も短い)
  command : S+ADR+$00+cmd1+cmd2+...+lastcmd+P
  data         : S+ADR+$40+dat1+dat2+...+lastdat+P
LCDWR1.TXTの書式(初期化コマンドのみ短い)
  command : S+ADR+$00+cmd1+cmd2+...+lastcmd+P
  data         : S+ADR+($C0+dat1)+($C0+dat2)+...+($40+lastdat)+P
LCDWR2.TXTの書式(標準の書式)
  command : S+ADR+($80+cmd1)+($80+cmd2)+...+($00+lastcmd)+P
  data         : S+ADR+($C0+dat1)+($C0+dat2)+...+($40+lastdat)+P

参考になるかどうかわかりませんが、作成した3つのプログラムのソースをMicrosoftのOneDriveに上げておきます。