3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Donkey Carのプロポ対応その2(ソフトウェア編)

Posted at

はじめに

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プログラムの書き換え及び設定を書きます。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?