はじめに
HID対応しているArduinoは実行時にUSBを使い、デバッグ時にもUSB経由でArduino IDEのシリアルコンソールに表示させるため、デバッグを意識したスケッチにしておくと便利です。Arduinoの開発方法を知っている前提で書いてあります。
想定機能
プロポにより色々とキー割り当てが考えられるため、以下の機能に想定して説明をします。
操作 | ピン | |
---|---|---|
左スティックX軸(横方向) | Steering | D09 |
右スティックY軸(縦方向) | Throttle | D10 |
ボタンL1 | 任意 | D11 |
ボタンR1 | 任意 | D15 |
ライブラリの取り込み
- PinChangeInterrupt ... ライブラリマネージャから取り込みます。
- Joystick ... 以下のサイトから取り込みます。
https://github.com/MHeironimus/ArduinoJoystickLibrary
受信データのPWM値を調べる
スケッチの最初の2行のライブラリを取り込んだのち、測定したいチャンネル毎のプロポの値を調べる。以下のスケッチのDEBUGを1にして実行します。左スティックのX軸を左、右に倒して、最小値・最大値をシリアルモニターに表示させます。最小値は1000㎲近辺、最大値は2000㎲近辺になると思います。
スケッチは可読性をよくするために1チャンネルだけの処理をしていますが、同様に別なチャンネルもプロポの設定値を確認します。
#include <PinChangeInterrupt.h>
#include <Joystick.h>
#define DEBUG 1
#define NUM_BUTTON 3
#define BUTTON_MODE 0
#define R1 1
#define L1 2
#define NUM_CHANNEL 4
#define BUTTON_PRESSED 1
#define BUTTON_RELEASED 0
#define STEERING_LEFT_PWM 1000
#define STEERING_RIGHT_PWM 2000
#define MIN_VALUE16 -32767
#define MAX_VALUE16 32767
#define ERROR_RANGE 16
const byte channel_pin[] = {9, 10, 11, 15};
volatile unsigned long rising_start[] = {0, 0, 0, 0};
volatile long channel_length[] = {0, 0, 0, 0};
volatile long base_value[] = {0, 0, 0, 0};
Joystick_ Joystick = Joystick_(
0x03, // reportid
JOYSTICK_TYPE_JOYSTICK, // type
NUM_BUTTON, // button count
0, // hat switch count
true, false, false, // left x,y,z axis enable
false, true, false, // right x,y,z axis enable
false, // rudder enable
false, // throttle enable
false, // accelerator enable
false, // brake enable
false // steering enable
);
void setup() {
int counter;
if(DEBUG) {
Serial.begin(115200);
while (!Serial) {}
}
pinMode(channel_pin[0], INPUT); // steering
pinMode(channel_pin[1], INPUT); // throttle
pinMode(channel_pin[2], INPUT);
pinMode(channel_pin[3], INPUT);
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(channel_pin[0]), onRising0, CHANGE);
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(channel_pin[1]), onRising1, CHANGE);
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(channel_pin[2]), onRising2, CHANGE);
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(channel_pin[3]), onRising3, CHANGE);
// Initialize Joystick
if(!DEBUG) {
Joystick.begin();
Joystick.setXAxisRange(MIN_VALUE16, MAX_VALUE16);
Joystick.setRyAxisRange(MIN_VALUE16, MAX_VALUE16);
}
// Wait Initial value of all channel
while(1) {
counter = 0;
for(int i=0; i<NUM_CHANNEL; i++) {
if(channel_length[i] == 0) { counter++; }
}
if(counter == 0) { break; }
}
// set base value
for(int i=0; i<NUM_CHANNEL; i++) {
base_value[i] = channel_length[i];
}
}
void processPin(byte pin) {
uint8_t trigger = getPinChangeInterruptTrigger(digitalPinToPCINT(channel_pin[pin]));
if(trigger == RISING) {
rising_start[pin] = micros();
} else if(trigger == FALLING) {
channel_length[pin] = micros() - rising_start[pin];
}
}
void onRising0(void) {
processPin(0);
}
void onRising1(void) {
processPin(1);
}
void onRising2(void) {
processPin(2);
}
void onRising3(void) {
processPin(3);
}
void loop() {
int steering_range, throttle_range;
int steering_value, throttle_value;
if(DEBUG) {
Serial.println(channel_length[0]);
} else {
steering_value = map(channel_length[0], STEERING_LEFT_PWM, STEERING_RIGHT_PWM, MIN_VALUE16, MAX_VALUE16);
Joystick.setXAxis(steering_value);
}
}
HIDとしてArduinoを動作させる
DEBUGを0にして、前のステップで採取したデータをSTEERING_LEFT_PWM, STEERING_RIGHT_PWMにセットして実行すると、ジョイスティック関連のプログラムが動くようにしています。
ArduinoのD09からのPWM値を、map関数により符号付き16ビット整数にして、Raspberry Pi側に送ります。
ボタンの扱い
ボタン番号 2を押して、50ms経って離したことを示しています。
Joystick.pressButton(L1);
delay(50);
Joystick.releaseButton(L1);
詳しくは、以下のサイトのJoystick APIを参照してプログラミングしてください。
続き
次は、Raspberry PiでのDonkey Carプログラムの書き換え及び設定を書きます。