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

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


2020年6月26日金曜日

FM-7/77用拡張PIAボードとP-ROMライタ

FM-7/77用拡張PIAボードとP-ROMライタの製作


P-ROMライタは持っているので、まれに必要になる2716のような古いデバイスも書き込みができるのですが、古い機種(ADVANTESTのR4945A)ですのでパソコンとの通信速度が9600baudと遅く、4MbitのROMを焼くときには読み込みに時間がかかりすぎて使う気になれません。
ということで、昨年TL866ⅡPLUSを購入しました。これは実に優秀で使い易くてしかも安いので言うことなしと言いたいのですが、残念なことに2764以前には対応していません(メーカーによりますが)。
大昔は自作の8ビット機用にROMライタボードを製作して使用していたこともあり、いつかは作ろうと思ってはいましたが実行する機会がありませんでした。
先日、プリント基板をまとめて発注することになり、ついでにということでROMライタ基板も作成しました。

元にしたのはマイコンピュータ「OS-9活用テクノロジー」(CQ出版社)中の「P-ROMライタ/エディタの製作(阿部英志著)」です。これは、2716から27512までに対応していますが使用するROMに応じてジャンパプラグを差し替えるというもので、その分簡素な回路になっています。

FM-7/77からはPIA(68B21)ひとつで制御するようになっているので、この部分を切り離して汎用の拡張PIAボードとし、フラットケーブルでROMライタボードと接続する形にしました。
(一体化して10x10cmのサイズに収めたもののプリント基板も一緒に作りましたが、製作の予定は今のところありません。)

回路図


拡張PIAボード


拡張PIAボードはFM-7/77の32Pコネクタに接続して使用するもので、FM-7では未使用のアドレス$FD9CにPIAのポートAを割り当てています。

P-ROMライタ

P-ROMライタはVPPの25V, 21V, 12.5VをTL497Aで作り出し、D-FFのLS273でアドレスとデータをコントロールしています。(TL497Aというのがいかにも古いという感じですが、幸い手持ちがありましたし、何と今でも入手可能なデバイスのようです。)


製作した基板


下左:拡張PIA基板 下右:P-ROMライタ基板
上:一体化した基板(製作予定なし)


いつもどこかでドジをする私ですが、今回は2SC1815のフットプリントが2.54mmピッチでなく1.27mmピッチであったことに気づかずにそのまま利用したり、ピッチが5.08mmの270uHや220uFのピッチを2.54mmにしたので、ハンダ付けがとてもしにくい部分がありましたが、配線パターンのミスはなかったようです。(部品を入手してから基板の設計をすべきなのですが、大体が逆のパターンになってしまいます...)


拡張PIA基板の動作テスト


まず拡張PIA基板を製作し、動作テストのつもりで、以前紹介した、PIAを用いてI2C通信によってRTCから時刻の読み出し/書き込みをするアセンブラプログラムを走らせてみました。


拡張PIA基板の動作テスト



Flex9上でRTCを読み書き


正常に読み書きできましたので、このPIAボードが正常に機能していることが確認できました。


P-ROMライタ基板の製作


続いてP-ROMライタ基板を仕上げ、ジャンパプラグも2716用、2732用、2764用、27256用の4種類を作成しました。20Pの丸穴ICソケットを利用しています。



完成した基板

ジャンパプラグ
(左から2716, 2732, 2764, 27256用)


動作風景


試しにP-ROM 27C256を書き込んでみましたが、正常に書き込むことができました。
ただ、今のところ2716にはうまく書き込めていません。(手持ちの2716が古すぎるせいなのかも...)


ドライバソフト


このROMライタのドライバソフトはOS-9上で動作するもので、コマンドも多く、データのスクリーンエディットもできるなど機能豊富なものですが、OS-9は一般的ではないので、他のOS(?)に移植しなければなりません。
とりあえずそのままOS-9上で動作させるということでしばらく触れていなかったOS-9を走らせてみましたが、使い方をかなり忘れてしまっていて、思い出すのに苦労しています。
(でも

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日のブログで公開しています。