フォト
無料ブログはココログ

MyList

Arduino

2025年2月 9日 (日)

CH559picoでTOYOSHIKI-BASIC (2)

CH559picoをCH55xduinoで豊四季BASICを実装したら何か変なので調べてみた。
実行したプログラムは、8Qeen問題を解くプログラム↓
豊四季BASICはtiny-basicだから WHILE が無いので IF と GOTO でループしている。
昔はこんな書き方だったよなぁ...


1  REM 8Qreen
10 T=(1=1); F=(1=2)
20 D=F
30 N=1
40 FOR I=1 TO 8; @(I)=0; NEXT I
50 X=1;Y=2;@(1)=1
100 REM
100 GOSUB 2000; REM Check
110 REM if C=T then
110 IF C=F GOTO 140
120   @(Y)=X; Y=Y+1; X=1
130   REM if Y=9 goub PrintTable
130   IF Y=9 GOSUB 3000
140   REM if C#F endif
140   IF C#F GOTO 190
150   X=X+1
160   IF X=9 Y=Y-1; X=@(Y)+1; @(Y)=0
170   IF X=9 Y=Y-1; X=@(Y)+1; @(Y)=0
180   IF Y=0 GOTO 210; REM End
190   REM EndIf
190   IF D GOSUB 3000
200 GOTO 100
210 REM END
210 STOP

2000 REM
2010 IF Y=9 C=F; RETURN
2020 C=T
2030 FOR L=1 TO Y-1
2040   IF @(L)=X C=F
2050   IF @(L)-X=Y-L C=F
2060   IF X-@(L)=Y-L C=F
2070   IF D PRINT "X=",X," Y=",Y," @(",L,")=",@(L)," C=",C
2080   IF C=F L=Y-1
2090   NEXT L
2100   IF D PRINT "< ",X,",",Y,":",C
2110 RETURN

3000 REM
3010 PRINT "--- ",N," ---",
3020 IF D PRINT X,",",Y,
3030 PRINT
3040 FOR L=1 TO 8
3050   FOR M=1 TO 8
3060     REM IF Y#L then
3060     IF Y=L GOTO 3090
3070       IF @(L)=M PRINT "|Q",
3080       IF @(L)#M PRINT "| ",
3090     REM else
3090       IF Y#L GOTO 3120
3100       IF X=M PRINT "|-",
3110       IF X#M PRINT "| ",
3120     REM EndIf
3120   NEXT M
3130   PRINT "|"
3140 NEXT L
3150 PRINT
3160 IF D INPUT A
3170 N=N+1
3180 RETURN


2060 IF X-@(L)=Y-L C=F

この行は必ず Flaseになる?
豊四季BASIC linux版で↑のソースを動かすと正常に動く。

PEEK() 関数を実装して中間言語バッファをダンプしたら中間言語は正しく変化されているようだった。

1 PRINT REM ABC
2 PRINT I-@(J)

00 0B 01 00 08 05 22 41 42 43 22 2A 0D 02 00 0B
28 08 14 20 18 28 09 19 2A 17 28 00 0A 29 0E 53


bacic.cppのipuluse()の戻り値 value の値がおかしいことが判った。
5行目の imul(),20行目の imul()の戻り値は正しいが、25行目で 0を返してしまう?

 1: // add or subtract calculation
 2: short iplus() {
 3: short value, tmp; //値と演算値
 4:
 5: 
value = imul(); //値を取得
 6: if (err) //もしエラーが生じたら
 7:   return -1; //終了
 8:
 9: while (1) //無限に繰り返す
10:  switch(*cip){ //中間コードで分岐
11: 
12:   case I_PLUS: //足し算の場合
13:     cip++; //中間コードポインタを次へ進める
14:     tmp = imul(); //演算値を取得
15:     value += tmp; //足し算を実行
16:     break; //ここで打ち切る
17: 
18:  case I_MINUS: //引き算の場合
19:    cip++; //中間コードポインタを次へ進める
20:    tmp = imul(); //演算値を取得
21:    value -= tmp; //引き算を実行
22:    break; //ここで打ち切る
23:    
24:  default: //以上のいずれにも該当しなかった場合
25:     return value; //値を持ち帰る
26:  } //中間コードで分岐の末尾
27: }


