操作側は適当にArduinoへUDP通信でデータを投げるだけ
通信フォーマットは
1バイト目 @固定
2バイト目 モーター1回転方向
3バイト目 モーター1回転速度
4バイト目 モーター2回転方向
5バイト目 モーター2回転速度
になってます。
イーサネットシールドはノイズに弱いようなので、実際にロボ化はしませんでした。
/*
* Arduinoラジコン
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>
/*------------ 定数定義 ------------*/
// モータの制御ピン設定
#define MOTOR1_PWM (5) // モータ1の出力制御ピン
#define MOTOR1_CTRL1 (6) // モータ1の回転方向制御ピン
#define MOTOR1_CTRL2 (7) // モータ1の回転方向制御ピン
#define MOTOR2_PWM (10) // モータ2の出力制御ピン
#define MOTOR2_CTRL1 (9) // モータ2の回転方向制御ピン
#define MOTOR2_CTRL2 (8) // モータ2の回転方向制御ピン
// モータの回転方向
#define MOTOR_S (0) // 停止
#define MOTOR_R (1) // 右回転
#define MOTOR_L (2) // 左回転
// 最大タイムアウト回数
#define TIMEOUT_MAX (2000)
#define PWM_PIN (0)
#define CTRL1_PIN (1)
#define CTRL2_PIN (2)
/*------------ 変数定義 ------------*/
/** イーサネットシールドのMACアドレス */
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x21, 0x04 };
/** IPアドレス */
byte ip[] = { 192, 168, 11, 200 };
/** ポート番号 */
unsigned int localPort = 8888;
/** 接続元のIP */
byte remoteIp[4];
/** 接続元のポート番号 */
unsigned int remotePort;
/** 受信データ */
char rcvData[UDP_TX_PACKET_MAX_SIZE];
/** 送信データ */
char sndData[] = "move";
/** タイムアウト回数 */
unsigned int timeout = 0;
unsigned char motor_pin[2][3];
int pwm=0;
/*------------ 関数定義 ------------*/
/**
* Arduinoの初期設定
*/
void setup() {
// イーサネットで通信開始
Ethernet.begin(mac,ip);
Udp.begin(localPort);
// 動作確認用のシリアル通信
Serial.begin(9600);
Serial.println("Wake up");
// モーター制御用のピンを格納
motor_pin[0][PWM_PIN] = MOTOR1_PWM;
motor_pin[0][CTRL1_PIN] = MOTOR1_CTRL1;
motor_pin[0][CTRL2_PIN] = MOTOR1_CTRL2;
motor_pin[1][PWM_PIN] = MOTOR2_PWM;
motor_pin[1][CTRL1_PIN] = MOTOR2_CTRL1;
motor_pin[1][CTRL2_PIN] = MOTOR2_CTRL2;
// モーター制御用のピンを出力用に設定
pinMode(MOTOR1_CTRL1, OUTPUT);
pinMode(MOTOR1_CTRL2, OUTPUT);
pinMode(MOTOR2_CTRL1, OUTPUT);
pinMode(MOTOR2_CTRL2, OUTPUT);
}
/**
* モーターの回転制御を行う
* rotationにMOTOR_S/MOTOR_R/MOTOR_Lを指定する事で回転方向や停止を制御する。
*
* @param[in] ch モータのチャンネル
* @param[in] rotation 回転方向(MOTOR_S/MOTOR_R/MOTOR_L)
* @param[in] power 出力値(0~255)
*/
void ctrlMotor(int ch, int rotation, unsigned char power) {
Serial.print(ch);
Serial.print("ch ");
Serial.print(rotation, DEC);
Serial.print("/");
Serial.println(power, DEC);
switch(rotation) {
default:
case MOTOR_S:// 停止
digitalWrite(motor_pin[ch][CTRL1_PIN], LOW);
digitalWrite(motor_pin[ch][CTRL2_PIN], LOW);
analogWrite(motor_pin[ch][PWM_PIN], 0);
break;
case MOTOR_R: // 右回転
digitalWrite(motor_pin[ch][CTRL1_PIN], LOW);
digitalWrite(motor_pin[ch][CTRL2_PIN], HIGH);
analogWrite(motor_pin[ch][PWM_PIN], power);
break;
case MOTOR_L: // 左回転
digitalWrite(motor_pin[ch][CTRL1_PIN], HIGH);
digitalWrite(motor_pin[ch][CTRL2_PIN], LOW);
analogWrite(motor_pin[ch][PWM_PIN], power);
break;
}
}
/**
* ループ
* UDP通信で制御用の情報を受信する
*/
void loop() {
unsigned char r1, s1, r2, s2;
// UDPソケットが受信可能になった
if(Udp.available()) {
Udp.readPacket(rcvData, UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
// マークチェック
if (rcvData[0] == '@') {
timeout = 0;
r1 = 0xFF & rcvData[1];
s1 = 0xFF & rcvData[2];
r2 = 0xFF & rcvData[3];
s2 = 0xFF & rcvData[4];
ctrlMotor(0, r1, s1);
ctrlMotor(1, r2, s2);
} else {
Serial.println("Error");
timeout++;
}
//Udp.sendPacket( ReplyBuffer, remoteIp, remotePort);
} else {
timeout++;
}
if (timeout >= TIMEOUT_MAX) {
Serial.println("Time out");
timeout = 0;
ctrlMotor(0, MOTOR_S, 0);
ctrlMotor(1, MOTOR_S, 0);
// テスト用
/*
pwm+=10;
if(pwm > 100) pwm = 0;
ctrlMotor(0, MOTOR_R, pwm);
ctrlMotor(1, MOTOR_R, pwm);
*/
}
}
0 件のコメント:
コメントを投稿