田舎の組み込みプログラマーがわざわざ趣味でも色々開発してみようとあがく様を綴るブログです。
DMM.makeのクリエイターズマーケットに出品しています。
ラジコン用コーナーウエイトゲージ2回目 ― 2018年11月08日
続きです。
コーナーウエイトゲージということで当然秤は4つあるわけで、HX711も4つ使っています。
なので、ロジアナでまとめて観察してみたところ、気になることが・・・
1回目の読み出しは次のチャンネルとゲインを指定するためのものなので除外するとして、それ以降のREADYになるタイミングがバラバラです。
DOUT 1(1個目のHX711のDOUT)だけは95msec弱とほぼ10SPS相当なので、それ以外はダメということになりそうです。
もしかすると、使っているHX711をモジュール化した基板でRATE端子をどこにも接続していないのが問題なのかもしれません。
その辺の調査は後回しにするとして、次にデータを見てみます。
データも見事にバラバラですね。
ゲインを64に抑えてもいますので、先頭から12ビットくらいは揃って欲しかったんですが・・・。
特にDOUT 1がいきなりFFhから始まっているのは、配線ミスやロードセルの不良も疑ったんですが、データシートを見ると測定値は2の補数形式ということなので、単にマイナスの値になっているということのようです。
この辺も使っているモジュールが推奨回路通りになっていなくて、入力抵抗が片側にしか入っていないことも影響しているかもしれません。
なので、推奨回路通りになっていると思われるモジュールを発注済みです。
中国発送のようですので、到着までまだしばらくかかりそうですが。
もうひとつ気になっていたこと
それは、割り込み中のデータシフト処理にどのくらいの時間がかかっているかということです。
これもロジアナを使って確認してみました。
割り込み処理の入り口でポートビットをオンし、出口でオフしています。
クロックの立ち下がりで割り込みをかけるようにしていますが、割り込み処理に入るまでに1.96μsecかかっていますね。
そして、割り込み処理が5.556μsec。
次のクロックまでにはまだ若干の猶予がありますが、計測結果を別のマイコンに転送することになると思いますので、そうなると割り込み処理が増えるのでちょっと厳しいかもしれません。
そんなこんなで
一応、年内にはサーキットでコーナーウエイト調整の効果を確認してみたいとは思っているんですが、こんな感じでちまちまやっていますので、どうなることやら。
ラジコン用のコーナーウエイトゲージを作ろう ― 2018年11月07日
またもや随分更新をサボってしまいました。
忙しかったと言えばそれまでですが、やはり具体的なビジョンがなければ頓挫しやすいということだと思います。
ということですので
ラジコン用のコーナーウエイトゲージを作ってみることにしました。
元々電子工作を始めようと思ったのはラジコン用の何かを作りたいというのが一番の理由で、コーナーウエイトゲージもずっと以前から作りたいと思っていた物です。
ぐずぐずしているうちに市販品が出てしまったわけですが、ロードセルとかロードセル用ADコンバータとかが簡単に手に入るようになったので、今更ながらやってみます。
で、これが試作品。
ロードセルは2kg、ADコンバータは定番のHX711、マイコンはいつものようにR8C/32Mです。
20MHzで不足とは・・・
HX711の使い方はあちこちで解説されていますが、マイコンからパルスを送ると同期してデータが出てくるという、クロック同期シリアルインターフェイス的なやつですね。
「的な」と言っているのはちょっと独自仕様が入っているからで、おかげでマイコンのシリアル通信機能が使えないわけですが、今回のように4つの物を使うとなるとクロック同期シリアルが4つも使えるマイコンなんて見当たらないので結局は自力でなんとかするしかないわけですね。
具体的には、転送クロックをタイマー機能で生成し、立ち下がりで割り込みをかけてシフトするわけですが、クロックパルスの幅は標準1μsecとかなり高速です。
この速度だと、1周期は2μsecですので20MHzだと40サイクルしかなく、この時間で4つ分のデータのシフトは無理そうというか実際無理でした。
ゆっくりしていってみる
標準はあくまでも標準ですので、ゆっくりやれば別に問題はないわけです。
が、一つ注意が必要なのはパルスがHIGHになっている時間が60μsecを超えるとHX711がパワーダウンモードに入ってしまうということです。
で、通常は50μsecまでにしろとのことですので、そこは守らないといけないわけですね。
ということで、実際の波形がこちら。
クロック周期を10μsec、HIGH時間を0.5μsecにしてみました。
具体的には、タイマRC機能でTRCIOAに出力、TRCGRAで10μsec周期を作りつつパルスの立ち下げと割り込み処理を、TRCGRCで9.5μsecの時点でパルスを立ち上げています。
どうやら10μsecもあればHX711の4個分のシフト処理は間に合うようです。
あとはメインループでHX711のデータ出力を監視し、4個全部の出力がLOWになったらタイマRCをスタート、タイマRCは1回分の入力処理が終わったら停止するように作り込んでいます。
といったところで、今回はこの辺で。
ゆっくりしていってみる ― 2018年06月13日
このところ仕事が色々大変だったり、仕事以外でもアレコレあったりしたので、ここらでちょっとゆっくりしてみたいと思います。
というわけで
ゆっ くりチップで遊んでみます。
なんかごっちゃりしていますが、PCのターミナルとR8Cマイコンをつなぎ、R8Cマイコンからゆっくりチップにしゃべらせる構成になっています。
具体的にはこんな感じです。
ゆっくりチップに対してローマ字風のコマンドを送ることで発声できます。
R8Cのソフトでは、受信割り込みでキューに入ったデータをメインループで横流ししています。
構造化アセンブラと当方オリジナルのマクロライブラリで記述していますので見慣れない感じだとは思いますが、だいたい理解していただけるのではないかと。
R8Cで仲介しなくてもPCのターミナルとゆっくりチップで直にやりとりもできるのですが(USB<->UART変換は必要)、次段への布石とい うことで。
さて
ゆっくりチップとのUARTによる通信にはいくつかのお約束があり、主なところはだいたい以下の通りです。
- ボーレートを認識してもらうため、最初に"?"を送信
- コマンドの最後にはキャリッジリターンをつける
- ">"が返ってくるまで次のコマンド送信は控える
ちなみに、発声中に次のコマンドを送ると"*"が返ってきます。
なので、その辺りの処理を実装すると、後の処理が楽になります。
$LOOP
; PC→ゆっくり
PROC$_CALL S0R$_GET ; 受信データ取得(→R0L)
for S == OFF
PROC$_CALL$_B YUKKURI_UART$_PUT, R0L
PROC$_CALL S0R$_GET ; 受信データ取得(→R0L)
next
; ゆっくり→PC
PROC$_CALL S2R$_GET ; 受信データ取得(→R0L)
for S == OFF
PROC$_CALL$_B YUKKURI_UART$_GET, R0L
PROC$_CALL S2R$_GET ; 受信データ取得(→R0L)
next
$END
;==========================================================
PART$ YUKKURI_UART
;----------------------------------------------------------
; メモリ確保
QUEUE$_B$_ALLOC yukkuri_send_queue, 128 ; 送信キュー確保
send_char: .blkb 1
;==========================================================
; コンディション定義
CONDITION$_DEFINE S_ENABLE ; [送信可能]
; ステータス定義
STATE$_DEFINE YUKKURI_BUSY ; ビジー<[]
STATE$_DEFINE YUKKURI_READY ; 送信受け付け<[送信可能]
;-----------------------------------
; ビジー<[]
;-----------------------------------
STATE$ YUKKURI_BUSY, 0
_GET
if [ PARAMETER ].b == '>'
TRANS YUKKURI_READY
endif
_END
;=======================================
;[送信可能]
;=======================================
CONDITION$ S_ENABLE
_PUT
QUEUE$_GET yukkuri_send_queue, [send_char]
for C ; キューデータあり
PROC$_CALL$_B S2T$_PUT, [send_char]
if [ send_char ] == 0dh
TRANS YUKKURI_BUSY
endif
QUEUE$_GET yukkuri_send_queue, [send_char]
next
_END
;-----------------------------------
; 送信受け付け<[送信可能]
;-----------------------------------
STATE$ YUKKURI_READY, S_ENABLE
REDIRECT _PUT
_END
_PUT
; 代替えキャラを元のコードに
R0L = [ PARAMETER ].b
if R0L == '!'
R0L = 27h
elif R0L == '$'
R0L = 0dh
endif
QUEUE$_PUT yukkuri_send_queue, R0L
THROW ; 後は STATE に投げる
_GET
PROC$_CALL$_B S0T$_PUT, [PARAMETER].b
THROW ; 後は STATE に投げる
_INIT
QUEUE$_INIT yukkuri_send_queue
PROC$_CALL$_B S2T$_PUT, "'?'" ; ゆっくりチップに同期コマンドを送る
;----------------------------------------------------------
_END
;==========================================================
といった感じです。
PART$というのは状態遷移処理を内蔵したオブジェクト的な物で、指定したメソッドをアクティブなSTATE$で処理するのが基本です。
メソッドの探査順はPART$→STATE$(アクティブ)→CONDITION$(アクティブ)となっており、対応メソッド処理が見つかった時点で打ち
切りますが、THROWで次段に投げることができ、REDIRECTで次段の別のメソッド処理に投げることができるため、非常にシンプルな記述が可能に
なっています。
という、投げっぱなしな感じで今回はここまでです。
いきなりつまづいてみたり ― 2016年11月24日
さて、システムを一から再構築すると決めた(ゼロからではないのが味噌です)ので、色々スッキリハッキリ分離させておこうと分析中です。
マイコン機能に極力依存しないシステムというのが王道なんでしょうけど、構造化アセンブラにどっぷり浸っている身としてはもうR8C以外に考えられませんので無理な相談というヤツだったりします。
とは言え
R8Cにも色々グループがあって周辺機能も様々なので、その辺は分離して簡単に使い分けられるようにするために当面使いそうな物をピックアップしてみました。
- R8C/3xM
- 会社で使っているのがこれなので、基本はこれになります。
20PINの32Mと、32PINの33Mを個人的に持っています。2029年1月までは生産してくれるとのことですが、本当でしょうね?ルネサスさん。 - R8C/M12A
- DIP20PINの使いやすいパッケージでお値段100円と超リーズナブルでありながら、20MHzの内蔵オシレータと2Kバイトのデータフラッシュも
ついているというスーパーなマイコンです。
ただ、E1エミュレータが使えないのでわざわざ旧型のE8aエミュレータを追加で買うハメに orz
プログラムメモリ2Kバイト、RAMは256バイトと一見制限は厳しいのですが、これを拡張する方法を公開してくれている方がいます。
しかし、この制限内でも十分電子工作を楽しめるようなシステムを目指そうと思っています。 - R8C/3xW
- 元々は80PINのR8C/38WとCANトランシーバーを搭載したボードを買ったのが最初でした。
続いて64PINの36W(48PINの34Wだったかもしれません)を載せたボード+CANトランシーバーボードを買いました。
当面CANの開発はこれで行こうと思いますが、移り気なもので・・・ - R8C/5xE
- 単品で購入可能なCAN内蔵R8Cを探していて見つけたのがこれです。
R8C/3系の周辺機能を踏襲しつつ動作周波数が高いのが魅力ですが、今のところそこまでの必要は感じていません。 - R8C/23
- 同じく単品購入可能なCAN内蔵R8Cです。
動作温度範囲の広いKバージョンが手に入るのが車載を考えると魅力ですが、他の使用部品の動作可能温度が低かったら意味がないので保留中です。
今のところこんな感じですが、まずは手元にある上3つを使えるようにするのが先決ですね。
もちろん、必要になれば下の2つにも対応できるような仕組みにしつつです。
都合のいいことに
R8Cの統合開発環境では、マイコンの品種を指定してプロジェクトを作成するとレジスタを網羅したインクルードファイルを作ってくれます。
今では当たり前の事なのかもしれませんが、その辺りも自作していた身としてはかなり感動物です。
というわけで、早速プロジェクトを一通り作ってみました。
一番上の"gestimotor"というのは先日ご紹介した基板に搭載した機能をPPAP的に並べたものです。
続いてCAN関連の比較です。
ピックアップした中ではCANがつかえる物が3つありますが、まずは38Wと56Eの割り込み部分から。
右側の56EはCAN割り込みが3つしかありませんが、38Wの方はこの先も続いています。
次は56Eと23の比較です。
これは明らかに別物ですね。
ということで3グループ共にCAN機能は別物だと分かりました。見比べてみると56Eが一番シンプルな感じで、もしかすると洗練されていて使いやすいのかも。
でも、まずは38WのCANを使えるようになるのが先決です。
ここまではグループが違えば周辺機能が違っていても仕方がないと納得できるのですが、驚いたのはこれ。
M12Aは割り込み関係の処理が全く違っているようです。
割り込み処理はコア機能だと漠然と考えていましたが、周辺機能から割り込みがかかるわけですからやはり周辺機能ということになるんでしょうね。
ここさえクリアできればちょっとした工作にどんどん使えそうなのですが・・・。
ということで
先はまだまだ長そうですが、地道にやっていこうと思います。
原点復帰 ― 2016年11月23日
なんだか・・・
あれこれ紆余曲折しているうちに一年以上経過してしまってました。
実は自宅で電子工作をしつつ、会社で作ったR8C用基本システムの検証と強化を行うという目的もあったんですが、構造的にも道義的にもスッキリしない感じでしたので思い切って一から作り直すことにしました。
そこで
システム開発用にこんな試験基板を作ってみました。
今まで買い溜めていたものを載せてみただけという感じが無きにしも非ずですが、あれこれ使ってみることが経験的にもシステム開発的にも大切だと思いますので、まずはこれで再スタートです。
実は未だにプリエンプティブなシステムは作ったことがありませんのでやってみたいかな〜などと思いつつ、余り複雑にしたくありませんしできるだけ早く動く状態にしたいのでスタック共有型を視野に入れつつ実装を進めていく考えです。
アーキテクチャ的な話をすると
メインループを主体に周期的処理を回していくスタイルを「サイクリック・エグゼクティブ」アーキテクチャと言うらしいですね。
ぶっちゃけ一番シンプルな形式なんですがスペースシャトルのフライトシステムの一部もこの方式だったらしく、ハードが確定している要件であれば大抵はこれでいけそうな気もしますし現状はこれで足りていたりします。
個人的にはこれが最強だと思っていて、自分が作るシステムにはマルチタスクの必要性は今のところ感じていないんですが、時間のかかる演算が必要な案件が出てきたらどうしようという漠然とした不安はあったりします。
まぁ、学習を兼ねて趣味でやっていることですから諸々のことは作りながら考えていくとして、会社の仕事の方でそういった事態になった時にスマートに解決できる技量を早く身につけたいとは思っています。
実践!ロータリーエンコーダ ― 2015年09月17日
このところ
ずっとロータリーエンコーダ関連の処理に取り組んでいて、先日ようやくR8Cのタイマ機能を使って取り込むところまで進みました。
今回はいよいよアプリケーションの中でどう使うかを追求します。
その前に
先日は入力のCRフィルターが効き過ぎていたのを放置していましたが、やはりそれでは勉強にならないと考えて調整してみました。
と言っても、コンデンサを0.1uFから0.033uFに変更しただけですが。
その結果がこちら。
昨日とほぼ同じ速さですが連続検出中もほぼ5Vまで戻っています。
わずか60msec足らずの間に15カウントした結果ですので十分だと思います。
そして、指先一つで速度自在なロータリーエンコーダはやはり便利なデバイスですね。
システム化
まず、R8Cの位相計数モードの設定はこんな風にしてみました。
;-----------------------------------
; タイマRG
;-----------------------------------
TRG$_MDF_MODE 00010001b ; 位相計数モード[ 加算/減算条件 ]
TRG$_START ; カウント開始
マクロの中身は公開できませんが、先日ご紹介した位相計数モードの使用準備がこれだけでできるようにしてあります。
そして、いきなりですがロータリーエンコーダの処理部分がこちら。
;-----------------------------------
; メモリ定義部
;-----------------------------------
DIFFERENCE$_ALLOC rotary
char_num: .blkb 1
;-----------------------------------
; 初期化部
;-----------------------------------
DIFFERENCE$_INIT rotary, [trg].w
[ char_num ] = 'A'
LCD$_POS 0, 0
LCD$_WRITE [char_num]
;-----------------------------------
; メインループ
;-----------------------------------
MAIN_LOOP$
DIFFERENCE$_EXEC$_ rotary, [trg].w
[ char_num ] = R0L + [ char_num ]
LCD$_POS 0, 0
LCD$_WRITE [char_num]
_$
_END
本当にいきなりですが、LCDに1文字表示していて、その文字をロータリーエンコーダで切り換えていると書けば何となくお分かりいただけるのではないでしょうか。
"DIFFERENCE"は変化分を抽出するオブジェクトで、今回新設しました。
"[trg].w"はタイマRGのカウント値が入っているレジスタで、これを直に指定するのは隠蔽が不十分な感じですが、位相計数モードのためだけにこの手の処理を作るのも特化しすぎな気もするのでこれでよしとしておきます。
"DIFFERENCE$_EXEC$_"〜"_$"はメインループの中にありますので最短周期で実行されていて、"[trg].w"が変化した時だけブロックの中まで入っていくようになっています。
この時、R0には変化分がワードサイズで入っていますが、ブロック中ではR0Lで下位バイトだけ使っています。
このフリーダムさもアセンブラの魅力ですね。
とまあ、こんな風に構造化アセンブラにどっぷり浸っていますので他のマイコンが使えなくて困っていたりもします。
ちなみに、上記のソースは構造化アセンブラを使って筆者がこう書いているだけで、構造化アセンブラ自体に"MAIN_LOOP$"とかがあるわけではありません。
割り込みを使わなかったわけ
色々考えてみましたが、R8CのタイマRGの割り込みは位相計数モードでは実質アウトプットコンペアだけで、1カウント毎に割り込みをかけたかったら現在のカウント値の+1と-1の値で割り込みがかかるようにその都度セットする必要があり現実的ではありません。
それに、ロータリーエンコーダの処理はカウント毎に実行しないといけないわけでもなく、例えば100msec周期でチェックしてその間に30カウント増えていたとしたら30カウント分増えた処理をしてやればいいだけです。
カウントはタイマRGがキッチリやってくれていますので、周期はもっと長くても平気です。
とは言え、さすがにそれでは操作に違和感があるでしょうから、実際は10msecくらいが妥当でしょうか。
オシロで見たところ、相当速く回しても10msecだと4カウントまでいかないくらいでしたし。
というわけで、やっとロータリーエンコーダを使いこなすことができたと思います。
位相計数モードで楽々カウント ― 2015年09月16日
あると便利
ロータリーエンコーダはとても優れた操作性を持つ一方、プログラミングは面倒臭そうです。
しかし、マイコンが「位相計数」という機能を持っていれば簡単に処理できる模様。
幸いR8Cにもこの機能がありますのでその恩恵に預かれます。
ただし、少ピンの品種ではこの機能が省かれていたりしますので、ロータリーエンコーダを使う場合はタイマRG機能のある物を選ぶといいでしょう。
楽々設定
位相計数機能を使うにはロータリーエンコーダの信号をTRGCLKA端子とTRGCLCB端子に入れてやる必要があります。
そして、タイマ端子選択レジスタ(timsr)のb6とb7をONにしてこれらの端子機能を有効にします。
タイマモードを位相計数モードにしただけでは端子機能は有効にならないので注意が必要です。また、端子機能の設定はタイマを動作させる前に済ませておきましょう。
次にカウントアップ/ダウンの条件を設定します。
タイマRGカウント制御レジスタ(trgcntc)の上位4bitがカウントアップ条件、下位4bitがカウントダウン条件となっていますが、単純なロータリーエンコーダの場合はそれぞれどれか1bitをONしておけばいいようです。
これらをうまく設定することでもっと複雑なエンコードをするエンコーダにも対応できるということだと思います(たぶん)。
あとはタイマRGモードレジスタ(trgmr)でタイマモードを「位相計数モード」にし、カウントを開始すればロータリーエンコーダの操作に呼応してタイマRGカウンタ(trg)の値をアップ/ダウンしてくれます。
かなりお手軽ですね。
ただし
これだけだと単純にカウンタのアップダウンをしてくれるだけで、割り込みをかけたいとかいう場合にはあれこれ設定が必要なようです。
その辺りのことはデータシートの位相計数モードの項には書かれていないのでちょっと面倒臭そう。
と言っても、タイマRGカウンタをポーリングするだけでも当面は大丈夫だと思いますのでその辺りの追求は後回しにするかもしれません。
あと、エンコーダからの入力パターンに対してカウントのアップダウン方向を変えることはできませんので、希望した方向と違う場合にはハード側で対応する必要があります。
接続を入れ替えてもいいのですが、入力の安定性を考えて反転付きのシュミットトリガやフリップフロップを入れる方がいいかもしれません。
ハードは堅実に
ハードは今絶賛学習中ということもあり、まずはロータリーエンコーダをマイコンに直結してみました。
あ、もちろんプルアップはしてあります。
オシロで見ると存外きれいな波形です。
巷のロータリーエンコーダの解説では分からなかったんですが、クリック感のあるタイプでは停止位置だと両方オープンになっているようですね。
これならそのままでもいけるかもと思ったんですが、マイコンのカウント値を確認すると操作感と全く一致せず・・・。
で、さらに波形の観察をしているとこんな状態になることも。
そこでウェブの情報を頼りにCRフィルタの値を決めてみました。
ロータリーエンコーダをゆっくり操作した時はきちんとカウントできたので喜んだのも束の間、が〜〜〜〜っと回すと全然だめでした。
オシロで見ると一目瞭然。
参考にしたのは押しボタンスイッチに対するフィルタですので、ロータリーエンコーダに使うには時定数が大きすぎました。
フィルタの要素をあれこれ試すのは面倒そうだったので、とりあえずプルアップ抵抗を替えてみた結果がこちら。
まだ効き過ぎてはいますが、取りこぼしはなかったので当面はこれで行こうと思います。
そう言えば、今使っているカーオーディオのヘッドユニットはロータリーエンコーダの取りこぼしが酷いんですが、こういうことなのかもしれないと思ってみたり。
これまではソフトの処理がまずいんじゃないかと考えていたんですけどね。
職場では何でもソフトのせいにされると嘆いていたんですが、自分でも同じ事をしていたとは・・・。
Vport with Power で行こう ― 2015年09月14日
製品では
コネクターの刺し間違いを防止するためにあえてコネクターの種類やピン数、色などをバラバラにしたりしますが、開発段階では統一しておいた方が色々手早く出来そうです。
そこで
Vport with Power規格というのに乗っからせてもらうことにしました。
詳しいことは公式ページであるブイポートラボを見ていただくとして、ざっくり言うと、MIL規格10Pコネクタの9番ピンをGND、10番ピンをプラス電源として、残り8ピンをI/Oとして使うというものです。
写真の上側はタクトスイッチ4点、トグルスイッチ2点、ロータリーエンコーダ1個のスイッチ入力基板で、下側は照度センサ、湿度センサ、温度センサ、2軸ジャイロセンサ、3軸Gセンサのアナログセンサ基板です。
ハーネスはご覧のようにフラットケーブルを使い、このくらいですとプライヤーで簡単に圧着できますのでハーネスの作成も大幅に省力化できます。
なんだか
亀の歩みでなかなかCANモニターにたどり着けませんが、ハードやソフトの資産作りも大切なことですので着実にやっていこうと思います。
とは言っても、スケジュールが全くないとだらけてしまいがちですので、シルバーウィークには車のCANを覗き見ることを目標にテンションを上げていこうと思います。
最近のコメント