みなさん,こんにちは
おかしょです.
電子工作を始めようと思ったきっかけとして,ラジコンカーを作りたいと思った人も多いと思います.
ラジコンカーは無線で制御ができるコントローラーを使って,車型のロボットを自由自在に動かすことができます.
もし,このようなラジコンカーを自分で作ることができたらと考えている人もいると思います.
今回は,ラジコンカーのコントローラーの役目をパソコンのキーボードにさせる方法について解説します.
この記事を読むと以下のようなことがわかる・できるようになります.
- Processingのプログラムの書き方
 - キーボードの使用方法
 - モーターをキーボードで操作する方法
 
この記事を読む前に
そもそもモーターの動かし方がわからないという方は以下の記事でArduinoでモーターを制御する方法を解説しているので,そちらを先に読んでおくことをおすすめします.
やりたいこと
この記事では,先程も述べたようにラジコンカーの制御をキーボードで行う方法を解説します.
具体的には,パソコンのキーボードを使ってモーターの回転速度を制御したいと思います.
その時に使用するのは,フリーソフトのProcessingというソフトです.
このブログでもProcessingに関する記事を公開しているので,Processingカテゴリーから読んでみてください.
簡単にProcessingとは何か説明すると,プログラミングでさまざまなデジタルアートを描くことのできるソフトです.
プログラムを工夫すれば,キーボードやマウスを使って動作を変更したり,ポートを使用してロボットに指令を送ることもできます.
このProcessingを利用してキーボードの状態を読み取り,2つのモーターの制御指令を送りたいと思います.
Processing側のプログラム
まずはProcessingのプログラムから解説します.
Processingのインストールが済んでいない方はこちらからインストールを行ってください.
import processing.serial.*;
Serial port;
int[] data = new int[6];
int uL, uR;
int uLa, uRa;
void setup() {
  size(250, 250);
  background(0);
  uL = 0;
  uR = 0;
  port = new Serial(this, Serial.list()[0], 9600);  // Serial port設定
}
void draw()
{
  translate(width/2, height/2);
  background(0);
  noStroke();
  fill(150);
  rect(-55, -55, 30, 30);
  rect(-55, -15, 30, 30);
  rect(-55, 25, 30, 30);
  rect(-15, -55, 30, 30);
  rect(-15, -15, 30, 30);
  rect(-15, 25, 30, 30);
  rect(25, -55, 30, 30);
  rect(25, -15, 30, 30);
  rect(25, 25, 30, 30);
  if (keyPressed) {
    fill(0, 255, 255);
    if (key == '1') 
    {
      uL -= 10;
      rect(-55, 25, 30, 30);
    }
    if (key == '4') 
    {
      uL = 0;
      rect(-55, -15, 30, 30);
    }
    if (key == '7') 
    {
      uL += 10;
      rect(-55, -55, 30, 30);
    }
    if (key == '2')
    {
      uL -= 10;
      uR -= 10;
      rect(-15, 25, 30, 30);
    }
    if (key == '5')
    {
      uL = 0;
      uR = 0;
      rect(-15, -15, 30, 30);
    }
    if (key == '8')
    {
      uL += 10;
      uR += 10;
      rect(-15, -55, 30, 30);
    }
    if (key == '3') 
    {
      uR -= 10;
      rect(25, 25, 30, 30);
    }
    if (key == '6') 
    {
      uR = 0;
      rect(25, -15, 30, 30);
    }
    if (key == '9') 
    {
      uR += 10;
      rect(25, -55, 30, 30);
    }
    
    if(uL>255)
    {
      uL = 255;
    }
    else if(uL<-255)
    {
      uL = -255;
    }
    if(uR>255)
    {
      uR = 255;
    }
    else if(uR<-255)
    {
      uR = -255;
    }
  }
  sendData(uL, uR);
  textSize(20);
  fill(255);
  textAlign(CENTER,CENTER);
  text("1", -40, 40);
  text("4", -40, 0);
  text("7", -40, -40);
  text("2", 0, 40);
  text("5", 0, 0);
  text("8", 0, -40);
  text("3", 40, 40);
  text("6", 40, 0);
  text("9", 40, -40);
  textAlign(LEFT,BOTTOM);
  text("uL: " + uLa, -100, -75);
  text("uR: " + uRa, 0, -75);
}
void sendData(int data1, int data2)
{
  // ダミーデータの送信
  port.write(200); 
  port.write(1);
  if(data1>=0)
  {
    port.write(0);
  }
  else
  {
    port.write(1);
    data1 = data1*(-1);
  }
  port.write((byte)(data1>>8));
  port.write((byte)(data1));
  if(data2>=0)
  {
    port.write(0);
  }
  else
  {
    port.write(1);
    data2 = data2*(-1);
  }
  port.write((byte)(data2>>8));
  port.write((byte)(data2));
}
void serialEvent(Serial port) {
  int[] data = new int[6];
  if ( port.available() > 7 )
  {
    if(port.read()==200)
    {
      if(port.read()==1)
      {
        data[0] = port.read();
        data[1] = port.read();
        data[2] = port.read();
        data[3] = port.read();
        data[4] = port.read();
        data[5] = port.read();
        if(data[0]==0)
        {
          uLa = data[1]*256+data[2];
        }
        else if(data[0]==1)
        {
          uLa = -1*(data[1]*256+data[2]);
        }
        if(data[3]==0)
        {
          uRa = data[4]*256+data[5];
        }
        else if(data[3]==1)
        {
          uRa = -1*(data[4]*256+data[5]);
        }
      }
    }
  }
}これを実行すると,以下のようなウィンドウが表示されます.

