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

2023年3月9日木曜日

FM-7にRTCとSDを接続する試み(RTC編)

 FM-7用のRTC&SDカード基板を製作してみました

【修正】OneDriveのリンク先が間違っていましたので、正しいリンク先に変更しました。

以前、6821PIAを用いてI2CでRTCを、SPIでSDカードを読み書きする試みを紹介しました。

「アセンブラでのPIAとRTCの間のI2C通信に成功しました(2018年10月27日)」
https://flexonsbd.blogspot.com/2018/10/piartci2c.html)
「SDカードを6809のアセンブラで読み書きしてみる(2022年6月12日)」
(https://flexonsbd.blogspot.com/2022/06/sd6809.html)

最終の目的は、FM-7にRTC(リアルタイムクロック)とSDカードを実装することなのですが、RTCはともかく、SDカードを実装するのはそれ程簡単ではありません。
しかし、あれこれ考えているだけでは進まないので、とりあえず基板を作成してみることにしました。

作成した基板です。

製作したRTC&SDカード基板


その回路図を示します。

回路図


基本的には以前紹介したものと同じで、68B21のAポートを使用してI2CでRTCを、Bポートを使用してSPIでSDカードを制御しています。なお、RTCは5V駆動ですので68B21と直結していますが、SDカードは3.3V駆動ですので、レベル変換モジュールを通しており、その3.3V電源はSDカードから供給しています。
使用しているRTC基板はDS3231チップを使用しているZS-042で、バッテリを充電しないようにパターンカットを施しています。またSDカード基板は画像のものの他に、以前秋月電子で販売されていた基板も使えるように両方のパターンを用意してあります。(下のマイコン用基板に装着されています。)

同時に、自作6809/6802ボードマイコン用の基板も製作しました。
この基板はFlex9の起動時に自動的に日付を読み込むために使用しています。


マイコン用基板


今回は、RTC部分についてのみ紹介します。


FM-7に装着した状態です。

動作風景


実行中の様子です。

実行画面


FM-7のF-BASIC V3.0用に制作したソフトは、RTCから読み出すRTC_RDと書き込むRTC_WRの2本です。
RTC_WRでは日付と時刻をF-BASICのワークエリアに直接書き込んでいますので、RTC_WRはV3.0専用です。
画像にありますように、書き込んだデータがPRINT文で表示できており、正しく設定されていることが確認できます。

参考までに、RTC_WRのリストを示します。

 

F-BASICの起動時にRTC_WRを実行して日付・時刻を設定することで、以降はF-BASICから日付・時刻を参照することができます。

以上でFM-7にRTCを搭載することができましたが、問題はSDカードです。
独自のフォーマットでSDカードにファイルを保存・読み出しをするのであれば、今回作成した基板でも可能かと思いますが、Windows PCと共通のフォーマット(FAT16/32)でと考えると、FM-7と6821の機械語だけでは無理があるようです。
ネット検索をしても、ほとんどがマイコン用に用意されているFATライブラリを使用しているようです。
しかし、困難かもしれませんが、マイコンを使用せずにやれるところまでやってみようと思います。
うまくファイルの読み書きができましたら紹介させていただきます。
(ネット検索をしても、FM系にSDカードを装着した記事が見当たらないようですが、私が見つけられないだけでしょうか? 見つかるのは80系ばかりのような。。。)

紹介しましたRTC用に制作した2本のソフト(RTC_WRとRTC_RD)のソースとバイナリをOneDriveに上げておきます。なお、これらのソースのアセンブリには以前紹介した自作のクロスアセンブラ6809AsmWin.exeを使用しています。

2021年11月3日水曜日

6821PIAからアセンブラによるSPI通信でセンサーを制御する

 6809SBCやFM-7からSPI通信でADコンバータMCP3208を制御してみました

これは以前の報告(6809SBCボードやFM-7にArduinoを接続してRTCやLCDを制御 2021年8月24日)の続編です。

実現しようとしているのは6809SBCボードやFM-7にArduinoやRaspberry Piのようなマイコンを接続して、その先の様々なセンサー等を制御することです。そのスタートが上記の報告だったのですが、SBCボードやFM-7に搭載したPIAとArduinoの通信にハードI2Cを用いざるを得なかったために、肝心のセンサー等の制御にソフトI2Cを用いることになり、これでは制御の自由度が狭まってしまっていました。

ということで、PIAとArduino間にSPI通信を用いることができれば、Arduinoに接続したセンサー等をI2C(ハード、ソフト)やSPIで自由に制御できると考えました。

手始めに、Arduinoを仲介せずにPIAにADコンバータMCP3208 を直接接続して制御してみました。写っていませんが前回同様にフラットケーブルの先でPIAと接続しています。


ブレッドボードで実験

 接続図です。


PIAとMCP3208の接続


プログラムを示します。
以前のI2C通信で用いたサブルーチンと同じ名称のものがありますが、その内容は細かいところで異なっているものがあります。またMCP3208のSPI通信に特化したものですので、制御信号は5ビットのみで良く、制御信号の書き込み、データの読み出しはいずれもSCLKをH->Lにするタイミングで行われます。

示したのは6809のFLEX9でのアセンブラプログラムですが、FLEX9特有のサブルーチンは15~18行目の4つ(WARMS, GETCHR, PCRLF, OUTADR)のみです。

   
 

これで、6809SBCやFM-7にマイコンを接続してその先に色々なセンサーをつなぐことができ、マイコンの高級言語(!)でセンサーを自由に制御できることになります。

間にマイコンを挟む場合ですが、ArduinoのようにSPI通信が1回路のみのものでは、センサー側がI2CかSPIかによってPIA側の接続を選ぶことになります。




Raspberry PiやBeaglebone blackのようにSPI通信を2回路持っているものではセンサーとの通信もSPIを使うことができます。





MCP3208の制御に関しては、データシートの他に「最新Raspberry Piで学ぶ電子工作」(金丸隆志著)の解説がとても分かりやすくて大変参考になりました。感謝いたします。


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に上げておきます。


2018年11月3日土曜日

PIAのみでRTCからの時刻の読み書きができました

PIAに接続したRTCから時刻を読み書きするアセンブラのプログラムが完成


前回(10月27日)はRTCモジュールから時刻を読み込むまででしたが、時刻の書き込みもできるようになりました。
読み込み・書き込みプログラムはそれぞれRTC_RD.CMD、RTC_WR.CMDですが、読み込みプログラムに、FLEX9の起動時に時刻をRTCモジュールから読み込んでFLEX9の日付を設定する機能を追加したSETDATE.CMDを用意しました。

RTC_RD.CMDとRTC_WR.CMDはFLEX9上のコマンドとして使用します。


FLEX9システムに組み込んで使用する


SETDATE.CMDはFLEX9の起動時に自動的に実行されるように、STARTUP.TXTに書き込んでおいて使用しますが、FLEX9の起動時にデフォルトで実行される日付入力ルーチンが不要になりますので、FLEX9のシステムを一箇所変更します。

FLEX9システムをTrk01,Sct01から保存した場合、初期化ルーチンはSct08にあります。
そのうちの日付入力ルーチンはオフセット$76からのBD,CA,AC (JSR $CAAC) ですので、このBDを39 (RTS)に変更します。

初期化ルーチン(変更前)
初期化ルーチン(変更後)

これによって、起動時に日付を問い合わせてくることは無くなり、代わりに、STARTUP.TXTに書き込んだSETDATE.CMDがRTCモジュールから取得した日付を設定してくれることになります。

その様子を下図に示します。


起動画面(従来のもの)

今までは、起動時に日付を「月、日、年」の順に入力する必要がありました。
(FLEX9では時刻は管理していませんので、年月日のみです。)
それに対して、SETDATE.CMDを組み込むと、

起動画面(RTCモジュールから読み込み)

日付を問い合わせてくることなく、RTCモジュールから取得した日付と時刻を表示してそのままコマンド入力待ちになります。DATEコマンドを入力してみると、確かに日付が設定されていることが分かります。
なお、RTCモジュールが無い場合には、デフォルトの日付入力ルーチンが呼び出されて手動で日付を入力することになります。

起動画面(RTCモジュールが無い場合)

作成したRTC_RD.CMD, RTC_WR.CMD, SETDATE.CMDのソースをOneDriveに上げておきます。
入出力ルーチンなど一部にFLEX9のシステムルーチンを使用していますが、I2C通信部分は一般的な6809のアセンブラですので、I2C機能を持たないマイコンで、しかもアセンブラでI2C通信をしたいという場合の参考になれば嬉しいです。
(I2Cの解説も、DS3231のマニュアルも、もう少し分かりやすく書いてもらえればこんなに苦労しなくても済んだかもしれないのに...愚痴でした。)

2018年10月27日土曜日

アセンブラでのPIAとRTCの間のI2C通信に成功しました

アセンブラでPIAを経由してRTCの時刻の読み出しができました


使用したRTCモジュールはアマゾンで入手したHiLetgoのZS-042です。このモジュールにはDS3231というチップが使われており、I2C通信で時刻の設定や読み出しを行うようになっています。
I2C通信については、名前を知っているだけで具体的なことは全く知らなかったのですが、FLEXの起動時の日付の入力が煩わしいので、RTCからの自動読み込みに挑戦することにしました。

しかし、ネット上の情報は多くがArduinoとの接続の場合で、しかもWireライブラリを使うものがほとんどで、私もRTCモジュールが動作するかどうかをArduinoで確認しましたが、30分もあればできるという簡便さは誠にありがたいのですが(ライブラリを作成してくれた方には感謝です...)、6809のアセンブラでI2C通信プログラムを書きたい場合には全く役に立ちません。

また、PICやAVRなどのマイコンのアセンブラでI2C通信をしているものも幾つか見つけましたが、これらもマイコン自身にI2C通信機能を備えたものを使用している場合がほとんどで、これも役には立ちません。また、I2C通信機能を持たないPICやAVRでのケースもありましたが、これらのマイコンはポートのビット処理命令を持っているので、ビット処理命令を持たない6809ではプログラムの参考にはあまりなりませんでした。

ということで、結局、I2C通信の解説とDS3231のデータシートを読みながら、自力でプログラムを組むことになりました。

6821とRTC間の接続

6821とRTC間は下図のように配線しました。
図中のプルアップ抵抗はPortAの内蔵抵抗で代用しています。
6821のPortAはオープンドレインで、しかも5kΩの抵抗でプルアップされていますので、I2C通信に適しているということと、入出力の切り替えが不要で、出力に設定したままで入力も可能(但し、予めHを出力しておく必要あり)なので、プログラムが書きやすいと考えました。

RTC配線図


ロジアナを所有していないので、デジタルオシロで波形を見ながら試行錯誤を続けましたが、手順の最初のスレーブアドレスの書き込みからして成功しているのかどうかも分からず、全くACKが返ってこない状態が続き、間にPICでも挟まないとダメかとあきらめかけたこともありました。

最終的には、SDA信号は、Lowは0を出力するのに対して、Highは1を出力するのではなく開放、つまりHi-Zにするのだということに気づき、それに対応するように書き直すことで、ようやく読み込みができるようになりました。

読み出しに成功

下図で表示されたデータは、RTCの最初の7レジスタを読んだもので、順に、秒、分、時、曜日、日、月、年を表しています。

RTCから日付と時刻を読み取り

現段階では、ようやく読み取りができたというところまでですが、あとは書き込みルーチンを作成し、それを常駐プログラムの形式にして、FLEXの初期化ルーチン中の日付入力ルーチンと置き換えれば完成です。
(完成しましたらプログラムは公開します。)

[11月4日 追加] 完成したプログラムは11月3日のブログで公開しています。