とりあえず、動かしてみたかったので、配線とかUSBケーブルとかそのままねじりっこで束ねて、かなり酷い外観になっていますが、まあ、そのあたりは追々改善するということで・・・
で、とりあえず、走らせてみる。
適当すぎて、役には立たないだろうけど、一応、Arduinoのソース(スケッチ)を載せてみます。
#include <Arduino.h>
/**
* Motor & PSD センサのテストスケッチ。
*/
#define DBG_MODE 1
// PSDセンサのアナログ入力ピン設定。
#define PIN_PSD_L 4
#define PIN_PSD_R 5
// Motor Shield Rev.3 のピン設定。
#define PIN_CH1_PWM 3
#define PIN_CH1_DIR 12
#define PIN_CH1_BRK 9
#define PIN_CH2_PWM 11
#define PIN_CH2_DIR 13
#define PIN_CH2_BRK 8
// 各モータの配置・配線で正逆転を適宜変更。
#define CH1_CW HIGH
#define CH1_CCW LOW
#define CH2_CW LOW
#define CH2_CCW HIGH
#define DIR_CW 0
#define DIR_CCW 1
#define MOTOR_LEFT 1
#define MOTOR_RIGHT 2
// PSDセンサの近接側測定不可領域閾値。
const int PSD_DEADZONE = 80;
// 通信終端文字コード定義。
static char CHAR_CR = 0x0d;
static char CHAR_LF = 0x0a;
// グローバル変数定義。
char rcvChar;
char rcvBuf[64];
int rcvCnt;
boolean isRcvCmd;
int spd1, spd2;
int rngL, rngR;
char *tmpc1, *tmpc2;
int tmpi1, tmpi2;
String dbg_msg = "";
int nearL, nearR;
int verynearL, verynearR;
// PSDセンサの電圧をcmに変換。
int analogToCentimeter(int analogValue) {
return (int)((6787 / (analogValue -3)) -4 );
}
// 回転方向(出力ピン)の設定。
// ch - 設定チャネル 1 or 2
// dir - 回転方向 DIR_CWで正転、DIR_CCWで逆転
// 戻り値 なし。
void setDirection(int ch, int dir) {
if(ch == 1) {
if(dir == DIR_CW) {
digitalWrite(PIN_CH1_DIR, CH1_CW);
} else if (dir == DIR_CCW) {
digitalWrite(PIN_CH1_DIR, CH1_CCW);
}
} else if (ch == 2) {
if (dir == DIR_CW) {
digitalWrite(PIN_CH2_DIR, CH2_CW);
} else if (dir == DIR_CCW) {
digitalWrite(PIN_CH2_DIR, CH2_CCW);
}
}
}
// 各チャネルのモータ出力(スピード)設定。
// ch - 設定チャネル 1 or 2
// spd - 設定出力。0~255
// 戻り値 なし。
boolean setMotorSpeed(int ch, int spd) {
if ((ch != 1) && (ch != 2)) return false;
if (spd > 255) spd = 255;
if (spd < -255) spd = -255;
if (spd < 0) {
spd = -1 * spd;
setDirection(ch, DIR_CCW);
}
else {
setDirection(ch, DIR_CW);
}
if (ch == 1) {
analogWrite(PIN_CH1_PWM, spd);
}
else if (ch == 2) {
analogWrite(PIN_CH2_PWM, spd);
}
return true;
}
// モータ出力 ch1,2設定。
// ch1spd - ch1の出力。0~255
// ch2spd - ch2の出力。0~255
// 戻り値 なし。
void setMotorSpeed2(int ch1spd, int ch2spd) {
setMotorSpeed(1, ch1spd);
setMotorSpeed(2, ch2spd);
}
// モータ設定の初期化。
// 引数 なし。
// 戻り値 なし。
void initMotor() {
pinMode(PIN_CH1_PWM, OUTPUT);
pinMode(PIN_CH1_DIR, OUTPUT);
pinMode(PIN_CH1_BRK, OUTPUT);
pinMode(PIN_CH2_PWM, OUTPUT);
pinMode(PIN_CH2_DIR, OUTPUT);
pinMode(PIN_CH2_BRK, OUTPUT);
setMotorSpeed2(0, 0);
digitalWrite(PIN_CH1_BRK, LOW);
digitalWrite(PIN_CH2_BRK, LOW);
}
void breakMotor() {
digitalWrite(PIN_CH1_BRK, HIGH);
digitalWrite(PIN_CH2_BRK, HIGH);
spd1 = 0;
spd2 = 0;
setMotorSpeed2(spd1, spd2);
delay(200);
digitalWrite(PIN_CH1_BRK, LOW);
digitalWrite(PIN_CH2_BRK, LOW);
}
// 初期設定。
void setup() {
// シリアル通信初期化。
Serial.begin(115200);
if (DBG_MODE) {
Serial.println("Hello, Motor and PSD Test program...");
}
// モーター初期化。
initMotor();
// 変数初期化。
spd1 = 0;
spd2 = 0;
rngL = 0;
rngR = 0;
nearL = 0;
verynearL = 0;
nearR = 0;
verynearR = 0;
}
// メインループ。
void loop() {
if (DBG_MODE) {
dbg_msg = "";
}
// PSDセンサ読み取り処理。
int value = analogRead(PIN_PSD_L);
// 読み取り値が閾値を超えていれば、距離に変換。
if (value > PSD_DEADZONE) {
rngL = analogToCentimeter(value);
} else {
// しきい値に達しなければ、とりあえず0。
rngL = 0;
}
// もう一つのPSDも同様。
value = analogRead(PIN_PSD_R);
if (value > PSD_DEADZONE) {
rngR = analogToCentimeter(value);
} else {
rngR = 0;
}
// 速度制限。
if ((30 >= rngL) && (rngL > 15)) {
/// 距離30~15で
nearL++;
verynearL = 0;
} else if ((15 >= rngL) && (rngL > 0)) {
/// 距離15以下。ただし0(測定不能かも)は除く
verynearL++;
} else {
/// それ以外はとりあえず制限なし。
nearL = 0;
verynearL = 0;
}
if ((30 >= rngR) && (rngR > 15)) {
/// 距離30~15で
nearR++;
verynearR = 0;
} else if ((15 >= rngL) && (rngL > 0)) {
/// 距離15以下。ただし0(測定不能かも)は除く
verynearR++;
} else {
/// それ以外はとりあえず制限なし。
nearR = 0;
verynearR = 0;
}
// 車輪スピード設定。
setMotorSpeed2(spd1, spd2);
if (verynearL > 2) {
/// 左側停止。
setMotorSpeed(MOTOR_LEFT, 0);
}
if (verynearR > 2) {
/// 右側停止。
setMotorSpeed(MOTOR_RIGHT, 0);
}
if (nearL > 0) {
/// 左側が近接なら、右へ旋回。
setMotorSpeed(MOTOR_RIGHT, (int)(spd2/2));
nearL= 0;
}
if (nearR > 0) {
/// 右側が近接なら、左へ旋回。
setMotorSpeed(MOTOR_LEFT, (int)(spd1/2));
nearR = 0;
}
/*
if (DBG_MODE) {
Serial.print(rngL, DEC);
Serial.print(", ");
Serial.println(rngR, DEC);
}
*/
// シリアル受信処理。受信バッファにデータがあれば、
if (Serial.available() > 0) {
/// 1文字読み込み。
rcvChar = Serial.read();
/// 受信文字が改行文字の場合は、
if ((rcvChar == CHAR_CR) || (rcvChar == CHAR_LF)) {
//// 既に1文字以上受信していれば、
if (rcvCnt > 0){
///// 文字列終端を設定して、コマンド受信フラグ立てる。
rcvBuf[rcvCnt] = '\0';
isRcvCmd = true;
rcvCnt = 0;
}
}
/// 受信文字が改行文字以外の場合は、
else {
//// 配列に順次取り込み。
rcvBuf[rcvCnt] = rcvChar;
rcvCnt++;
}
} // シリアル受信処理、ここまで。
// コマンド解析処理。
if (isRcvCmd == true) {
/// 受信フラグクリア。
isRcvCmd = false;
/// 1文字目で処理振り分け。
switch (rcvBuf[0]) {
case 'D':
case 'd':
//// モータスピード指定。
tmpc1 = strtok(rcvBuf, ",");
tmpc1 = strtok(NULL, ",");
tmpc2 = strtok(NULL, ",");
if ((tmpc1 == NULL) || (tmpc2 == NULL)) break;
tmpi1 = atoi(tmpc1);
tmpi2 = atoi(tmpc2);
if ((tmpi1 < -255) || (tmpi1 > 255)) break;
if ((tmpi2 < -255) || (tmpi2 > 255)) break;
spd1 = tmpi1;
spd2 = tmpi2;
if (DBG_MODE) {
Serial.print("D command : ");
Serial.print(spd1, DEC);
Serial.print(", ");
Serial.println(spd2, DEC);
}
break;
case 'B':
case 'b':
//// ブレーキ。
breakMotor();
if (DBG_MODE) {
Serial.println("Break");
}
break;
case '?':
//// デバッグ情報取得。
if (DBG_MODE) {
dbg_msg += "spd1 = ";
dbg_msg += spd1;
dbg_msg += ", ";
dbg_msg += "spd2 = ";
dbg_msg += spd2;
dbg_msg += ", ";
dbg_msg += "PSD Left = " ;
dbg_msg += rngL;
dbg_msg += ", ";
dbg_msg += "PSD Right = ";
dbg_msg += rngR;
dbg_msg += ", ";
Serial.println(dbg_msg);
}
break;
default:
//// 該当なし。
break;
}
} // コマンド解析処理、ここまで。
}


0 件のコメント:
コメントを投稿