Chapter 6 Infrared Car
6.1 Introduction of infrared reception function
Infrared Remote
An infrared(IR) remote control is a device with a certain number of buttons. Pressing down different buttons will make the infrared emission tube, which is located in the front of the remote control, send infrared ray with
different command. Infrared remote control technology is widely used in electronic products such as TV, air conditioning, etc. Thus making it possible for you to switch TV programs and adjust the temperature of the air conditioning when away from them. The remote control we use is shown below:
Infrared receiver
An infrared(IR) receiver is a component which can receive the infrared light, so we can use it to detect the signal emitted by the infrared remote control. DATA pin here outputs the received infrared signal.
When you use the infrared remote control, the infrared remote control sends a key value to the receiving circuit according to the pressed keys. We can program the Raspberry Pi Pico W to do things like lighting, when a key value is received.
The following is the key value that the receiving circuit will receive when each key of the infrared remote control is pressed.
ICON |
KEY Value |
ICON |
KEY Value |
|---|---|---|---|
|
BA45FF00 |
|
F20DFF00 |
|
B847FF00 |
|
F30CFF00 |
|
BB44FF00 |
|
E718FF00 |
|
BF40FF00 |
|
A15EFF00 |
|
BC43FF00 |
|
F708FF00 |
|
F807FF00 |
|
E31CFF00 |
|
EA15FF00 |
|
A55AFF00 |
|
F609FF00 |
|
BD42FF00 |
|
E916FF00 |
|
AD52FF00 |
|
E619FF00 |
|
B54AFF00 |
This sketch uses the infrared receiving tube to receive the value sent form the infrared remote control, and print it out via the serial port.
Sketch
Each time when you press the infrared remote control, the car will print the received infrared coding value through serial port.
Open the folder “05.1_IR_Receiver”in
“Freenove_4WD_Car_Kit_for_Raspberry_Pi_Pico\Ordinary_wheels\Sketches” and double click
“05.1_IR_Receiver.ino”.
Code
1/**********************************************************************
2 Filename : Infrared Remote Control
3 Description : Decode the infrared remote control and print it out through the serial port.
4 Auther : www.freenove.com
5 Modification: 2023/04/13
6**********************************************************************/
7#include <IRremote.hpp>
8#define IR_Pin 3 // Infrared receiving pin
9#define ENABLE_LED_FEEDBACK true
10#define DISABLE_LED_FEEDBACK false
11void setup() {
12 Serial.begin(115200); // Initialize the serial port and set the baud rate to 115200
13 IrReceiver.begin(IR_Pin, DISABLE_LED_FEEDBACK); // Start the receiver
14 Serial.print("IRrecvDemo is now running and waiting for IR message on Pin ");
15 Serial.println(IR_Pin); //print the infrared receiving pin
16}
17
18void loop() {
19 if (IrReceiver.decode()) {
20 unsigned long value = IrReceiver.decodedIRData.decodedRawData;
21 Serial.println(value, HEX); // Print "old" raw data
22 IrReceiver.resume(); // Enable receiving of the next value
23 }
24}
Download the code to Raspberry Pi Pico (W), open the serial port monitor, set the baud rate to 115200, press the IR remote control, the pressed keys value will be printed out through the serial port. As shown in the following figure: (Note that if the remote control button is long pressed, the infrared receiving circuit receives a “0”.)
First, include header file. Each time you use the infrared sensor, you need to include the header file at the beginning of the program.
1#include <IRremote.hpp>
Second, define an infrared receive pin and the infrared sensor is initialized.
1#define IR_Pin 3 // Infrared receiving pin
2...
3IrReceiver.begin(IR_Pin, DISABLE_LED_FEEDBACK); // Start the receiver
Finally, IrReceiver.decode() is used to determine whether an infrared signal has been received, returning true/1 if an infrared signal has been received, or false/0 if no infrared signal has been received; If an infrared signal is received, the received infrared coded value is printed through the serial port.
Please note that IrReceiver.resume() must be applied to release the infrared receiver function each time data are received. Otherwise, the infrared receiver function can only be used once and data cannot be received next time.
1if (IrReceiver.decode()) {
2 unsigned long value = IrReceiver.decodedIRData.decodedRawData;
3 Serial.println(value, HEX); // Print "old" raw data
4 IrReceiver.resume(); // Enable receiving of the next value
5}
6.2 Infrared Car
Based on the previous section, we use the infrared remote control to control the car. Press the black button on the infrared remote control to control the car to move forward, backward, turn left, and turn right. Press other buttons and the cart stops moving.
Sketch
Open the folder “05.2_IR_Receiver_Car” in the “Freenove_4WD_Car_Kit_for_Raspberry_Pi_Pico\Ordinary_wheels\Sketches” and double click “05.2_IR_Receiver_Car.ino”.
Code
1/**********************************************************************
2 Filename : IR_Receiver_Car.ino
3 Product : Freenove 4WD Car for Raspberry Pi Pico (W)
4 Auther : www.freenove.com
5 Modification: 2023/04/13
6**********************************************************************/
7#include <Arduino.h>
8#include <IRremote.hpp>
9#include "Freenove_4WD_Car_For_Pico_W.h"
10#define IR_Pin 3
11#define ENABLE_LED_FEEDBACK true
12#define DISABLE_LED_FEEDBACK false
13int motor_speed = 50;
14int emotionMode = 4;
15int motor_flag = 0;
16
17void setup() {
18 Serial.begin(115200);
19 Motor_Setup(); //Motor initialization
20 Emotion_Setup(); //Initializes Emotion module
21 IrReceiver.begin(IR_Pin, DISABLE_LED_FEEDBACK); // Start the receiver
22}
23
24void loop() {
25 if (IrReceiver.decode()) {
26 unsigned long value = IrReceiver.decodedIRData.decodedRawData;
27 handleControl(value); // Handle the commands from remote control
28 Serial.println(value, HEX); // Print "old" raw data
29 Serial.println();
30 IrReceiver.resume(); // Enable receiving of the next value
31 }
32 showEmotion(emotionMode);
33}
34
35void handleControl(unsigned long value) {
36 // Handle the commands
37 switch (value) {
38 case 0xBF40FF00: // Receive the number '+'
39 motor_flag = 1;
40 Motor_Move(motor_speed , motor_speed); // Go forward
41 delay(200);
42 Motor_Move(0 , 0);
43 break;
44
45 case 0xE619FF00: // Receive the number '-'
46 motor_flag = 2;
47 Motor_Move(-motor_speed , -motor_speed); // Back up
48 delay(200);
49 Motor_Move(0 , 0);
50 break;
51
52 case 0xF807FF00: // Receive the number '|<<'
53 motor_flag = 3;
54 Motor_Move(-motor_speed , motor_speed); // Turn left
55 delay(200);
56 Motor_Move(0 , 0);
57 break;
58
59 case 0xF609FF00: // Receive the number '>>|'
60 motor_flag = 4;
61 Motor_Move(motor_speed , -motor_speed); // Turn right
62 delay(200);
63 Motor_Move(0 , 0);
64 break;
65
66 case 0xE916FF00: // Receive the number '0'
67 emotionMode = millis() % 10;
68 break;
69
70 default:
71 motor_flag = 0;
72 Motor_Move(0 , 0); //stop
73 break;
74 }
75}
Compile and upload the code to Raspberry Pi Pico (W). When pressing “0” of the infrared remote control, the expression module will randomly display the content dynamically.
|
|
Move forward |
|
|
Turn left |
|
|
Turn right |
|
|
Move back |
Code Explanation
Variable IrReceiver.DecodedIRData.DecodedRawData holds the infrared remote control encoding information, call handleccontrol function performs different code value corresponding action. After each execution of the program, call the IrReceiver.resume() function to release the infrared pin. If you do not call this function, you cannot use the infrared receiving and decoding functions again.
1void loop() {
2 if (IrReceiver.decode()) {
3 unsigned long value = IrReceiver.decodedIRData.decodedRawData;
4 handleControl(value); // Handle the commands from remote control
5 Serial.println(value, HEX); // Print "old" raw data
6 Serial.println();
7 IrReceiver.resume(); // Enable receiving of the next value
8 }
9 showEmotion(emotionMode);
10}
Infrared key code value processing function, receives instructions sent by the infrared remote control, and execute the corresponding program.
1void handleControl(unsigned long value) {
2 // Handle the commands
3 switch (value) {
4 case 0xBF40FF00: // Receive the number '+'
5 ...
6 case 0xE619FF00: // Receive the number '-'
7 ...
8 case 0xF807FF00: // Receive the number '|<<'
9 ...
10 case 0xF609FF00: // Receive the number '>>|'
11 ...
12 case 0xE916FF00: // Receive the number '0'
13 ...
14 default: // Control the car to stop moving
15 ...
16 }
17}
6.3 Multi-Functional Infrared Car
Following the previous section, we now integrate other functions into the infrared car, and most of the car’s functions can be controlled by the infrared remote.
Sketch
Open the folder “05.3_Multi_Functional_Car” in the “Freenove_4WD_Car_Kit_for_Raspberry_Pi_Pico\Ordinary_wheels\Sketches” and double click “05.3_Multi_Functional_Car.ino”.
Code
1/**********************************************************************
2 Filename : IR_Receiver_Car.ino
3 Product : Freenove 4WD Car for Raspberry Pi Pico (W)
4 Auther : www.freenove.com
5 Modification: 2023/04/13
6**********************************************************************/
7#include <Arduino.h>
8#include <Adafruit_NeoPixel.h>
9#include <IRremote.hpp>
10#include "Freenove_4WD_Car_For_Pico_W.h"
11#include "Freenove_4WD_Car_Emotion.h"
12#include "Freenove_VK16K33_Lib.h"
13#include "Freenove_4WD_Car_WS2812.h"
14
15#define IR_Pin 3 // Infrared receiving pin
16#define ENABLE_LED_FEEDBACK true
17#define DISABLE_LED_FEEDBACK false
18
19static int servo_1_angle = 90;
20int emotion_flag = 0;
21int ws2812_flag = 0;
22
23int CAR_MODE_VOL = 0;
24int LASt_CAR_MODE_VOL = 0;
25
26void setup() {
27 Serial.begin(115200); //Turn on the serial port monitor and set the baud rate to 115200
28 Motor_Setup(); //Initialize motor
29 Servo_Setup(); //Initialize servo
30 Buzzer_Setup(); //Initialize the buzzer
31 WS2812_Setup(); //WS2812 initialization
32 Emotion_and_Ultrasonic_Setup();
33 IrReceiver.begin(IR_Pin, DISABLE_LED_FEEDBACK); // Start the receiver
34 Servo_1_Angle(servo_1_angle);
35 delay(100);
36}
37
38void loop() {
39 if (IrReceiver.decode()) {
40 unsigned long value=IrReceiver.decodedIRData.decodedRawData;
41 handleControl(value); // Handle the commands from remote control
42 Serial.println(value, HEX); // Print "old" raw data
43 Serial.println();
44 IrReceiver.resume(); // Enable receiving of the next value
45 }
46 Emotion_and_Ultrasonic_Setup();
47 oa_CalculateVoltageCompensation();
48 if (Check_Module_value == MATRIX_IS_EXIST) {
49 Emotion_Show(emotion_task_mode); //Led matrix display function
50 } else if (Check_Module_value == SONAR_IS_ESIST) {
51 }
52 Car_Select(carFlag);
53 WS2812_Show(ws2812_task_mode); //Car color lights display function
54}
55
56void handleControl(unsigned long value) {
57 // Handle the commands
58 switch (value) {
59 case 0xBF40FF00: // Receive the number '+'
60 Motor_Move(50, 50);
61 delay(300);
62 Motor_Move(0, 0);
63 break;
64 case 0xE619FF00: // Receive the number '-'
65 Motor_Move(-50, -50);
66 delay(300);
67 Motor_Move(0, 0);
68 break;
69 case 0xF807FF00: // Receive the number '|<<'
70 Motor_Move(-50, 50);
71 delay(300);
72 Motor_Move(0, 0);
73 break;
74 case 0xF609FF00: // Receive the number '>>|'
75 Motor_Move(50, -50);
76 delay(300);
77 Motor_Move(0, 0);
78 break;
79 case 0xEA15FF00: // Receive the number '▶'
80 Motor_Move(0, 0);
81 break;
82 case 0xE916FF00: // Receive the number '0'
83 servo_1_angle = servo_1_angle + 10;
84 Servo_1_Angle(servo_1_angle);
85 break;
86 case 0xF30CFF00: // Receive the number '1'
87 servo_1_angle = servo_1_angle - 10;
88 Servo_1_Angle(servo_1_angle);
89 break;
90 case 0xF708FF00: // Receive the number '4'
91 servo_1_angle = 90;
92 Servo_1_Angle(servo_1_angle);
93 break;
94 case 0xF20DFF00: // Receive the number 'C'
95 isLightModeFirstStarting = true;
96 Servo_1_Angle(90);
97 Car_SetMode(1);
98 break;
99 case 0xA15EFF00: // Receive the number '3'
100 Servo_1_Angle(90);
101 Car_SetMode(2);
102 break;
103 case 0xA55AFF00: // Receive the number '6'
104 Servo_1_Angle(90);
105 if (Check_Module_value == SONAR_IS_ESIST) {
106 LASt_CAR_MODE_VOL = 1;
107 Car_SetMode(3);
108 }
109 if (Check_Module_value != SONAR_IS_ESIST) {
110 Buzzer_Variable(2000, 50, 2);
111 Car_SetMode(0);
112 Motor_Move(0, 0);
113 }
114 break;
115 case 0xB54AFF00: // Receive the number '9'
116 emotion_flag = 0;
117 Emotion_SetMode(emotion_flag);
118 Servo_1_Angle(90);
119 Car_SetMode(0);
120 Motor_Move(0, 0);
121 break;
122 case 0xBB44FF00: // Receive the number 'TEST'
123 Buzzer_Variable(2000, 100, 1);
124 break;
125 case 0xE718FF00: // Receive the number '2'
126 if (Check_Module_value == MATRIX_IS_EXIST) {
127 emotion_flag = emotion_flag + 1;
128 if (emotion_flag > 7) {
129 emotion_flag = 0;
130 }
131 Emotion_SetMode(emotion_flag); //Display
132 Serial.print(" \n matrix is exist !!! \n");
133 }
134 if (Check_Module_value != MATRIX_IS_EXIST) {
135 Buzzer_Variable(2000, 50, 2);
136 Serial.print(" \n sonar is exist !!! \n");
137 }
138 break;
139 case 0xE31CFF00: // Receive the number '5'
140 emotion_flag = 0;
141 Emotion_SetMode(emotion_flag);
142 break;
143 case 0xBD42FF00: // Receive the number '7'
144 ws2812_flag = ws2812_flag + 1;
145 if (ws2812_flag >= 6) {
146 ws2812_flag = 0;
147 }
148 WS2812_SetMode(ws2812_flag);
149 break;
150 case 0xAD52FF00: // Receive the number '8'
151 ws2812_flag = 0;
152 WS2812_SetMode(ws2812_flag);
153 break;
154 case 0xFFFFFFFF: // Remain unchanged
155 break;
156 default:
157 break;
158 }
159}
After the code is successfully uploaded, turn on the power of the car and use the infrared remote to control the car and other functions. The corresponding keys and their functions are shown in the following table:
ICON |
KEY Value |
Function |
ICON |
KEY Value |
Function |
|
BF40FF00 |
Move forward |
|
E718FF00 |
Change the expression display mode |
|
F807FF00 |
Turn left |
|
E31CFF00 |
Turn off emoticons |
|
F609FF00 |
Turn light |
|
BD42FF00 |
Change the display mode of the WS2812 |
|
E619FF00 |
Move back |
|
AD52FF00 |
Turn off WS2812 display |
|
EA15FF00 |
Stop the car |
|
F20DFF00 |
Light tracing car mode |
|
E916FF00 |
Control servo turn left |
|
A15EFF00 |
Line tracking car mode |
|
F30CFF00 |
Control servo turn right |
|
A55AFF00 |
Ultrasonic obstacle avoidance car mode |
|
F708FF00 |
Control servo turn to 90° |
|
B54AFF00 |
Manual control mode |
|
BB44FF00 |
Control the buzzer |
Since the ultrasonic module shares the interface with the LED Matrix, only one of them can be used at the same time. When the function of the sent button conflicts with the current head module, the buzzer will sound twice continuously. The situations can be as follows:
When “6” is pressed, if the LED Matrix is connected to the head, the buzzer will sound twice.
When “2” is pressed, if the head is connected to an ultrasonic module, the buzzer will sound twice.
When you hear the buzzer beep twice, please replace the module on the head to continue the experiment.
Code Explanation
Add the header file for the car.
1#include <Arduino.h>
2#include <Adafruit_NeoPixel.h>
3#include <IRremote.hpp>
4#include "Freenove_4WD_Car_For_Pico_W.h"
5#include "Freenove_4WD_Car_Emotion.h"
6#include "Freenove_VK16K33_Lib.h"
7#include "Freenove_4WD_Car_WS2812.h"
Initialize each function of the car.
1Serial.begin(115200); //Turn on the serial port monitor and set the baud rate to 115200
2Motor_Setup(); //Initialize motor
3Servo_Setup(); //Initialize servo
4Buzzer_Setup(); //Initialize the buzzer
5WS2812_Setup(); //WS2812 initialization
6Emotion_and_Ultrasonic_Setup();
7IrReceiver.begin(IR_Pin, DISABLE_LED_FEEDBACK); // Start the receiver
8Servo_1_Angle(servo_1_angle);
9delay(100);
Infrared key code value processing function receives instructions sent by the infrared remote control and execute the corresponding program.
1void handleControl(unsigned long value) {
2 // Handle the commands
3 switch (value) {
4 case 0xBF40FF00: // Receive the number '+'
5 ...
6 case 0xE619FF00: // Receive the number '-'
7 ...
8 case 0xF807FF00: // Receive the number '|<<'
9 ...
10 case 0xF609FF00: // Receive the number '>>|'
11 ...
12 case 0xEA15FF00: // Receive the number '▶'
13 ...
14 case 0xE916FF00: // Receive the number '0'
15 ...
16 case 0xF30CFF00: // Receive the number '1'
17 ...
18 case 0xF708FF00: // Receive the number '4'
19 ...
20 case 0xF20DFF00: // Receive the number 'C'
21 ...
22 case 0xA15EFF00: // Receive the number '3'
23 ...
24 case 0xA55AFF00: // Receive the number '6'
25 ...
26 case 0xB54AFF00: // Receive the number '9'
27 ...
28 case 0xBB44FF00: // Receive the number 'TEST'
29 ...
30 case 0xE718FF00: // Receive the number '2'
31 ...
32 case 0xE31CFF00: // Receive the number '5'
33 ...
34 case 0xBD42FF00: // Receive the number '7'
35 ...
36 case 0xAD52FF00: // Receive the number '8'
37 ...
38 case 0xFFFFFFFF: // Remain unchanged
39 break;
40 default:
41 break;
42 }
43}



