このウィンドウ内の数字はキーボードの数字を表しています.
試しに数字の「5」を押してみると,以下のように数字の「5」の部分が光ります.

操縦方法
プログラムの説明の前に操作方法について解説します.
左側の数字(1, 4, 7)は左に取り付けてあるモーターの制御を行います.右側の数字(3, 6, 9)は右に取り付けてあるモーター,真ん中の数字(2, 5, 8)は両方のモーターを同時に制御します.数字が小さいものを押すと角速度が減少し,大きい方は増加します.真ん中の数字を押すとモーターの回転は止まるようになっています.
そして,上に表示されている数字はそれぞれのモーターに送られる指令値が表示されています.この数値はArduinoから送られてくるようになっていて,キーボードの操作通りに指令値が送られているのかを確認することができるようになっています.
プログラムの解説
それではプログラムの解説をします.
Arduinoと通信を行うため,1行目でシリアル通信を行うことができるライブラリをインクルードしています.
setup関数でもそのためのポートの割り当てを13行目で行っています.
プログラムの下方ではsendData関数とserialEvent関数を使用しています.
これについてはこちらで解説しているので,そちらを参照してください.
draw関数では,キーボードの状態を表示できるようにボタンの作成をしています.
rectコマンドを使ってボタンの外形を整列させ,そのボタンの中にtextコマンドを使用して数字を書き込んでいます.
このとき,外径を塗りつぶす色をキーボードが押されたときに変化するようにしています.
Processingのプログラムでキーボードを使用する方法についてはこちらで詳しく解説しています.
また,キーボードが押されるたびに塗りつぶす色の変更だけでなく,指令値の修正も行っています.(例:ul += 10)
モーターの制御指令値の上限値は255,下限値は-255なので,その範囲を超えないように82~97行目のプログラムを書き加えています.
キーボードの状態を読み取ってArduinoに送信する制御指令値はuL,uRとして,Arduinoから受け取る指令値をuLa,uRaに格納するようにしています.
draw関数内の最後の行(113,114行目)では,Arduinoから受け取ったuLaとuRaを表示するようにしています.
Arduino側のプログラム
次にArduino側のプログラムです.
int uL, uR;
void setup() {
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  Serial.begin(9600);
}
void loop() {
  recvData();
  MotorControl(2, 4, 3, uL);
  MotorControl(5, 7, 6, uR);
}
void MotorControl(uint8_t pin1, uint8_t pin2, uint8_t pin3, int p)
{
  if(p>=0)
  {
    digitalWrite(pin1,LOW);
    digitalWrite(pin2,HIGH);
  }
  else
  {
    digitalWrite(pin1,HIGH);
    digitalWrite(pin2,LOW);
    p = -1*p;
  }
  analogWrite(pin3,p);
}
void sendData(int data1, int data2)
{
  // ダミーデータの送信
  Serial.write(200);
  Serial.write(1);
  if(data1>=0)
  {
    Serial.write(0);
  }
  else
  {
    data1 = data1*(-1);
    Serial.write(1);
  }
  Serial.write((byte)(data1>>8));
  Serial.write((byte)(data1));
  if(data2>=0)
  {
    Serial.write(0);
  }
  else
  {
    data2 = data2*(-1);
    Serial.write(1);
  }
  Serial.write((byte)(data2>>8));
  Serial.write((byte)(data2));
}
void recvData()
{
  int data[6];
  if(Serial.available()>7)
  {
    if(Serial.read()==200)
    {
      if(Serial.read()==1)
      {
        data[0] = Serial.read();
        data[1] = Serial.read();
        data[2] = Serial.read();
        data[3] = Serial.read();
        data[4] = Serial.read();
        data[5] = Serial.read();
        if(data[0]==0)
        {
          uL = data[1]*256+data[2];
        }
        else if(data[0]==1)
        {
          uL = -1*(data[1]*256+data[2]);
        }
        if(data[3]==0)
        {
          uR = data[4]*256+data[5];
        }
        else if(data[3]==1)
        {
          uR = -1*(data[4]*256+data[5]);
        }
        sendData(uL, uR);
      }
    }
  }
}このプログラムに関してはこちらで解説しているので,そちらを参照してください.
特に難しいことはしておらず,上記の記事のプログラムを組み合わせただけです.
電子回路
今回のプログラムの確認をするために使用した電子回路は以下のように組みました.
参考にして実際にやってみてください.

まとめ

この記事ではキーボードを使ってモーターを制御するProcessingのプログラムとArduinoのプログラムを公開しました.
今回解説した技術を使用すれば,ラジコンカーを作ることも可能となります.
続けて読む
この記事で解説した技術を使用して,以下の記事では二輪型倒立振子のモーターを制御しています.
興味のある方は読んでみてください.
Twitterでは記事の更新情報や活動の進捗などをつぶやいているので気が向いたらフォローしてください.
それでは最後まで読んでいただきありがとうございました.

  
  
  
  



コメント