↓ -@(L)+X のように書くと正しい答えになる?

2060 IF -@(L)+X=Y-L C=F

1週間くらい悩んでいたのだが、このページにヒントがあった。
8Qenn(2011/09/15)←自分のページかいっ!!

SDCCは関数を呼ぶときの引数はレジスタ渡しにしたり、関数内のローカル変数をレジスタに割付けたりする。
このような関数に再入すると変数を上書きしてしまう。
スタックを使用するにはコンパイル・オプション --satck-auto を指定する必要があるが、ライブラリも --stack-autoでコンパイルされている必要がある。
CH55xduinoのコンパイルオプションに --satck-auto を追加したら、CH55x用ライブラリがコンパイルできなかった。

関数を __reentrant 修飾すると、その関数は再入可能な関数になる。
ttbasic.cpp内の iexpから呼び出される関数を __reentrant 修飾したら、期待した結果になった。

20250125-143220

CH55xduinoのライブラリは --int-long-reent, --float-reentでコンパイルさてているらしいのが、--stack-autoではないらしいのでどこかで不具合が出るかもしれない。



最近の投稿】【最近のCPUボード】【最近のプログラミング】【2019の投稿】【2018の投稿】【2017の投稿】【2016の投稿】【2015の投稿

2025年1月26日 (日)

CH559picoでTOYOSHIKI-BASIC

今年の目標の一つ
積んCPUを使ってみることにした。

2020年に買ったCH559pico を使ってみることにした。
CH559picoボード↓
Ch559pico

CH559はざっくり8051core+USB I/F+Flash 60KB+RAM 6KBだ。

単体でBASIC 52が動きそうだ。
USB I/FがあるのでCDCクラスを実装すると、USBコネクタに刺すだけでお手軽BASIC マイコンになりそうだ。
昔、EZ-USBで遊んでいたときに、思いついたのだが、EZ-USBはメモリが少なくて実現出来なかった。

CH55xシリーズはarduinoIDEで開発できることがわかった。
しかも、CDCクラスのシリアルデバイスとして認識する。
何とお手軽

ここを参考にCH55xduinoをインストールし、blinkを書き込むとあっけなく動いた。
先達に感謝

arduinoでシリアルの入出力は、aerial.begin()で初期化してaerial.Read、Serial.write()でデータを送受信する。
USBSerialでは関数に先頭にUSBをつけてUSBSerial_Read()
Serial.Begin()での初期化は必要ない。

こんなスケッチを書いUSBシリアルのループバックテストをやってみた。

void setup() {
  while (!USBSerial());
}


// the loop function runs over and over again forever
void loop() {
  uint8_t c;

  if (USBSerial_available()) {
    c=USBSerial_read();
    USBSerial_write('[');
    USBSerial_write(c);
    USBSerial_write(']');
  }
}

1字づつ送受信出来ることが分かった。
大量のデータを転送するなら、パケットサイズを大きくして一度の転送で多くのデータを送受信した方が効率が良い。
今回は、BASICのコンソールに使うので、速度よりリアルタイム性が重要だ。BASIC52を実装する前に、
鈴木哲也氏の著書「タイニーBASICをCで書く」で、豊四季BASICがarduinoに実装されているのを思い出したので、これを動かしてみることにした。

