人気ブログランキング |

体重と今日食べたもの

k1segawa.exblog.jp

ダイエット

ブログトップ

カテゴリ:ポケコン( 50 )

SPI通信について。

スレーブ(SPIモジュール)によってSPI通信のサポートする種類が異なるようだ。

SPI通信といってもクロックの立上がり・立下りでデータを取り出すようにインプリメントするケースや、
最初のMSBFをクロックの最初から取り出すか、1CLK待ってから取り出すようにインプリメントするかを、スレーブが選べるようにしている。

従って4種類あって、MCP3002はそのうちMODE0,0(モード0)とMODE1,1(モード3)の形式のSPI通信をサポートしているようだ。

MCP3002データシート15ページ目図6-1,2

だからと言ってモード0と3を切り替えられるわけではなく、両方とも立上がりでデータを取り出すモードなだけだ。
MSBFも余り神経質にならずにその前に続くStartビットからの流れで取り出せばよく、モード0と3の違いが余りわからない。(下記サイト様のSPIの罠様にはきちんと書いてある)

SPI通信のモードに関しては、以下のサイト様が参考になった。
SPIについて
SPI Transfer Modes | USB-I2C/SPI/GPIO Interface Adapters
SPIの罠

0,0と1,1は立上がり、0,1と1,0は立下りでデータを読み書きする。

SPI通信ができたといってもMCP3002の場合だけなので、別のSPIモジュールの時は同じ手順とは限らないという事。
さらにモードの呼び方まで統一されてないらしい(SPIの罠様参照)ので、きちんとタイミングチャートとモードの対応をデータシートで確認する事。

SPI通信は同期(外部クロックが要らない―自分でクロックを作って送り込める)通信で、かつ単方向信号(双方向でない)なのに、信号線が独立しているからスピードも出る。なのでSDカードの読み書きもSPI通信。
SDカードの構造と内部レジスタ(その1) | ミームス(MEMEs)のサポートページ様や浅草ギ研 A33FでMicroSDカードにアクセスしてみる様などでは、詳しいSD用コマンドが解説されているので、SPI通信の応用にいいかもしれない。
by k1segawa | 2015-06-08 19:51 | ポケコン | Comments(0)
そろそろ電池が消耗してきたので、プログラムをPCに退避。

主にTEXTモードで保存した場合を示す。

(1) 12/14の記事を見てケーブルを繋ぐ。
(2) デバイスドライバでCOMポート番号を確認。
(3) 1/4の記事でTeraTermの設定を行う。(128x24にしておくと後で助かる)
(4) ポケコンのTEXTボタン>F(ile)>L(oad)で、LOAD →と出るのでカーソル移動して保存したいプログラムを選ぶ(リターン)。(マニュアルP.177)
※この時BASIC中間コードで保存してある場合、マニュアルP.177によれば、エラー(FILE MODE ERROR)になるので、その時は別途記述する。
(5) << PROGRAM FILE >>というメニューに戻るので、TEXTボタン>S(io)>S(ave)で、PCへ送出。
(6) TeraTermの画面にプログラムが表示されるので、マウスで先頭から末尾+空行1行辺りまで選択して、コントロール+Cを押す。
(7) テキストエディタを開き、余計なものがあってもいいように、コントロール+Aで全選択し、コントロール+Vで上書きする。
(8) (4)でLOADした時の名前を参照する。
(9)名前を付けて保存で、LOADで選択した時の名前を付けて保存する。
(繰り返す場合)
(10) (8)で次のファイルを選択する。
(11) TeraTermの画面でEdit>ClearScreen、Edit>ClearBufferと実行し、余計なものを消す。
(12) (5)に戻って以下同じ。

【ポケコンの方の設定】
TEXTボタン>S(io)>F(ormat)
9600,8,1,none,CR LF,1A,yes,RS/CSに設定

