プログラミング素人のはてなブログ

プログラミングも電気回路も専門外の技術屋の末端が勉強したことや作品をアウトプットするブログ。コードに間違いなど見つけられたら、気軽にコメントください。 C#、Python3、ラズパイなど。

ビュートローバーARMでモーター制御

ARMでモーター制御

以前ARMに入門しましたがもう少し進めてみました。
s51517765.hatenadiary.jp

ビュートローバーにはモータが2つついていて、前進後進のほかに転回もできるようになっています。
また、ライントレーサーとしてのプログラミングもできるように反射光で地面を観測できるセンサが付いています。
ライントレーサーはよっぽど広い場所がないといまいち楽しめないですが、これらを使って簡単なプログラムを作ってみました。

シリアル通信と押しボタン検知を実装

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で見ることが出来ます。
f:id:s51517765:20211113175228p:plain
ここで、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つのモーターはm1m2で制御できそうとわかります。
ここに速度のパラメータを渡せばよさそうです。

#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