ARMでモーター制御
以前ARMに入門しましたがもう少し進めてみました。
s51517765.hatenadiary.jp
ビュートローバーにはモータが2つついていて、前進後進のほかに転回もできるようになっています。
また、ライントレーサーとしてのプログラミングもできるように反射光で地面を観測できるセンサが付いています。
ライントレーサーはよっぽど広い場所がないといまいち楽しめないですが、これらを使って簡単なプログラムを作ってみました。
ビュートローバーARMでモーター制御出来た!
— とりてん (@s51517765) 2021年11月13日
地面の境目でターン! pic.twitter.com/j8EcPupScC
押しボタンで転回機能追加。 pic.twitter.com/t1RwBi0nFR
— とりてん (@s51517765) 2021年11月13日
シリアル通信と押しボタン検知を実装
vstone.co.jp
こちらを参考にシリアル通信と押しボタン検知を実装します。
ARMのシリアル通信機能を用いてセンサー値をまず読んでみます。
ただし、シリアル出力はサンプルとしてcdcuser.c
に実装されています。
ADRead()
はvs-wrc103.c
に実装されています。
#include <stdio.h> char sentence [11]; //送る文字数より1文字多い配列を確保する。 while(1){ //{}内を永遠に繰り返す for(int i=0; i<2; i++){ //for文 2回くりかえす unsigned short data=ADRead(i); //赤外線センサの値をA/D変換してdataに代入 sprintf(sentence,"AN%01d=%04d\r\n",i,data); //%01にはiの値が1桁、%04にはdataの値が4桁で //文字列に変換され //まとめてsentenceに文字列として格納される //\r\n(2文字)は改行を表す SciStrTx(sentence,10); //変数sentenceに入った10文字をパソコンに送信 Wait(20); //0.02秒待つ } sprintf(sentence,"\033[1;1H"); //1行目1列目にカーソルを戻すエスケープシーケンスの命令 SciStrTx(sentence,6); //エスケープシーケンス6文字を送信 Wait(20); //0.02秒待つ }
これで2つ実装されているセンサの値をシリアルに出力します。
シリアル通信はTeraTermで見ることが出来ます。
ここで、FW書き込みのためのUSB接続とTeraTermによるシリアル通信は排他的になるようです。
他方を閉じないと接続できません。
これで、転回させる位置とそれ以外の位置のセンサー出力を確認し、閾値を決めます。
私の環境では、転回位置ではおよそ800でそれ以外ではおよそ400でした。
これより閾値を600とします。
次に押しボタンを検出するコードです。
ここではシリアルに出力しています。
ここでgetSW()
はvs-wrc103.c
に実装されています。
while (1) { if(getSW()==1){//押しボタンがおされたら SciByteTx('C'); //(大文字のC)を送信 Wait(100); //0.1秒待つ }
地面の境目で転回し、押しボタン検知で転回する
あとは、モーターが制御できれば目的は達成できそうです。
モーターの制御はvs-wrc103.c
に実装されてされています。
void Mtr_Run_lv(short m1,short m2,short m3,short m4,short m5,short m6)
は中身とドキュメント(VS-WRC103LV_doc_ver04.pdf)、サンプルコードを見ると、標準で実装されている2つのモーターはm1
とm2
で制御できそうとわかります。
ここに速度のパラメータを渡せばよさそうです。
#include "lpc13xx.h" #include "gpio.h" #include "vs-wrc103.h" #include "ixbus.h" #include "cdcuser.h" #include <stdio.h> int read_sensor(){ char sentence [11]; //送る文字数より1文字多い配列を確保する。 unsigned short data[2]; for(int i=0; i<2; i++){ //for文 2回くりかえす data[i]=ADRead(i); //赤外線センサの値をA/D変換してdataに代入 sprintf(sentence,"AN%01d=%04d\r\n",i,data[i]); //%01にはiの値が1桁、%04にはdataの値が4桁で //文字列に変換され //まとめてsentenceに文字列として格納される //\r\n(2文字)は改行を表す SciStrTx(sentence,10); //変数sentenceに入った10文字をパソコンに送信 Wait(20); //0.02秒待つ } sprintf(sentence,"\033[1;1H"); //1行目1列目にカーソルを戻すエスケープシーケンスの命令 SciStrTx(sentence,6); //エスケープシーケンス6文字を送信 Wait(20); //0.02秒待つ if ((data[0]+data[1])/2>600)return 1; else return 0; } int main (void) { //制御周期の設定[単位:Hz 範囲:30.0~] const unsigned short MainCycle = 60; Init(MainCycle); //CPUの初期設定 SciInit(); while(1){ int sns= read_sensor(); if(getSW()==1){//押しボタンがおされたら //逆転回 Mtr_Run_lv(10000,10000,0,0,0,0); Wait(3000); } else if (sns==1) { //転回 Mtr_Run_lv(-10000,-10000,0,0,0,0); Wait(3000); } else { //前進 Mtr_Run_lv(-10000,10000,0,0,0,0); //後進 //Mtr_Run_lv(10000,-10000,0,0,0,0); } } }
まとめ
といっても、LPC_TMR16B0->MR0 = t_Duty[0]&0x0000FFFF;
のあたりとか意味わからないです。
サンプルコードやドキュメントは以下の公式ページで見れます。
www.vstone.co.jp