書くととても面倒だが、ポケコン側は単に
TEXTボタン:*** TEXT EDITOR ***モード
└→ F(ile):<< PROGRAM FILE >>モード>L(oad)
もう一度TEXTボタン:
└→ S(io):<< SIO >>モード>S(ave)
を繰り返しているだけ。(たまに間違ってFの代わりにLを押して"--- PRINTING ---"と出るけどONキーをちょっと長押しすれば戻る)
TeraTermも単に受信した文字列をコピーし、画面をクリアしているだけ。
エディタも貼り付けられた文字列を名前を付けて保存しているだけ。(※TeraTermの80行を超える長い行はコピーして貼り付けると改行が付加されるので、行番号のない行は前の行とくっつけて1行に編集する事。あらかじめTeraTermを80x24から128x24ぐらいに変更しておくとよい)

通信さえ整っていれば、これを繰り返しているだけ。通信は最初から全く変更していない。

※LOADでエラーの時は、BASICボタン>LOAD"そのファイル名"で読み出すか、
TEXTモードのように、BASICボタン>FILES(リターン)と入力し、SHIFT+M(LOAD)(マニュアルP.159)で読み出すこともできる。
LOADしようとしたファイルがTEXTだった場合、ERROR 96(マニュアルP.386)が出てBASICじゃない旨を教えてくれる。
その後、TEXTボタン>B(asic)>Text←basicでBASICをTEXT変換する。
この時TEXTプログラムを削除するかY/Nで聞いてくるので、必要ならTEXTを保存してからTEXT変換する。
BASICプログラムとTEXTは両方同時にメモリに存在できるので、落ち着いて行う。
by k1segawa | 2015-06-08 13:50 | ポケコン | Comments(0)
念の為BASICでも構造化してみた。構造化はPC-G8系?G85系からなので、PC-E5系はPC-E650とPC-U6000だけかな。

前回のCプログラムを直す形にしたので、PEEK、POKE文によるPC-E5系のINP/OUTの代替命令は残していない。

【構造化BASICでのSPI通信によるA/D変換】
DIM A(33):I=0:X=-1

CLS
OUT &H60,1
OUT &H61,1

REPEAT
READ A(I):I=I+1
UNTIL A(I-1)=99

WHILE 1

C=10:D=0:I=0
WHILE A(I)<>99
OUT &H62,(A(I) AND &HFE)
IF (A(I) AND 1)<>0 THEN
A= INP &H62
IF C<>10 THEN
IF A=1 THEN D=D+(2^C)
IF C=0 THEN
W= INT (D/8)
IF X<>W THEN
LINE(X-(X<W),0)-(W-(X>W),15),X,BF
X=W
ENDIF
ENDIF
ENDIF
C=C-1
ENDIF
I=I+1
WEND
WEND
DATA 0,2,6,2,6,0,4,2,6,0,5,0,5,0,5,0,5,0,
5,0,5,0,5,0,5,0,5,0,5,0,5,8,12,99
INTは関数なのでマニュアルの先頭に載っている。ただし、Cのintとは負の値の扱いが異なるのでFIX(こちらはBASICの命令)が本来正しい。まあ負の値を取らないのでCに字面だけ合わせてあるが。(X<W)の論理値は、Cの場合の真の値(1)と異なり-1なので符号を逆にしてある。またLINE文はX=XOR、BF=長方形塗りつぶしで、XとBFの間のパターンは省略している。あとREPEAT-UNTILやWHILEなので制御変数Iの初期値や判定が微妙に違うので(太文字)注意。

やっぱり実行すると遅い。Cプログラムと同時にメモリに存在できるので切り替えて実行するとよくわかる。

でもBASICも構造化するとループの範囲や意図が分かり易いし、なによりポケコンの狭い画面でも、横はタブを1にして書くと、Cと違ってセミコロンがない分、何とか収まるし、中かっこでなくENDIFやWENDなので縦も対応が分かり易い。ポケコン上でデバッグしやすい。(Cは一度ノートに書いて入力し机上デバッグする方がいい-画面狭いので)

おしいな~。これでBASICコンパイラがついてれば構造化BASICならプログラムの入門には最適だな。
だれかPC-E5系のBASICコンパイラBASCOM(BASC102)の構造化BASICへの移植してくれないかな~

