プロジェクト15:IRリモコンタンク

(1)説明:
赤外線リモコンは、電気モーター、電気ファン、その他多くの家電製品に最もよく使われるリモコンの一つです。このプロジェクトでは、これまでに学んだ知識を活用して、赤外線リモコンスマートカーを作成します。
第9レッスンでは、赤外線リモコンの各キーに対応するキー値をテストしました。このプロジェクトでは、コード(キー値)を設定して、対応するボタンでスマートカーの動きを制御し、8X16 LEDドットマトリクスに動作パターンを表示させることができます。
ライントラッキングスマートカーの具体的なロジックを以下の表に示します:
超音波キー |
キー値 |
キーからの指示 |
|---|---|---|
|
FF629D |
前進(PWMを200に設定) |
|
FFA857 |
後退(PWMを200に設定) |
|
FF22DD |
左折 |
|
FFC23D |
右折 |
|
FF02FD |
停止 |
初期設定:8X16 LEDドットマトリクスに「
」のパターンを表示します。
(2)フローチャート:

(3)接続図:

注意:
8x16 LEDパネルのGND、VCC、SDA、SCLは、拡張ボードのG(GND)、V(VCC)、SDA、SCLに接続されています。
8833ボードにはIR受信機が内蔵されているため、配線する必要はありません。IR受信機のピンはG(GND)、V(VCC)、D3です。
(4)テストコード:
(注意:コードをアップロードする前にBluetoothモジュールを接続しないでください。コードのアップロードもシリアル通信を使用しており、Bluetoothシリアル通信と競合が発生し、アップロードが失敗する可能性があります。)
/*
Keyestudio Mini Tank Robot V3 (Popular Edition)
lesson 15
IRremote Control Tank
http://www.keyestudio.com
*/
#include <IRremote.h>
IRrecv irrecv(3); //
decode_results results;
long ir_rec; //受信した赤外線値を格納するために使用
//配列、画像データを保存するために使用。自分で計算するかモジュールツールから取得できます
unsigned char start01[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
unsigned char front[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x12, 0x09, 0x12, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char back[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x48, 0x90, 0x48, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char left[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x44, 0x28, 0x10, 0x44, 0x28, 0x10, 0x00};
unsigned char right[] = {0x00, 0x10, 0x28, 0x44, 0x10, 0x28, 0x44, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char STOP01[] = {0x2E, 0x2A, 0x3A, 0x00, 0x02, 0x3E, 0x02, 0x00, 0x3E, 0x22, 0x3E, 0x00, 0x3E, 0x0A, 0x0E, 0x00};
unsigned char clear[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#define SCL_Pin A5 //クロックピンをA5に設定
#define SDA_Pin A4 //データピンをA4に設定
#define ML_Ctrl 4 //左モーターの方向制御ピンを定義
#define ML_PWM 6 //左モーターのPWM制御ピンを定義
#define MR_Ctrl 2 //右モーターの方向制御ピンを定義
#define MR_PWM 5 //右モーターのPWM制御ピンを定義
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); //赤外線受信ライブラリを初期化
pinMode(ML_Ctrl, OUTPUT);
pinMode(ML_PWM, OUTPUT);
pinMode(MR_Ctrl, OUTPUT);
pinMode(MR_PWM, OUTPUT);
pinMode(SCL_Pin, OUTPUT);
pinMode(SDA_Pin, OUTPUT);
matrix_display(clear); //画面をクリア
matrix_display(start01); //開始時の画像を表示
}
void loop()
{
if (irrecv.decode(&results)) //赤外線リモコン値を受信
{
ir_rec = results.value;
String type = "UNKNOWN";
String typelist[14] = {"UNKNOWN", "NEC", "SONY", "RC5", "RC6", "DISH", "SHARP", "PANASONIC", "JVC", "SANYO", "MITSUBISHI", "SAMSUNG", "LG", "WHYNTER"};
if (results.decode_type >= 1 && results.decode_type <= 13)
{
type = typelist[results.decode_type];
}
Serial.print("IR TYPE:" + type + " ");
Serial.println(ir_rec, HEX);
irrecv.resume();
}
switch (ir_rec)
{
case 0xFF629D: Car_front(); break; //前進コマンド
case 0xFFA857: Car_back(); break; //後退コマンド
case 0xFF22DD: Car_T_left(); break; //左折コマンド
case 0xFFC23D: Car_T_right(); break; //右折コマンド
case 0xFF02FD: Car_Stop(); break; //停止コマンド
case 0xFF30CF: Car_left(); break; //左回転コマンド
case 0xFF7A85: Car_right(); break; //右回転コマンド
default: break;
}
}
/***************モーターを動かす関数***************/
void Car_back()
{
digitalWrite(MR_Ctrl, LOW);
analogWrite(MR_PWM, 200);
digitalWrite(ML_Ctrl, LOW);
analogWrite(ML_PWM, 200);
matrix_display(back); //後退
}
void Car_front()
{
digitalWrite(MR_Ctrl, HIGH);
analogWrite(MR_PWM, 55);
digitalWrite(ML_Ctrl, HIGH);
analogWrite(ML_PWM, 55);
matrix_display(front); //前進画像を表示
}
void Car_left()
{
digitalWrite(MR_Ctrl, HIGH);
analogWrite(MR_PWM, 55);
digitalWrite(ML_Ctrl, LOW);
analogWrite(ML_PWM, 200);
matrix_display(left); //左折画像を表示
}
void Car_right()
{
digitalWrite(MR_Ctrl, LOW);
analogWrite(MR_PWM, 200);
digitalWrite(ML_Ctrl, HIGH);
analogWrite(ML_PWM, 55);
matrix_display(right); //右折画像を表示
}
void Car_Stop()
{
digitalWrite(MR_Ctrl, LOW);
analogWrite(MR_PWM, 0);
digitalWrite(ML_Ctrl, LOW);
analogWrite(ML_PWM, 0);
matrix_display(STOP01); //停止画像を表示
}
void Car_T_left()
{
digitalWrite(MR_Ctrl, HIGH);
analogWrite(MR_PWM, 0);
digitalWrite(ML_Ctrl, HIGH);
analogWrite(ML_PWM, 100);
matrix_display(left); //左折画像を表示
}
void Car_T_right()
{
digitalWrite(MR_Ctrl, HIGH);
analogWrite(MR_PWM, 100);
digitalWrite(ML_Ctrl, HIGH);
analogWrite(ML_PWM, 0);
matrix_display(right); //右折画像を表示
}
//この関数はドットマトリクス画面の表示に使用
void matrix_display(unsigned char matrix_value[])
{
IIC_start(); //データ転送開始条件の関数を呼び出す
IIC_send(0xc0); //アドレスを選択
for (int i = 0; i < 16; i++) //パターンデータは16バイト
{
IIC_send(matrix_value[i]); //パターンデータを転送
}
IIC_end(); //パターンデータ転送を終了
IIC_start();
IIC_send(0x8A); //表示制御、パルス幅を4/16に選択
IIC_end();
}
//データ転送開始の条件
void IIC_start()
{
digitalWrite(SDA_Pin, HIGH);
digitalWrite(SCL_Pin, HIGH);
delayMicroseconds(3);
digitalWrite(SDA_Pin, LOW);
delayMicroseconds(3);
digitalWrite(SCL_Pin, LOW);
}
//データ送信終了のサイン
void IIC_end()
{
digitalWrite(SCL_Pin, LOW);
digitalWrite(SDA_Pin, LOW);
delayMicroseconds(3);
digitalWrite(SCL_Pin, HIGH);
delayMicroseconds(3);
digitalWrite(SDA_Pin, HIGH);
delayMicroseconds(3);
}
//データを転送
void IIC_send(unsigned char send_data)
{
for (byte mask = 0x01; mask != 0; mask <<= 1) //各文字は8桁あり、1つずつ検出される
{
if (send_data & mask) //各ビット(0または1)に応じてHIGHまたはLOWレベルを設定
{
digitalWrite(SDA_Pin, HIGH);
}
else
{
digitalWrite(SDA_Pin, LOW);
}
delayMicroseconds(3);
digitalWrite(SCL_Pin, HIGH); //クロックピンSCL_PinをHIGHに引き上げてデータ送信を停止
delayMicroseconds(3);
digitalWrite(SCL_Pin, LOW); //クロックピンSCL_Pinを引き下げてSDAの信号を変更
}
}
(5)テスト結果:
コードをアップロードした後、モータードライブシールドの電源スイッチをオンにします。ロボットを床に置き、上の表を参照して異なるボタンを押すと、ロボットは対応するプリセットの方向に動きます。





