### Project 15: IR Remote Control Tank ![](./media/image-20250709113214889.png) #### **(1)Description:** Infrared remote control is one of the most common remote control found applications in electric motors, electric fans, and many other household appliances. In this project,we use the knowledge we learned before to make an infrared remote control smart car. In the 9th lesson, we have tested the corresponding key value of each key of the infrared remote control. In the project, we can set the code (key value) to make the corresponding button to control the movements of the smart car, and display the movement patterns on the 8X16 LED dot matrix. The specific logic of the line-tracking smart car is shown in the table: | Ultrasonic key | Key value | Instructions from keys | | :----------------------------------------------------------: | :-------: | :----------------------------------------------------------: | | ![image-20230427094710725](media/image-20230427094710725.png) | FF629D | Move forward(set PWM to 200)
display the pattern of going forward | | ![image-20230427094716639](media/image-20230427094716639.png) | FFA857 | Go back(set PWM to 200)
display the pattern of going back | | ![image-20230427094720417](media/image-20230427094720417.png) | FF22DD | Turn left
display the pattern“STOP” | | ![image-20230427094725151](media/image-20230427094725151.png) | FFC23D | Turn right
display the pattern of turning left | | ![image-20230427094729839](media/image-20230427094729839.png) | FF02FD | Stop
display the pattern“STOP” | **Initial setting**: 8X16 LED dot matrix shows the pattern“![](media/wps20.jpg)”. #### **(2)Flow chart:** ![](media/wps21.png) #### **(3)Connection Diagram:** ![](media/54527fe245b218dd22bdff5dafd4805d.png) Note: GND, VCC, SDA and SCL of the 8x16 LED panel are connected to G(GND), V(VCC). SDA and SCL of the expansion board. Since the 8833 board integrates the IR receiver, you don’t need to wire it up. The pins of the IR receiver are G(GND), V(VCC) and D3. #### (4)**Test Code:** (**Note:** Do not connect the Bluetooth module before uploading the code, because uploading the code also uses serial communication, and there may be conflicts with the Bluetooth serial communication, which can cause the upload to fail.) ```C /* Keyestudio Mini Tank Robot V3 (Popular Edition) lesson 15 IRremote Control Tank http://www.keyestudio.com */ #include IRrecv irrecv(3); // decode_results results; long ir_rec; //Used to store the received infrared values //Array, used to save data of images, can be calculated by yourself or gotten from modulus tool 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 //Set the clock pin as A5 #define SDA_Pin A4 //Set the data pin as A4 #define ML_Ctrl 4 //Define the direction control pin of the left motor #define ML_PWM 6 //Define the PWM control pin of the left motor #define MR_Ctrl 2 //Define the direction control pin of the right motor #define MR_PWM 5 //Define the PWM control pin of the right motor void setup() { Serial.begin(9600); irrecv.enableIRIn(); //Initialize infrared receiver library 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); //clear screens matrix_display(start01); //show the image to start } void loop() { if (irrecv.decode(&results)) //Receive infrared remote control value { 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; //the command to go front case 0xFFA857: Car_back(); break; //the command to go back case 0xFF22DD: Car_T_left(); break; //the command to turn left case 0xFFC23D: Car_T_right(); break; //the command to turn right case 0xFF02FD: Car_Stop(); break; //the command to stop case 0xFF30CF: Car_left(); break; //the command to rotate to left case 0xFF7A85: Car_right(); break; //the command to rotate to right default: break; } } /***************The function to run the motor***************/ void Car_back() { digitalWrite(MR_Ctrl, LOW); analogWrite(MR_PWM, 200); digitalWrite(ML_Ctrl, LOW); analogWrite(ML_PWM, 200); matrix_display(back); //Go back } void Car_front() { digitalWrite(MR_Ctrl, HIGH); analogWrite(MR_PWM, 55); digitalWrite(ML_Ctrl, HIGH); analogWrite(ML_PWM, 55); matrix_display(front); //show the image to go front } void Car_left() { digitalWrite(MR_Ctrl, HIGH); analogWrite(MR_PWM, 55); digitalWrite(ML_Ctrl, LOW); analogWrite(ML_PWM, 200); matrix_display(left); //show the image to turn lefr } void Car_right() { digitalWrite(MR_Ctrl, LOW); analogWrite(MR_PWM, 200); digitalWrite(ML_Ctrl, HIGH); analogWrite(ML_PWM, 55); matrix_display(right); //show the image to turn right } void Car_Stop() { digitalWrite(MR_Ctrl, LOW); analogWrite(MR_PWM, 0); digitalWrite(ML_Ctrl, LOW); analogWrite(ML_PWM, 0); matrix_display(STOP01); //show the image to stop } void Car_T_left() { digitalWrite(MR_Ctrl, HIGH); analogWrite(MR_PWM, 0); digitalWrite(ML_Ctrl, HIGH); analogWrite(ML_PWM, 100); matrix_display(left); //show the image to turn lefr } void Car_T_right() { digitalWrite(MR_Ctrl, HIGH); analogWrite(MR_PWM, 100); digitalWrite(ML_Ctrl, HIGH); analogWrite(ML_PWM, 0); matrix_display(right); //show the image to turn right } //This function is used for dot matrix screen display void matrix_display(unsigned char matrix_value[]) { IIC_start(); //Function to call data transfer start condition IIC_send(0xc0); //Choose an address for (int i = 0; i < 16; i++) //Pattern data has 16 bytes { IIC_send(matrix_value[i]); //transfer pattern data } IIC_end(); //End pattern data transfer IIC_start(); IIC_send(0x8A); //display control, select pulse width as 4/16 IIC_end(); } //Conditions for the start of data transfer void IIC_start() { digitalWrite(SDA_Pin, HIGH); digitalWrite(SCL_Pin, HIGH); delayMicroseconds(3); digitalWrite(SDA_Pin, LOW); delayMicroseconds(3); digitalWrite(SCL_Pin, LOW); } //the sign of ending data transmission 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); } //transfer data void IIC_send(unsigned char send_data) { for (byte mask = 0x01; mask != 0; mask <<= 1) //each character has 8 digits, which is detected one by one { if (send_data & mask) //set high or low levels in light of each bit(0 or 1) { digitalWrite(SDA_Pin, HIGH); } else { digitalWrite(SDA_Pin, LOW); } delayMicroseconds(3); digitalWrite(SCL_Pin, HIGH); //Pull the clock pin SCL_Pin high to stop data transmission delayMicroseconds(3); digitalWrite(SCL_Pin, LOW); //pull down the clock pin SCL_Pin to change signals of SDA } } ``` #### **(5)Test Result:** After uploading the code, turn on the power switch of the motor drive shield. Place the robot on the floor, refer to the table above and press different buttons, the robot will move in the corresponding preset direction. ![](./media/img-20240117090114.png)