【独り言・・・】
ソフト屋さんなので、入れ子構造が見やすい(BASICやCで育った人)と感じるが、ハード屋さんは前の構造化しない方のプログラムの方が見やすいのだろうな~。BASICに限るが、一行一行見て理解する形だと、GOTOのラベルの方が、単なるブロックの}やENDIFより意味がすぐわかるから。全体を見渡すよりべたっとしたリストを好む気がする。もちろん慣れの問題もあると思うが。Cも入れ子構造があまりに深いとわかりづらいから程度問題か。
Cで書いていても、ソフト屋さんは、for、whileのなるべく単純な制御構造に当てはめようと問題自体の分割やアルゴリズムを簡素なものにできないか再検討をするが、ハード屋さんのソースはどこかそういうループに特殊な脱出条件を追加したまま複雑化している気がする。きっとそこまで手間をかけるかどうかなんだろう。
by k1segawa | 2015-06-07 23:44 | ポケコン | Comments(0)
センサーを付け替える前にちょっとビジュアライゼーション。

アナログ入力を表現するのに、動的な棒グラフでキャッチ―にしてみた。

【ポケコンによるSPI通信(A/D変換)】
main() {
unsigned char a[34]={0,2,6,2,6,0,4,2,6,0,5,0,5,0,5,0,
5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,8,12,99};
int c,d,i;
unsigned char r;
int x=-1;int w;

clrscr();
outport(0x60,1);
outport(0x61,1);

do {

c=10;d=0;i=-1;
do {
outport(0x62,(a[i] & 0xFE);
if((a[i] & 1)!=0) {
r=inport(0x62);
if(c!=10) {
if(r==1)
d+=(1<<c);
if(c==0) {
w=(int)(d/8);
if(x!=w) {
line(x+(x<w),0,w+(x>w),15,2,0xFFFF,2);
x=w;
}
}
}
c--;
}
} while(a[i++]!=99);
} while(1);
}
最初のCS=HIの8は要らないみたいなのでデータから削除。d(アナログ値)をx方向で表現。(0,0)-(アナログ値,15)の長方形の伸び縮みで表す。/8≒1024/144(最大x座標)。wは内部計算を少なくするため。
xは前回のx座標。line文は後ろ3つが2=XOR、0xFFFF=塗り潰しパターン全て、2=長方形塗り潰しを示す。(x<w)は論理値が真なら1、偽なら0を利用。<、>はブログの制限で全角。

youtube:ポケコン SPI通信でアナログ入力
a0034780_2125019.jpg


processingみたいにデザインに凝ると単なるデータもありがたみが増す。昔のNECのPCの画面がジャン=フランソワ・ミレーの絵画「落穂拾い」だったようなもの。
by k1segawa | 2015-06-07 21:10 | ポケコン | Comments(0)
今までポケコンで、以下のようなデータの入出力を色々やった。
1.デジタル出力
2.デジタル入力
3.アナログ入力

1番はよくあるLEDを光らせるやつ。
応用としてシフトレジスタを使って1ポートで7セグを点灯させた。
少ない出力ピンで多くの信号を制御する。
デジタル出力であとやってないのはLEDをPWM制御で調光することかな。

2番はスイッチのON/OFFを読み取るやつ。
基本だが、プルアップ・プルダウン抵抗を理解しないと進めない。
応用としてパラレル-シリアル変換ICからの複数スイッチの入力など。
少ない入力ピンでたくさんの信号を受け取れるようにする。

3番はA/D変換ICの入力。
アナログ値を入力するのに、MCP3002というICで、電圧値をデジタル入力に変換して取り込む。
ポケコンでSPI通信ができることが分かったのが収穫。
応用としてタッチパネルや複数のセンサー切り替えや無線によって遠隔地のデータを取り込んだり。

次にI2Cをやろうとしたが、双方向インターフェースというのが必要だった。
SPIは単方向の信号つまり入力か出力に特化したピンでやり取りするのだが、
I2Cは1個のピン?で入力も出力もこなさなければならない。いわゆるバスってやつだ。
ポケコンにもPC-G850Vにはバスが出ていて、命令もシステムバス命令で用意されているが、まだ11ピンしか使ったことがないので敷居が高い。
どうにかできないかと調べていたら、こちらのサイト様にGPIOで出来るようなことが書いてあった。

2.3.4.1. GPIO初期化関数
【以下引用】
ここで注意したいのは、ポートを出力として設定するタイミングです。
今回接続するLCDモジュールは、R/WがHレベルになると、データバス
(DB0-DB7)からデータが出力されます。このときマイコン側もピンが
出力設定になっていると、電気的にショートしてマイコンや
LCDモジュールが破壊されてしまう危険があります。
 例えばマイコン側の出力ピンがHレベルになっている場合には、
マイコン内部でピンが+電源に接続されています。
そしてモジュール側でピンがLレベルになっている場合には、
そのピンは-電源に接続されています。
そうするとこれらのピンが接続されてしまうと、結局は、
+電源と-電源が直接に接続されたのと同じになってしまうのです。
 そのためマイコン側のポートを出力として設定する前には、
LCDモジュール側を確実に入力に設定(R/WをLレベルにする)
しておく必要があります。
 なおこの問題はLCDのモジュールに限ったことではなく、
データの出力と入力を兼用するデバイス全般との接続において注意
すべきポイントです。
【ここまで】

ずっと入出力兼用のピン設定がないか考えていたが、入出力モードを切り替えて使えばいいらしい。
ただプルアップや何かの信号がモード切替のタイミングでHIにならないように、回路設計と相手機器をコントロールしないといけないみたい。

うん。敷居が高いな。SPIができるようになったのだから、I2Cはとりあえずおいておこう。
まだ外部電源の実験やアナログ入力の応用も手広く残っているし。
by k1segawa | 2015-06-07 17:16 | ポケコン | Comments(0)
少し間違っているのと、ちょっとだけCっぽく構造化したのを書いてみる。

まず、間違いはpsetの文の次のxの144を越さないようにした行。グラフィック座標は(0,0)-(143,47)なので、144と比較して偽なら0になるので0*x=0にしているのだが、その行は本来if文が{}で括られていなければ条件成立時に実行されるようにならない。まあでもこれでもxをインクリメントしてなくても実行しても問題ないので、影響なかったという事。22は≒1024/47である。

あと、このC特有の機能(マニュアルに書いてあった)だが、自動変数の配列の初期化を最初にやっているが、本来staticかグローバルでないと初期値は入れられない。スタックが毎回初期化されるってこと。

それとoutput関数は0x20までとマニュアルには書いてあるがopenしないで使ってるから0x60とか使えているのかな?

で構造化してみたのがこちら。

main() {
unsigned char a[35]={8,0,2,6,2,6,0,4,2,6,0,5,0,5,0,5,0,
5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,8,12,99};
int c,d,i;
unsigned char r;
int x=0;

clrscr();
outport(0x60,1);
outport(0x61,1);

do {

c=10;d=0;i=-1;

do {
outport(0x62,(a[i] & 0xFE);
if((a[i] & 1)!=0) {
r=inport(0x62);
if(c!=10) {
if(r==1)
d+=(1<<c);
if(c==0) {
pset(x++,d/22,1);
x=(x<144)*x;
}
}
c--;
}
} while(a[i++]!=99);
} while(1);
}
普通はdo {} while() じゃなく while() {}を使うのだが、末尾の{}の対応が、画面の狭いポケコンでは付けづらいのであえてdo-whileにした。BASICならWENDなのでこんなことしないでもIF文のブロックと区別がつく。
また99との比較を末尾に置いたのでデータは必ず99以外で始まることが前提となる。

この方がgoto文やラベルが無くなって、ループの範囲と意図が伝わりやすい。
さらにコメントも入れてみたが、よけいわかりづらくなった。関数は短くシンプルに。コメントが不要なくらいに。

変数cもデクリメントを条件文の中に入れてもいいが、やりすぎてわかりづらいのでやめた。

BASICも構造化した方が分かり易いかな?

やっぱり構造化言語にとってポケコンの縦も横(タブ2がせいぜい)もスクリーンが小さすぎるな~
by k1segawa | 2015-06-06 00:22 | ポケコン | Comments(0)
A/D変換した値をちょっとグラフにしてみた。

【Cプログラム】
10 main() {
20 unsigned char a[35]={8,0,2,6,2,6,0,4,2,6,0,5,0,5,0,5,0,
5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,8,12,99};
25 int c,d,i;
26 unsigned char r;
27 int x=0;
28 clrscr();

30 outport(0x60,1);
40 outport(0x61,1);
50 INIT:c=10;d=0;i=-1;
60 READ:i++;
70 if(a[i]==99) goto INIT;
90 outport(0x62,(a[i] & 0xFE);
100 if((a[i] & 1)==0) goto READ;
120 r= inport(0x62);
140 if(c==10) goto NEXT;
150 if(r==1) d+=(1<<c);
160 if(c==0) pset(x++,d/22,1);x=(x<144)*x;
170 NEXT:c--;
180 goto READ;
190 }
a0034780_21313284.jpg

可変抵抗にしてみたんだけどね。
by k1segawa | 2015-06-02 21:32 | ポケコン | Comments(0)
Cでも組んでみた。
BASIC配列化プログラムに似せて書いてある。

【Cプログラム】
10 main() {
20 unsigned char a[35]={8,0,2,6,2,6,0,4,2,6,0,5,0,5,0,5,0,
5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,8,12,99};
25 int c,d,i;
26 unsigned char r;

30 outport(0x60,1);
40 outport(0x61,1);
50 INIT:c=10;d=0;i=-1;
60 READ:i++;
70 if(a[i]==99) goto INIT;
90 outport(0x62,(a[i] & 0xFE);
100 if((a[i] & 1)==0) goto READ;
120 r= inport(0x62);
140 if(c==10) goto NEXT;
150 if(r==1) d+=(1<<c);
160 if(c==0) printf("%d\n",d);
170 NEXT:c--;
180 goto READ;
190 }
大文字のジャンプ先ラベルやgoto命令を残した。BASICなら配列Aと変数Aは別物なのだが、Cはそうもいかないので変数Aは r に置換。8,12,は1拍に直して、「<<」はタグの制限で全角にしてある。

実行した結果は、BASICの10倍くらい。

あと配線図も以下に示す。
a0034780_2131549.jpg

MCP3002は部品図になかったので足の数が同じICで代替。(左がICの凹みがある方)
(6/8訂正:抵抗の繋ぐピンを5→4ピンに修正。赤丸の所。プルダウン抵抗になっていなかった)
by k1segawa | 2015-06-02 01:23 | ポケコン | Comments(0)
BASICプログラムを配列化してみたけどあまりスピードは変わらない。READが遅いと思ったがそんなことはなかったという事。ついでにCS=HIにするのを最後2拍にしたのを1拍にしたが、悪いことは起きなかった。DATA文の最後の「8,12,」は不要という事で。

【BASIC配列化プログラム】
10:*MAIN DIM A(34):I=0
20:REM POKE &H60,1,1
30:OUT &H60,1
40:OUT &H61,1
45:*DATA READ A(I):IF A(I)<>99 THEN I=I+1:GOTO *DATA
50:*INIT C=10:D=0:I=-1
60:*READ I=I+1
70:IF A(I)=99 GOTO *INIT
80:REM POKE &H62,(A(I) AND &HFE)
90:OUT &H62,(A(I) AND &HFE)
100:IF (A(I) AND 1)=0 GOTO *READ
110:REM A= PEEK &H62
120:A= INP &H62
130:REM NullBit SKIP
140:IF C=10 GOTO *NEXT
150:IF A=1 THEN D=D+(2^C)
160:IF C=0 PRINT D
170:*NEXT C=C-1
180:GOTO *READ
190:*RESTORE
200:DATA 8,0,2,6,2,6,0,4,2,6,0,5,0,5,0,5,0,5,0,
5,0,5,0,5,0,5,0,5,0,5,0,5,8,12,99
by k1segawa | 2015-06-01 23:24 | ポケコン | Comments(0)
こちらのポケコンの資料を見ると、モータ制御やライントレースの方法と合わせてポケコンに繋ぐ簡単な回路が載っている。いずれこちらにも手を出すのかもしれないが、中盤以降のDownloadというボタンをクリックしてPDFを読むと、ソフト屋さんが学ぶべき基本の電子回路が載ってていいかもしれない。(それでも本当の初心者より私のようにプルダウンとか勉強した者が読まないとわからないと思う)

ポケコン搬送車?サイト様
a0034780_18394823.jpg

動画は写真をクリックするとmpgファイルがダウンロードされるので、Windows Playerで再生可。
by k1segawa | 2015-06-01 18:41 | ポケコン | Comments(0)