arduino用の豊四季BASICはこのページ(https://vintagechips.wordpress.com/2015/12/06/豊四季タイニー BCbasic確定版 /)のリンクからダウンロードできる。

豊四季BASICは、c_getch, c_putch, c_kbhit, rand, を環境に合わせて実装すれば動くようになっている。
書籍では、Serial.read(), Serial.write(), Serial.available()を使う方法が説明されている。

今回は、USBシリアルを使用するので、

#define c_getch(c) USBSerial_read(c)
#define c_putch() USBSerial_write()
#define c_kbhit()  USBSerial_available()

rand() はCH55xduinoのコンパイラsdccにもあるのでそのまま使える。
rand()に使用するシードの初期化は、randomseed()になるべくランダムな値を使用しする。
組み込み用のCPUではアナログポートから読み取った値を使う方法が紹介されている。
今回は、USBシリアルの初期化が終了した時刻を取得してシードとした。

randomseed(moicros());

arduinoIDEのシリアルの設定をCOMx(CH559picoが認識されているポート)にすると、シリアルモニタが使える。
arduino用豊四季BASICは、ttbasic.ino 内のloop() から、ttbasic.ccpのbasic() 関数を呼び出している。 
arduinoIDEで検証(Check)すると、キャストのwarningが出るが、コンパイルできて、USB経由で書き込むことができる。
書き込むと自動的にリセットされて、バナーが表示されるはずだが、いくら待っても表示されない。

ENTERを連打すると、バナーが表示され、> OK がたくさん表示される。
コマンドを入力してもエコーバックされず、一定数キー入力するとまとめて入力されているようだ。

テストプログラムを書いて調べたら、
loop()の外でUSBSerial_read()を呼ぶと1文字づつ取得できないことが判った。

豊四季BASICはbasic()関数内の無限ループで、c_gets()で1行取得し、処理するようになっている。
c_gets()関数も、関数内のwhileループでENTERまで文字をバッファに格納するようになっている。

loop()関数の中なら1文字づつ取得できるので、basic()を初期化部、1行取得部、処理部に分けて、初期化部をsetup()に書いて、loop()内で1行取得して、BASICの処理部を呼ぶようにしたら、動くようになった。

ところが、INPUT A を実行しようとすると、1文字づつ取得できない。
調べてみると、INPUTコマンドで入力する数字を数値に変化する関数 getnum()のwhileループ内で文字入力していることが分かった。

c_gets(),getnum()で使用する文字入力でloop()を呼ぶようにすればよさそうだが、loop()関数内でarduinoの内部関数を呼んでいると良くないことが起こりそうだ、と考えソースを見てみたら、

main()関数の中の無限ループがloop()を呼ぶシンプル構成だった。
CH55xduinoの main()の部分

void main(void) {
  init();

  //!!!initVariant();

  setup();

  for (;;) {
    loop();
    if (1) {
#ifndef USER_USB_RAM
      USBSerial_flush();
#endif
      // serialEvent();
    }
  }

  //    return 0;
}
 

よく見ると、無限ループの中でUSBSerial_refresh()
を実行していることを発見した。
どうやらこれが解決方法のようだ。

ということで、
c_gets(), getnum()の中のループから、USBSerial_flush()を実行するように書き換えたら動いた。

BASICが動くようになったらお約束の8queen問題を解くプログラムを書てみたら挙動がおかしい。
同じプログラムを豊四季BASIC linux版で動かしたら正常だった。
A=5, B=2, @(2)=3 のとき、A-@(B)の結果が 0 になっている。

つづく...



最近の投稿】【最近のCPUボード】【最近のプログラミング】【2019の投稿】【2018の投稿】【2017の投稿】【2016の投稿】【2015の投稿

2019年3月 3日 (日)

Line tracer <ちびギアモータ>

ネットでギアードモーターを探していたらこんなのを見つけた。

Photo

 ちっちゃいものくらぶが領布している「ちびギアモータ」 プリ―付きで400円だ。

 ギアードモーターはモータと減速機構が一体になったモータで、外部にギアボックスが不要になる。

業務用は当然だけど高い。
千石で模型用の安いのを探してみると1000円~2000円くらいだ。
ギアがプラスチックでよければこんなのもある。


↑(https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-0F4C)

「ちびギアモータ」は他のギアードモーターとくらべて消費電流が少ないようだ。

〇プラスチックギヤードモータ」(千石)
 電源電圧6V 無負荷時消費電流:120mA、無負荷時回転数23~28rpm

に対して

〇「ちびギアモーター」(ちっちゃいものくらぶ)
 動作電圧 3~6V、5V無負荷時:35mA、回転数120rpm

 AVRのGPIOで直接駆動できるらしい。
消費電流が大きいとトランジスタやFETでドライブしなければならないから部品が増えるけど、GPIOで直接駆動できるならとてもお手軽だ。

AVRの絶対最大規格はピン当たりの出力電流は40mA、デバイス全体の消費電流は200mAだから「ちびギアモーター」2個は回せそうだ。

負荷をかけるとピン当たりの制限に引っかかりそうだが、超えたらからといってすぐに燃えたりしないだろう。そのあたりは売り物にするわけではないので勝手にやれば良い。

 プーリーにはφ25でOリングがはめてあるのでタイヤに使える。 台車にモータとタイヤを付けてまっすく走るだけでは面白くないので、ライントレースをやってみよう。

2012年9月23日 (日)

Android+microbridgeでネギ振り

Android + microbidge + arduino + hostShield でサーボが動いたのでネギを振ってみた
Negifuri

アプリはこんな感じz
Negi_app

gifを表示してBGMを流して、加速度センサーの出力を読んで45°~135°になるように変換してarduinoに送るだけ。
arduino側のF/Wはmicrobridgeに含まれるDemoが使える。

アプリを実行した LifeTouchNoteを振るとミクがネギを振る
Nefifuri_movie

←リンク先にAVI

昨日参加した勉強会でやったらウケた。v(^^

2012年9月18日 (火)

Android+microbridgeでI/O制御

HostShieldそっくりさんができたのでAndroidと繋いでみた。
スマホは使っていないので(裸眼で使えそうなスマホはラクラクホンしかない)LifeTouchNoteを使った。LTNはAndroid2.2でAOA(
Android Open Accessory Protocol )をサポートしていないのでmicrobridgeでLTNと繋いだ。

 microbridgeは、ADBを利用して制御するハードに接続するのでUSBデバッグを許可するとどのバージョンのAndroidでも使える。USB-Host機能を持ったハードからADB経由で tcp:xxxxを実行し、Android上のアプリはlocalhost:xxxx経由でハードと通信を行う仕掛けだ。

 microbridgeのサイトからHostShieldのF/W(MicroBridge-Arduino.zip)とAndrodのアプリ(ServoControl.zip)をDLしてサーボを制御するデモを実行してみるとうまく動かないので、パッチを当てた。

  • HostShieldのRESET,GPXの配線が逆
    原因:
    DEV-09628
    の回路図を参考にしたのでRESETとGPXの配線が逆になっていた。DEV-09628のページにも説明がある。(DEV-09947はサンプルソースのとおりになっているようだ)
    対策:
    max3421e.hの#define PIN_MAX_GPX 8 #define PIN_MAX_RESET 7 を書き換えて逆にした。
  • HostShield初期化時に"Error: OSCOKIRQ failed to assert"が出力される
    原因:
    MAX3412Eは電源ONの際に、内部の48MHzPLL発振器が外部の12MHzX'tal発振器にロックすると割り込みを発生する。
    max3421e.cppの max3421e_reset()関数で、この割り込みを待っているのだが、タイムアウト用の変数を8bit(unit8_t tmp)で宣言しているため、PLLがロックする前にタイムアウトが発生している
    対策:
    uint16_t tmp にした。
  • LTNが認識されない(10回に9回は認識に失敗する)
    原因:
    Adb.cppのADB::isAdbDevice()関数でコンフィグデスクリプタの取得に失敗している(getConfigurationDescriptor()の戻り値が負)
    対策:
    getConfigurationDescriptor()の戻り値が負ならばもう一度実行するようにした。

 HostShieldのF/Wでadb logcatしておくとAndroidのログがHostShield経由でシリアルで送られてくる。
Logcat
AndroidはUSBでHostShieldと繋がるのでEclipseでデバッグできなくなるが、logcatしておくとログを確認することができるようになる。

 Android側のアプリ(ServoControl.apk)はこんな感じ
Servocontrol1

画面上の赤い四角をドラッグするとサーボが動く。(このデモはX,Y 2ch分の制御が可能なのだがサーボが1個しかなかった。)
画面左上の赤いバーはArduinoのアナログ入力値を表示している。(アナログ入力ピンには何も繋いでない。)

 microbridgeを使用するアプリはsocketを使用するのでManifestでINTERNETアクセスを許可しておかなければならない。
簡単に動くと思っていたらまったくアプリが起動せず、INTERNETアクセスの許可していないことに気付くまでちょっとハマってしまった。(ログを見て気がついた。)


sparkfunのDEV-9947のリンクが間違っていたので、そ~っと直した。(2012/9/18)

2012年9月14日 (金)

USB Host Shield

Arduino用ユニバーサル基板 UB-ARD03でUSB Host Shieldを作った
Hostshield2

MAX3412Eを使ったSparkfunのUSB Host Shield(DEV-09947 DEV-0926) そっくりさんである。
(2012/9/18:そっくりさんを作るなら、サンプルソースを変更しなくて良いので DEV-09947を参考にしたほうが良い。)
MAX3412EはDigikeyから\1,161で買った。DEV-09947はスイッチサイエンスで\2,495だから、そっくりさんを作ってもそんなにお得ではなかった。
MAX3412E
は32pin-TQFPなので素直にピッチ変換基板を使ったらユニバーサル部分がなくなってしまったので、ソケットを使って浮かしてピッチ変換基板の下に3端子レギュレータを実装している。

Hostshield

なんだか空母状態になっている。
一番下が秋月のATMega168/328基板を使ったArduinoそっくりさん、手前が秋月のAE-UM232Rそっくりさん、奥側がSparkfunのUSB HostShieldそっくりさん。
 オープンソースばんざい。

2012年9月 8日 (土)

Arduino用ユニバーサル基板

Arduino用ユニバーサル基板 UB-ARD03

 サンハヤトのArduino用ユニバーサル基板 UB-ARD01↓は
Ubard01

秋月のUSBシリアル変換モジュールATMEGA168/328用マイコンボードにソケットで実装した場合、USBシリアル変換モジュールに干渉すると書いた。

 最近サンハヤトから寸法の短いUB-ARD03が販売されてたようなので、さっそく買ってきた。(基板の色は緑だけのようだ)
Ubard031

Ubard03

干渉しない。これならOK

2012年8月 6日 (月)

Arduinoそっくりさん

作りかけて放ってあった、秋月の「FT232RL USBシリアル変換モジュール(AE-UM232R)」そっくりさんを作った。
Aeft232_clone Aeft232_clone1_2

FT232RLを使った、ただのUSB-Serial変換アダプタだ。

 FT232RLをSOPのピッチ変換基板に載せて、コネクタ、コンデンサ類は千石で売ってるフレキシブル基板(曲がる万能両面基板両面スルーホール)をはさみで切って使った。

 なぜ、わざわざAE-UM232そっくりさんにしたかというと、秋月のArduino互換基板を持っているからである。
Img_5860

AE-UM232にソケットを使うと、シールド基板と干渉することは知っていたのだけれど、本当に干渉する。
Universalsheeld

秋月C基板で作るか
Akizukic

ホストシールドを作るためにMAX3421EはDigikeyで買ってある。

 ここを参考すzのAVR研究所 にあるFT232RのBitBangが使えるavrdudeを使ってBootloaderを書いて、サンプルスケッチをロードするとちゃんと動いた。
Arduinoide

 AVRの書き込みは、arduinoISP+avrdude+avrdude-GUIを使っている。
学研のjapaninoも買ったのだがarduinoISP専用になっている。)
本家のavrdude-GUI 1.0.5はFlashメモリに書くデータファイルをうまく指定できなかった。

ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。

と叱られる。

ソースも公開されているので読んでみようかと思っていたら、既にパッチを当てている人がいて修正版が公開されていた。
(横着しないでコマンドラインで使えば良いんだけど...)