Tutorial
Tutorial
Tutorial
com Contents I
Getting started
Thank you for choosing Freenove products!
First, read the document About_Battery.pdf in the unzipped folder.
If you did not download the zip file, please download it and unzip it via link below.
https://github.com/Freenove/Freenove_4WD_Car_Kit/archive/master.zip
Freenove provides free and responsive product and technical support, including but not limited to:
Product quality issues
Product use and build issues
Questions regarding the technology employed in our products for learning and education
Your input and opinions are always welcome
We also encourage your ideas and suggestions for new products and product improvements
For any of the above, you may send us an email to:
[email protected]
Safety and Precautions
Please follow the following safety precautions when using or storing this product:
Keep this product out of the reach of children under 6 years old.
This product should be used only when there is adult supervision present as young children lack
necessary judgment regarding safety and the consequences of product misuse.
This product contains small parts and parts, which are sharp. This product contains electrically conductive
parts. Use caution with electrically conductive parts near or around power supplies, batteries and
powered (live) circuits.
When the product is turned ON, activated or tested, some parts will move or rotate. To avoid injuries to
hands and fingers, keep them away from any moving parts!
It is possible that an improperly connected or shorted circuit may cause overheating. Should this happen,
immediately disconnect the power supply or remove the batteries and do not touch anything until it
cools down! When everything is safe and cool, review the product tutorial to identify the cause.
Only operate the product in accordance with the instructions and guidelines of this tutorial, otherwise
parts may be damaged or you could be injured.
Store the product in a cool dry place and avoid exposing the product to direct sunlight.
After use, always turn the power OFF and remove or unplug the batteries before storing.
www.freenove.com
II Contents www.freenove.com █
We also have cars and robot kit for Raspberry Pi. If you are interesting in them, please visit our website for
details.
http://www.freenove.com/store.html
https://www.youtube.com/watch?v=4Zv0GZUQjZc
https://www.youtube.com/watch?v=7BmIZ8_R9d4&t=35s
www.freenove.com
[email protected] Contents III
About Freenove
Freenove is committed to assist customers in their education of robotics, programming and electronic circuits
so that they may transform their creative ideas into prototypes and new and innovative products. To this end,
our services include but are not limited to:
Educational and Entertaining Project Kits for Robots, Smart Cars and Drones
Educational Kits to Learn Robotic Software Systems for Arduino, Raspberry Pi and micro: bit
Electronic Component Assortments, Electronic Modules and Specialized Tools
Product Development and Customization Services
You can find more about Freenove and get our latest news and updates through our website:
http://www.freenove.com
Copyright
All the files, materials and instructional guides provided are released under Creative Commons Attribution-
NonCommercial-ShareAlike 3.0 Unported License. A copy of this license can be found in the folder containing
the Tutorial and software files associated with this product.
This means you can use these resource in your own derived works, in part or completely, but NOT for the
intent or purpose of commercial use.
Freenove brand and logo are copyright of Freenove Creative Technology Co., Ltd. and cannot be used without
written permission.
○
R
www.freenove.com
IV Contents www.freenove.com █
Contents
Getting started....................................................................................................................................................................... I
Get Support and Offer Input ...................................................................................................................................... I
Safety and Precautions ................................................................................................................................................ I
Car and Robot for Raspberry Pi ................................................................................................................................ II
About Freenove .......................................................................................................................................................... III
Contents................................................................................................................................................................................ IV
List ........................................................................................................................................................................................... 1
Preface ................................................................................................................................................................................... 7
Control Board and Software .............................................................................................................................................. 8
Chapter 0 Preparation, Assembly and Play ................................................................................................................... 11
0.1 Preparation ............................................................................................................................ 错误!未定义书签。
0.2 Assembly............................................................................................................................................................... 16
0.3 How to Play .......................................................................................................................................................... 26
Chapter 1 Control Basic Components............................................................................................................................ 36
1.1 Motor..................................................................................................................................................................... 36
1.2 Buzzer and Battery level .................................................................................................................................... 45
1.3 RGB ........................................................................................................................................................................ 51
1.4 Integrate functions.............................................................................................................................................. 56
Chapter 2 Obstacle avoidance ........................................................................................................................................ 65
2.1 Servo...................................................................................................................................................................... 65
2.2 Ultrasonic ranging module................................................................................................................................ 67
2.3 Automatic Obstacle Avoidance Car................................................................................................................. 72
Chapter 3 Line tracking ..................................................................................................................................................... 85
3.1 Line tracking sensor ............................................................................................................................................ 85
3.2 Line tracking car .................................................................................................................................................. 88
Chapter 4 IR control .......................................................................................................................................................... 92
4.1 Infrared remote and receiver ............................................................................................................................ 92
4.2 IR Remote Car ...................................................................................................................................................... 95
4.3 Multifunctional IR Remote Car ......................................................................................................................... 98
Chapter 5 RF Remote Control ....................................................................................................................................... 106
5.1 Remote Control ................................................................................................................................................. 106
5.2 Receive RF Remote Control Data ................................................................................................................... 109
5.3 RF Remote Car ................................................................................................................................................... 114
5.4 Multifunctional RF24 Remote Car .................................................................................................................. 118
Chapter 6 Bluetooth control .......................................................................................................................................... 132
6.1 Set Bluetooth and Receive Data..................................................................................................................... 132
6.2 Bluetooth Remote Car...................................................................................................................................... 142
6.3 Multifunctional Bluetooth Remote Car ......................................................................................................... 149
What is next?..................................................................................................................................................................... 160
www.freenove.com
[email protected] List 1
List
Acrylic Parts
The surface of the acrylic parts is covered with a layer of protective film. You need to remove it first.
Some holes in the acrylic parts may have residues. You also need to clean them before using.
www.freenove.com
2 List [email protected]
Mechanical Parts
Servo x1 Motor x4
www.freenove.com
[email protected] List 3
Electronic Parts
Freenove control board (Your kit will randomly contain one control board)
Or
Freenove 4WD extension board
www.freenove.com
4 List [email protected]
WS2812B_LED_controller WS2812B_LED
IRreceiver Tape
www.freenove.com
[email protected] List 5
RF remote kit package (only contained in the Version with RF remote control)
The remote kit also has two versions, black or blue. You will receive one of them randomly.
www.freenove.com
6 List [email protected]
Tools
Cross Screwdriver x1
www.freenove.com
[email protected] Preface 7
Preface
This 4WD Smart car is based on Arduino.
This tutorial will start from controlling electronic components such as LED, motor, servo, to building
multifunctional car.
Please follow the tutorial step by step patiently.
If you have any concerns, please feel free to contact us. Our support team will provide quick and free customer
service.
www.freenove.com
8 Control Board and Software [email protected]
Control Board
Reset button
LED L
LED TX
LED RX
DC interface
Digital I/O ports is used to connect to other components or modules, to receive an input signal, or to
send a control signal. Usually, we name it by adding a "D" in front of the number, such as D13.
Only digital I/O ports with “~” can output PWM, Pin 3, 5, 6, 9, 10, 11.
USB interface is used to provide power, upload code or communicate with PC.
LED L is connected to digital I/O port 13 (D13).
LED TX, RX is used to indicate the state of the serial communication.
DC interface is connected with DC power to provide power for the board.
Power ports can provide power for electronic components and modules.
Analog I/O ports can be used to measure analog signals.
LED ON is used to indicate the power state.
www.freenove.com
[email protected] Control Board and Software 9
If you want to learn more about how to use Freenove control board to create interesting projects, please
visit http://www.freenove.com/store.html for Arduino kits designed for beginners.
Extension Board
Active buzzer
Receiver port
Bluetooth
port
Servo port
I2C port
Power port
www.freenove.com
10 Control Board and Software [email protected]
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 11
Please visit https://www.arduino.cc, then click "SOFTWARE" – “DOWNLOADS” to enter the downloads page.
Find "Download the Arduino IDE". Microsoft Windows users please click the "Windows Installer".
After the download completes, run the installer and complete the installation.
Open the Arduino Software, the interface of Arduino Software is as follows:
www.freenove.com
12 Chapter 0 Software, Assembly and Play [email protected]
Programs written with Arduino Software (IDE) are called sketches. These sketches are written in the text editor
and are saved with the file extension .ino. The editor has features for cutting/pasting and for
searching/replacing text. The message area gives feedback while saving and exporting and it also displays
errors. The console displays text output by the Arduino Software (IDE), including complete error messages
and other information. The bottom right corner of the window displays the configured board and serial port.
The toolbar buttons allow you to verify and upload programs, create, open, and save sketches, and open the
serial monitor.
Verify, Checks your code for errors compiling it.
Upload, Compiles your code and uploads it to the configured board.
New, Creates a new sketch.
Open, Presents a menu of all the sketches in your sketchbook. Clicking one will open it
within the current window overwriting its content.
Save, Saves your sketch.
Serial Monitor, Opens the serial monitor.
Additional commands are found within the five menus: File, Edit, Sketch, Tools, Help. The menus are context
sensitive, which means only those items relevant to the work currently being carried out are available.
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 13
If the port doesn’t work, please install the driver for the board.
Freenove_4WD_Car_Kit\Drivers
www.freenove.com
14 Chapter 0 Software, Assembly and Play [email protected]
Connect the control board to computer via USB cable. And then check Port again. You will find a COM added.
That is the port of control board. Here it is COM19. In your computer, it would be a different number.
Click "Verify" button and “Upload” button. “Done uploading” indicates that the code is uploaded successfully.
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 15
www.freenove.com
16 Chapter 0 Software, Assembly and Play [email protected]
0.3 Assembly
If you have any concerns, please feel free to contact us via [email protected]
In this chapter, we will learn how to assemble this car. This will spend some time. Please be patient.
Install Motor Bracket on bottom acrylic board, with screw M3*8 in the same bag.
Screw M3*8
In your kit, the bottom acrylic board may look like below:
Install Motor Bracket on bottom acrylic board, with screw M3*30 and Nut M3 in the same bag.
Nut M3
Screw M3*30
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 17
Nut M3
www.freenove.com
18 Chapter 0 Software, Assembly and Play [email protected]
Install line tracking module with Screw M3*8 and Nut M3.
Nut M3
Screw M3*8
If you have other kind of bottom acrylic board, please install the tracking module like below.
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 19
Nut M3
LED 5x1
Not F
3x2 Pins
Don’t reverse.
LED controller
4x2 Pins
LED 5x1
Screw M3*8
Connect wiring of LED controller and LED 5X1. The wire need to be twisted 180°.
www.freenove.com
20 Chapter 0 Software, Assembly and Play [email protected]
Standoff M3*10
M3*8
Screw M3*6
Screw M3*6
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 21
Connect LED controller with extension board with jumper wire F-F 4P. Wires of LED are hidden.
GND-GND, 5V-VCC, SCAL-RX, SDA-TX.
Some battery holders have short cable. Please rotate the battery holder for 180° to install.
www.freenove.com
22 Chapter 0 Software, Assembly and Play [email protected]
Install servo.
Screw M2*10
Nut M2
Install battery. And conect servo to servo port, yellow-SIG pin, red-5v, brown-GND.
Spring end
18650 3.7V rechargeable lithium battery x2 It is easier to find proper battery on eBay than Amazon.
Connect power supply to extension board (the top board, not control board board).
Turn on
Turn on
If you have uploaded code before, just turn on the switch of extension board and battery holder.
If not, you need upload the code.
Some battery holders have short cable. Please rotate the battery holder for 180° to install.
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 23
Install servo arm with sonic module connector. The screw and arm are in the same bag with servo.
Servo arm
Connect servo arm to servo. Make sure servo arm is installed at 90 degrees.
www.freenove.com
24 Chapter 0 Software, Assembly and Play [email protected]
M1 M3
M2 M4
Self-taping screw
1.4*4
Inside line
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 25
Standoff
M3*40
Screw M3*6
Screw M3*6
www.freenove.com
26 Chapter 0 Software, Assembly and Play [email protected]
You can follow this video or the later steps to play this car:
https://youtu.be/HxXmkmQxEjY
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 27
If you have installed RF24 libraries, you need select to install Version 1.3.2
www.freenove.com
28 Chapter 0 Software, Assembly and Play [email protected]
If you want to use different control ways, you need to upload different codes.
IR remote control
1) Install IR receiver to the car. And remove the plastic paper from IR remote.
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 29
2) Upload following code to the car board. Please remove Bluetooth Module when you upload code.
Freenove_4WD_Car_Kit\Sketches\04.4_One_Code_Multifunctional_IR_Remote_Car.ino
After uploading successfully, you can use the IR remote control to control the car.
www.freenove.com
30 Chapter 0 Software, Assembly and Play [email protected]
After the code is successfully uploaded, turn on the power of the car and use the infrared remote control to
control the car and other functions. The corresponding keys and their functions are shown in the following
table:
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 31
RF remote control
Download tutorial and code to assemble remote controller.
https://github.com/Freenove/Freenove_Remote_Control_Kit/raw/master/Tutorial(forBlackBoard).pdf
www.freenove.com
32 Chapter 0 Software, Assembly and Play [email protected]
After uploading successfully, you can use the RF remote control to control the car.
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 33
1, Change the switch state of S1, S2, and S3, and the car will stop moving.
2, Press the Z axis of the joystick and the buzzer B sounds to indicate that the mode is successfully switched.
The following table shows the modes indicated by the different states of the three switches S1, S2, and S3.
The LED next to the switch illuminates to indicate ON and OFF state of switches. The three switches can form
2x2x2=8 modes.
S1 S2 S3 Mode No. Mode
ON ON ON 0 None
ON ON OFF 1 Calibrate servo mode
ON OFF ON 2 None
ON OFF OFF 3 Obstacle avoidance mode
OFF ON ON 4 None
OFF ON OFF 5 Line tracking mode
OFF OFF ON 6 Switch LED mode
OFF OFF OFF 7 Manuel control mode / Default mode
Mode 0, 2, 4
Reserved. We did not assign functions for them.
www.freenove.com
34 Chapter 0 Software, Assembly and Play [email protected]
In this mode, you can adjust potentiometer 2 (POT2) to fine tune the angle of the servo. When you adjust the
servo to the correct angle, press the Z-axis of joystick to save calibration data to EEPROM. It will be saved
permanently unless it is modified.
Mode 3-obstical avoidance, Mode 5-line tracking mode
These two modes have been learned separately in the previous project, and their running logic and codes are
consistent with the previous project.
The difference is that in this project, the car can respond to commands from the remote control at any time.
Therefore, in this project, it is still necessary to communicate with the remote controller in these two modes.
When the remote control signal is disconnected, the car will stop. Therefore, the normal communication
between the remote control and the car should be maintained at any time. Poor communication conditions
may cause these two modes to work abnormally.
Mode 6-switch LED display mode
There are three display modes for the LEDs on the car, which are 0-flowing rainbow, 1-flowing water led, 2-
Blink. In this mode, the display mode of the LED can be switched.
In any mode, the LEDs can be adjusted with potentiometers P1 and P2. P1 is used to adjust the color change
of the LED, and P2 is used to adjust the change frequency of LED.
P1(POT1)
P2(POT2)
You can switch the
display mode of the
LED by turning the
joystick in the
direction of the X axis.
www.freenove.com
[email protected] Chapter 0 Software, Assembly and Play 35
www.freenove.com
36 Chapter 1 Control Basic Components [email protected]
1.1 Motor
When motor is connected to the power supply, it will rotate in one direction. Reverse the polarity of power
supply, the motor will rotate in the opposite direction.
And the speed of motor depends on the voltage between two ends. The larger the voltage, the lager the
speed.
PWM
PWM, Pulse Width Modulation, uses digital pins to send certain frequencies of square waves, that is, the
output of high levels and low levels, which alternately last for a while. The total time for each set of high levels
and low levels is generally fixed, which is called the period (the reciprocal of the period is frequency). The time
of high level outputs are generally called “pulse width”, and the duty cycle is the percentage of the ratio of
pulse duration, or pulse width (PW) to the total period (T) of the waveform.
The longer the output of high levels last, the larger the duty cycle and the higher the corresponding voltage
in analog signal will be. The following figures show how the analogs signal voltage vary between 0V-5V
(high level is 5V) corresponding to the pulse width 0%-100%:
www.freenove.com
[email protected] Chapter 1 Control Basic Components 37
The longer the PWM duty cycle is, the higher the output power will be. Now that we understand this
relationship, we can use PWM to control the brightness of an LED or the speed of DC motor and so on.
GND GND
In this car, M1 and M2 are connected in parallel; M3 and M4 are connected in parallel. Schematic is below:
www.freenove.com
38 Chapter 1 Control Basic Components [email protected]
D3 and D5 pins of control board control M3 and M4 respectively. D4 and D6 pins of board control M1 and
M2.
www.freenove.com
[email protected] Chapter 1 Control Basic Components 39
M1 M3
M4
M2
Code
01.1.1_RunMotor_Left_Wheel
If you don’t know how to upload code to Arduino, you can refer to First Use.
You need remove Bluetooth Module Module when you upload code.
Next turn off the power. And connect control board to computer with a USB cable. Upload code in the folder:
Sketches\01.1.1_RunMotor_Left_Wheel
Then disconnect USB cable and put your car in a place with enough space to move. Or make the car’s head
stand up and observe the wheel. The following code also requires this step.
Turn on the power of Car. Then the left motors and wheels of car will rotate forth and back. And you can
www.freenove.com
40 Chapter 1 Control Basic Components [email protected]
see the speeds are different. You can turn off the power of the car to stop that.
From previous section, we have known that M1 and M2 are connected in parallel andM3 and M4 are
connected in parallel. It means that you can only control motors in the same side together but not
separately. Usually, motors of the same side don’t need to rotate in different directions.
#define A B, it means A is B. Use A instead of B for easy maintenance and easy reading.
You can also define pins with int type, like int PIN_DIRECTION_RIGHT=3; But this need more RAM space.
Usually, there are two basic main functions for Arduino code, void setup() and void loop().
void setup(){ }
The setup() function is called when a sketch starts, which is used to initialize variables, pin modes, start
using libraries, etc.
The setup() function will only run once, after each power up or reset of the Arduino board.
void loop(){ }
This function will loop consecutively. Code in this function will be executed again and again…
Note, as to analogWrite(pin, value) of motors for this car, the maximum value is 255.As the motor requires a
certain voltage to run, and analogwirte (pin, 1) doesn’t meet such required voltage., according to different
voltage, the value that makes the car run will be much greater than analogwirte (pin, 1).
01.1.2_RunMotor_Right_Wheel
You need remove Bluetooth Module Module when you upload code.
Upload code in folder: Sketches\01.1.2_RunMotor_Right_Wheel.
Then put your car in a place with enough space to move. Turn ON the power of car. Then the right motors
and wheels of car will rotate forth and back. And you can see that the speeds are different.
Because the left motors and right motors are mirrored. When the motors rotate with same direction, the car
will react with reversed direction.
The code is below:
www.freenove.com
42 Chapter 1 Control Basic Components [email protected]
1 #define PIN_DIRECTION_RIGHT 3
2 #define PIN_DIRECTION_LEFT 4
3 #define PIN_MOTOR_PWM_RIGHT 5
4 #define PIN_MOTOR_PWM_LEFT 6
5
6 void setup() {
7 pinMode(PIN_DIRECTION_LEFT, OUTPUT);
8 pinMode(PIN_MOTOR_PWM_LEFT, OUTPUT);
9 pinMode(PIN_DIRECTION_RIGHT, OUTPUT);
10 pinMode(PIN_MOTOR_PWM_RIGHT, OUTPUT);
11 }
12
13 void loop() {
14 //Right motors rotate to one direction
15 digitalWrite(PIN_DIRECTION_RIGHT, HIGH);
16 analogWrite(PIN_MOTOR_PWM_RIGHT, 100);
17 delay(1000);
18 analogWrite(PIN_MOTOR_PWM_RIGHT, 0);
19 delay(1000);
20
21 //Right motors rotate to opposite direction
22 digitalWrite(PIN_DIRECTION_RIGHT, LOW);
23 analogWrite(PIN_MOTOR_PWM_RIGHT, 255);
24 delay(1000);
25 analogWrite(PIN_MOTOR_PWM_RIGHT, 0);
26 delay(1000);
27 }
28
01.1.3_Car_Move_and_Turn
You need remove Bluetooth Module Module when you upload code.
Upload code in folder: Sketches\01.1.3_Car_Move_and_Turn.
Then put your car in a place with enough space to move. Turn ON the power of car. Then the car will move
forth and back, then turn left and turn right. After stopping for 2 second, it repeat the actions.
The code is below:
1 #define PIN_DIRECTION_RIGHT 3
2 #define PIN_DIRECTION_LEFT 4
3 #define PIN_MOTOR_PWM_RIGHT 5
4 #define PIN_MOTOR_PWM_LEFT 6
5
6 void setup() {
7 pinMode(PIN_DIRECTION_LEFT, OUTPUT);
8 pinMode(PIN_MOTOR_PWM_LEFT, OUTPUT);
9 pinMode(PIN_DIRECTION_RIGHT, OUTPUT);
www.freenove.com
[email protected] Chapter 1 Control Basic Components 43
10 pinMode(PIN_MOTOR_PWM_RIGHT, OUTPUT);
11 }
12
13 void loop() {
14 //Move forward
15 motorRun(200, 200);
16 delay(1000);
17
18 //Move back
19 motorRun(-200, -200);
20 delay(1000);
21
22 //Turn left
23 motorRun(-200, 200);
24 delay(1000);
25
26 //Turn right
27 motorRun(200, -200);
28 delay(1000);
29
30 //Stop
31 motorRun(0, 0);
32 delay(2000);
33 }
34
35 void motorRun(int speedl, int speedr) {
36 int dirL = 0, dirR = 0;
37 if (speedl > 0) {
38 dirL = 0;
39 }
40 else {
41 dirL = 1;
42 speedl = -speedl;
43 }
44 if (speedr > 0) {
45 dirR = 1;
46 }
47 else {
48 dirR = 0;
49 speedr = -speedr;
50 }
51 digitalWrite(PIN_DIRECTION_LEFT, dirL);
52 digitalWrite(PIN_DIRECTION_RIGHT, dirR);
53 analogWrite(PIN_MOTOR_PWM_LEFT, speedl);
www.freenove.com
44 Chapter 1 Control Basic Components [email protected]
54 analogWrite(PIN_MOTOR_PWM_RIGHT, speedr);
55 }
56
www.freenove.com
[email protected] Chapter 1 Control Basic Components 45
A buzzer is an audio component. There are both active and passive types of buzzers. Active buzzers have
oscillator inside, these will sound as long as power is supplied. Passive buzzers require an external oscillator
signal (generally using PWM with different frequencies) to make a sound.
Active buzzers are easier to use. Generally, they can only make a specific sound frequency.
Passive buzzers require an external circuit to make sounds, but they can be controlled to make sounds of
various frequencies. The resonant frequency of the passive buzzer is 2kHz, which means the passive buzzer is
the loudest when resonant frequency is 2kHz.
In this car, the buzzer is an active buzzer. So it can only make a specific frequency of sound. Function tone()
of Arduino cannot be used for this kind of buzzer.
Since the control board has limited number of IOs. Buzzer and battery level are not used frequently. So we
use one IO of control board controlling buzzer and detecting battery level in different time
The schematic of buzzer and battery is below:
www.freenove.com
46 Chapter 1 Control Basic Components [email protected]
Serial Communication
Serial communication uses one data cable to transfer data one bit by another in turn. Parallel communication
means that the data is transmitted simultaneously on multiple cables. Serial communication takes only a few
cables to exchange information between systems, which is especially suitable for computers to computers,
long distance communication between computers and peripherals. Parallel communication is faster, but it
requires more cables and higher cost, so it is not appropriate for long distance communication.
Parallel communication Serial communication
Serial communication generally refers to the Universal Asynchronous Receiver/Transmitter (UART), which is
commonly used in electronic circuit communication. It has two communication lines, one is responsible for
sending data (TX line) and the other for receiving data (RX line). The serial communication connections of two
devices use is as follows:
Device 1(Your computer) Device 2(control board)
RX RX
TX Usb cable TX
For serial communication, the baud rate in both sides must be the same. The baud rates commonly used
are 9600 and 115200.
Computer identifies serial devices connected to your computer as COMx. We can use the Serial Monitor
window of Arduino Software to communicate with Freenove control board.
Code
01.2.1_Buzzer
You need remove Bluetooth Module Module when you upload code.
Upload code in Sketches\01.2.1_Buzzer. Then turn the switch of car.
You will hear b-bbbb----bbbb----bbbb---- ……
The code in setup() is only executed once. Code in loop() will be executed circularly.
1 #define PIN_BATTERY A0
2 #define PIN_BUZZER A0
3
4 void setup() {
5 pinMode(PIN_BUZZER, OUTPUT);
6 digitalWrite(PIN_BUZZER, HIGH);
7 delay(100);
8 digitalWrite(PIN_BUZZER, LOW);
9 }
10
11 void loop() {
www.freenove.com
[email protected] Chapter 1 Control Basic Components 47
01.2.2_Battery_level
Upload code in Sketches\01.2.2_Battery_level. Don’t disconnect the USB cable. Then turn on the switch of the
car.
And then click the Serial Monitor icon to open the Serial Monitor window.
Then you will hear buzzer making sounds twice. And then see the Interface of Serial Monitor window as
follows. If you can't open it, make sure Freenove control board had been connected to the computer, and
choose the right serial port in the menu bar "Tools-Port".
www.freenove.com
48 Chapter 1 Control Basic Components [email protected]
Title bar
Data-
sending
button
Data-
sending
area
31 Serial.print(batteryVoltage);
32 Serial.println(" V");
33 }
34 else {
35 Serial.print("Port busy! Please turn off buzzer before reading battery voltage.");
36 }
37 delay(1000);
38 }
39
40 bool getBatteryVoltage() {
41 pinMode(PIN_BATTERY, INPUT);
42 int batteryADC = analogRead(PIN_BATTERY);
43 if (batteryADC < 614) // 614/1023* 5=3V, reasonable Voltage:<2.1V
44 {
45 batteryVoltage = batteryADC / 1023.0 * 5.0 * 4;
46 return true;
47 } else {
48 return false;
49 }
50 }
In this code, different Data Types are mentioned: float, bool, void.
If you are not familiar with data types, please refer to https://www.arduino.cc/reference/
www.freenove.com
50 Chapter 1 Control Basic Components [email protected]
Code is always executed line by line. When if (getBatteryVoltage()) is executed, the program will turn to
execute bool getBatteryVoltage(){ }. After return, the program will execute code in if { }.
Serial.print()
Syntax is below:
Serial.print(val)
Serial.print(val, format)
Serial: serial port object. See the list of available serial ports for each board on the Serial main page.
val: the value to print. Allowed data types: any data type.
The only difference is that Serial.pritnln() will send a “\n”. content of next print() or println() will be shown in
a new line.
analogRead( pin)
It will map input voltages between 0 and the operating voltage(5V or 3.3V) into integer values between 0
and 1023. For 5v as an example, ADCvalue= analogRead( pin)
If you want to get the voltage value. It should be V=ADCvalue/1023*5V.
www.freenove.com
[email protected] Chapter 1 Control Basic Components 51
1.3 RGB
A RGB LED has 3 LEDs integrated into one LED component. It can respectively emit Red, Green and Blue light.
In order to do this, it requires 4 pins (this is also how you identify it). The long pin (1) is the common which is
the Cathode (+) or positive lead, the other 3 are the Anodes (-) or negative leads. A rendering of a RGB LED
and its electronic symbol are shown below. We can make RGB LED emit various colors of light and brightness
by controlling the 3 Anodes (2, 3 & 4) of the RGB LED
Red, Green, and Blue light are called 3 Primary Colors when discussing light (Note: for pigments such as paints,
the 3 Primary Colors are Red, Blue and Yellow). When you combine these three Primary Colors of light with
varied brightness, they can produce almost any color of visible light. Computer screens, single pixels of cell
phone screens, neon lamps, etc. can all produce millions of colors due to this phenomenon.
Red
Magenta Yellow
White
We know from previous section that, control board controls LEDs to emit a total of 256(0-255) different
brightness with PWM. So, through the combination of three different colors of LEDs, RGB LED can emit
256^3=16777216 Colors, 16Million colors.
www.freenove.com
52 Chapter 1 Control Basic Components [email protected]
Include Library
Click
Code
01.3_Led_Strip
You need remove Bluetooth Module Module when you upload code.
Upload code in Sketches\01.3_Led_Strip. Then turn the power of car.
You can find a proper view to observe LED colors on the bottom acrylic board.
www.freenove.com
[email protected] Chapter 1 Control Basic Components 53
You will see that all LEDs show red, green, blue, yellow in turn. Then all LEDs turn off.
Then first 5 LEDs show different colors one by one. Then all LEDs show the same color and the color changes
smoothly. Then different LEDs show different colors and they change smoothly.
The code is below:
1 #include "Freenove_WS2812B_RGBLED_Controller.h"
2
3 #define I2C_ADDRESS 0x20
4 #define LEDS_COUNT 10 //it defines number of LEDs
5
6 Freenove_WS2812B_Controller strip(I2C_ADDRESS, LEDS_COUNT, TYPE_GRB); //initialization
7
8 void setup() {
9 while (!strip.begin()); //judge if initialization success
10
11 strip.setAllLedsColor(0xFF0000); //Set all LED color to red
12 delay(2000);
13 strip.setAllLedsColor(0x00FF00); //set all LED color to green
14 delay(2000);
15 strip.setAllLedsColor(0x0000FF); //set all LED color to blue
16 delay(2000);
17 strip.setAllLedsColor(255, 255, 0); //set all LED color to yellow. This is just different
18 form of rgb value.
19 delay(2000);
20 strip.setAllLedsColor(0, 0, 0); //set all LED off.
21 delay(2000);
22
23 strip.setLedColor(0, 255, 0, 0); //set the N0.0 LED to red
24 delay(1000);
25 strip.setLedColor(1, 0, 255, 0); //set the N0.1 LED to green
26 delay(1000);
27 strip.setLedColor(2, 0, 0, 255); //set the N0.2 LED to blue
28 delay(1000);
29 strip.setLedColor(3, 255, 255, 0); //set the N0.3 LED to yellow
30 delay(1000);
31 strip.setLedColor(4, 255, 0, 255); //set the N0.4 LED to purple
32 delay(1000);
33 }
34
www.freenove.com
54 Chapter 1 Control Basic Components [email protected]
35 void loop() {
36 for (int k = 0; k < 255; k = k + 2) {
37 strip.setAllLedsColorData(strip.Wheel(k)); // set color data for all LED
38 strip.show(); // show the color set before
39 delay(50);
40 }
41 delay(3000);
42
43 for (int j = 0; j < 255; j += 2) {
44 for (int i = 0; i < LEDS_COUNT; i++) {
45 strip.setLedColorData(i, strip.Wheel(i * 256 / LEDS_COUNT + j)); //set color data for
46 LED one by one
47 }
48 strip.show(); // show the color set
49 delay(50);
50 }
51 }
First, you need install and include the library.
#include "Freenove_WS2812B_RGBLED_Controller.h"
Then set number of LED. The maximum is 255. But it is limited by power supply.
#define LEDS_COUNT 10 //it defines number of LEDs
There are two ways to set LED color.
A, set LED color directly.
1) set all LED colors
strip.setAllLedsColor( rgb value)
rgb value should be Hexadecimal value, like strip.setAllLedsColor(0x0000FF) .
strip.setAllLedsColor( rvalue, gvalue, bvalue)
This is another form, Like strip.setAllLedsColor(255, 255, 0).
You can find more rgb values and colors here https://www.rapidtables.com/web/color/RGB_Color.html
2) set color for one LED
strip.setLedColor( LED_Index, rgb_value) or strip.setLedColor(LED_Index, rvalue, gvalue, bvalue)
LED No. starts from 0, like strip.setLedColor(0, 255, 0, 0).
www.freenove.com
56 Chapter 1 Control Basic Components [email protected]
Code
01.4.1_Integrate_Functions
You need remove Bluetooth Module Module first when you upload code.
Upload code in Sketches\01.4.1_Integrate_Functions. Don't separate the files in the folder.
Then put your car in a place with enough space to move. Turn ON the power of car.
1 #include "Freenove_WS2812B_RGBLED_Controller.h"
2
3 #define I2C_ADDRESS 0x20 //define I2C address of LEDs
4 #define LEDS_COUNT 10 //it defines number of LEDs
5 //define motor pins
6 #define PIN_DIRECTION_LEFT 4
7 #define PIN_DIRECTION_RIGHT 3
8 #define PIN_MOTOR_PWM_LEFT 6
9 #define PIN_MOTOR_PWM_RIGHT 5
10
11 #define PIN_BATTERY A0
12 #define PIN_BUZZER A0
13 #define MOTOR_PWM_DEAD 10
14 float batteryVoltage = 0;
15 bool isBuzzered = false;
16
17 Freenove_WS2812B_Controller strip(I2C_ADDRESS, LEDS_COUNT, TYPE_GRB); //initialization
18
19 void setup() {
20 while (!strip.begin()); //judge if initialization successes
21
22 Serial.begin(9600); //set baud rate
23 pinsSetup(); //set pin mode (output or input )
24
25 strip.setAllLedsColor(0x00FF00); //set all LED color to green
26 motorRun(100, 100); //Car move forward
27 alarm(4, 1); //4 beat, 1 repeat
28 resetCarAction(); //Stop the car and turn off the buzzer
29
30 strip.setAllLedsColor(0xFF0000); //Set all LED color to red
31 motorRun(-100, -100); //Car move back
32 setBuzzer(true); //turn on buzzer
www.freenove.com
[email protected] Chapter 1 Control Basic Components 57
33 delay(1000);
34 resetCarAction(); //Stop the car and turn off the buzzer
35 }
36
37 void loop() {
38 if (getBatteryVoltage() == true) {
39 Serial.print("voltage: ");
40 Serial.println(batteryVoltage);
41 }
42
43 int r = random(0, 255); //a random value between 0~255
44 int g = random(0, 255); //a random value between 0~255
45 int b = random(0, 255); //a random value between 0~255
46 strip.setAllLedsColor(r, g, b); //Set all LED color with current r, g, b value
47 delay(1000);
48 }
49
50 void pinsSetup() {
51 pinMode(PIN_DIRECTION_LEFT, OUTPUT);
52 pinMode(PIN_MOTOR_PWM_LEFT, OUTPUT);
53 pinMode(PIN_DIRECTION_RIGHT, OUTPUT);
54 pinMode(PIN_MOTOR_PWM_RIGHT, OUTPUT);
55 setBuzzer(false); //Turn off the Buzzer
56 }
57
58 void motorRun(int speedl, int speedr) {
59 int dirL = 0, dirR = 0;
60 if (speedl > 0) {
61 dirL = 0;
62 }
63 else {
64 dirL = 1;
65 speedl = -speedl;
66 }
67
68 if (speedr > 0) {
69 dirR = 1;
70 }
71 else {
72 dirR = 0;
73 speedr = -speedr;
74 }
75
76 speedl = constrain(speedl, 0, 255);
www.freenove.com
58 Chapter 1 Control Basic Components [email protected]
121
122 void resetCarAction() {
123 motorRun(0, 0);
124 setBuzzer(false);
125 }
01.4.2_Library_Integrate_Functions
Upload code in sketches\01.4.2_Library_Integrate_Functions, which has the same function with code
01.4.1_Integrate_Functions. The only difference is that we write some codes into library. We will use this
library later.
If libraries don’t work on your computer, it may be related to your computer system.
Don’t worry. We also provide one code for later projects.
The main code is as below. The Freenove_4WD_Car_for_Arduino.h has defined some pins, variables and
functions. We can use them directly. We do not need redefine them again.
1 #include "Freenove_4WD_Car_for_Arduino.h"
2 #include "Freenove_WS2812B_RGBLED_Controller.h"
3
4 #define I2C_ADDRESS 0x20 //define I2C address of LEDs
5 #define LEDS_COUNT 10 //it defines number of LEDs
6 Freenove_WS2812B_Controller strip(I2C_ADDRESS, LEDS_COUNT, TYPE_GRB); //initialization
7
8 void setup() {
9 while (!strip.begin()); //judge if initialization successes
10 Serial.begin(9600); //set baud rate
11 pinsSetup(); //set pin mode (output or input )
12
13 strip.setAllLedsColor(0x00FF00); //set all LED color to green
14 motorRun(100, 100); //Car move forward
15 alarm(4, 1); //4 beat, 1 repeat
www.freenove.com
60 Chapter 1 Control Basic Components [email protected]
Open the directory Sketches\01.4.2_Library_Integrate_Functions. You will see .cpp and .h file. They are
library files.
When use the library in new code, you just need put this two files into the same directory of your code.
This library will be used latter, which will make programing more efficient.
Now we will introduce content in the library.
www.freenove.com
62 Chapter 1 Control Basic Components [email protected]
if (speedr > 0) {
dirR = 1;
}
else {
dirR = 0;
speedr = -speedr;
}
speedl = constrain(speedl, 0, 255); // speedl absolute value should be within 0~255
speedr = constrain(speedr, 0, 255); // speedr absolute value should be within 0~255
www.freenove.com
[email protected] Chapter 1 Control Basic Components 63
digitalWrite(PIN_DIRECTION_LEFT, dirL);
digitalWrite(PIN_DIRECTION_RIGHT, dirR);
analogWrite(PIN_MOTOR_PWM_LEFT, speedl);
analogWrite(PIN_MOTOR_PWM_RIGHT, speedr);
}
bool getBatteryVoltage() {
if (!isBuzzered) {
pinMode(PIN_BATTERY, INPUT);
int batteryADC = analogRead(PIN_BATTERY);
if (batteryADC < 614) // 3V/12V ,Voltage read: <2.1V/8.4V
{
batteryVoltage = batteryADC / 1023.0 * 5.0 * 4;
return true;
}
}
return false;
}
void setBuzzer(bool flag) {
isBuzzered = flag;
pinMode(PIN_BUZZER, flag);
digitalWrite(PIN_BUZZER, flag);
}
void alarm(u8 beat, u8 repeat) {
beat = constrain(beat, 1, 9);
repeat = constrain(repeat, 1, 255);
for (int j = 0; j < repeat; j++) {
for (int i = 0; i < beat; i++) {
setBuzzer(true);
delay(100);
setBuzzer(false);
delay(100);
}
delay(500);
}
}
void resetCarAction() {
motorRun(0, 0);
setBuzzer(false);
}
www.freenove.com
64 Chapter 1 Control Basic Components [email protected]
www.freenove.com
[email protected] Chapter 2 Obstacle avoidance 65
2.1 Servo
Servo is a compact package which consists of a DC Motor, a set of reduction gears to provide torque, a sensor
and control circuit board. Most Servos only have a 180-degree range of motion via their “horn”. Servos can
output higher torque than a simple DC Motor alone and they are widely used to control motion in model cars,
model airplanes, robots, etc. Servos have three wire leads which usually terminate to a male or female 3-pin
plug. Two leads are for electric power: Positive (2-VCC, Red wire), Negative (3-GND, Brown wire), and the
signal line (1-Signal, Orange wire) as represented in the Servo provided in your Kit.
We will use a 50Hz PWM signal with a duty cycle in a certain range to drive the servo. The lasting time 0.5ms-
2.5ms of PWM single cycle high level corresponds to the servo angle 0 degrees - 180 degrees linearly. Part
of the corresponding values are as follows:
High level time Servo angle
0.5ms 0 degree
1ms 45 degree
1.5ms 90 degree
2ms 135 degree
2.5ms 180 degree
When you change the servo signal, the servo will rotate to the designated position.
Code
02.1_Servo
You need remove Bluetooth Module Module first when you upload code.
Upload code in Sketches\02.1_Servo. Then turn on the power of car.
Then you will see servo sweep among 45°, 90° and 135°.
The code is below:
1 #include "Servo.h" //servo library
www.freenove.com
66 Chapter 2 Obstacle avoidance [email protected]
2
3 #define PIN_SERVO 2 //define servo pin
4
5 Servo; //create servo object to control a servo
6 char servoOffset = 0; // change the value to Calibrate servo
7
8 void setup() {
9 servo.attach(PIN_SERVO); //initialize servo
10 servo.write(90 + servoOffset); //Calibrate servo
11 }
12
13 void loop() {
14 servo.write(45); //make servo rotate to 45°
15 delay(1000); //delay 1000ms
16
17 servo.write(90); //make servo rotate to 90°
18 delay(1000);
19
20 servo.write(135); //make servo rotate to 135°
21 delay(1000);
22
23 servo.write(90); //make servo rotate to 90°
24 delay(1000);
25 }
26
Servo library
There are some functions of this library:
servo.attach(pin)
Attach the Servo variable to a pin.
pin: servo pin it is an initialization step to control a servo.
servo.write(angle)
Writes a value to the servo, controlling the shaft accordingly.
angle: the value to write to the servo, from 0 to 180
www.freenove.com
[email protected] Chapter 2 Obstacle avoidance 67
The Ultrasonic Ranging Module uses the principle that ultrasonic waves will reflect when they encounter any
obstacles. This is possible by counting the time interval between when the ultrasonic wave is transmitted to
when the ultrasonic wave reflects back after encountering an obstacle. Time interval counting will end after
an ultrasonic wave is received, and the time difference (delta) is the total time of the ultrasonic wave’s journey
from being transmitted to being received. Because the speed of sound in air is a constant, and is about
v=340m/s, we can calculate the distance between the Ultrasonic Ranging Module and the obstacle: s=vt/2.
2S=V·t.
The HC-SR04 Ultrasonic Ranging Module integrates a both an ultrasonic transmitter and a receiver. The
transmitter is used to convert electrical signals (electrical energy) into high frequency (beyond human hearing)
sound waves (mechanical energy) and the function of the receiver is opposite of this. The picture and the
diagram of the HC SR04 Ultrasonic Ranging Module are shown below:
Pin description:
Pin name Pin number Description
Vcc 1 Positive electrode of power supply, the voltage is 5V
Trig 2 Triger pin
Echo 3 Echo pin
Gnd 4 Negative electrode of power supply
www.freenove.com
68 Chapter 2 Obstacle avoidance [email protected]
Code
02.2_Ultrasonic_Ranging
This project is used to set servo different angles and detect obstacle distance at each angle.
You need remove Bluetooth Module Module first when you upload code.
Upload code in Sketches\02.2_Ultrasonic_Ranging.
Then turn on the power of car. Then open the serial monitor.
Then you will see servo sweep among 45°, 90°, 135°. And ultrasonic module detects different distance at
different angles. All the distance values are printed below:
www.freenove.com
[email protected] Chapter 2 Obstacle avoidance 69
www.freenove.com
70 Chapter 2 Obstacle avoidance [email protected]
24 servo.write(45);
25 delay(1000);
26 distance[0] = getSonar(); //get ultrasonic value and save it into distance[0]
27
28 servo.write(90);
29 delay(1000);
30 distance[1] = getSonar();
31
32 servo.write(135);
33 delay(1000);
34 distance[2] = getSonar();
35
36 servo.write(90);
37 delay(1000);
38 distance[3] = getSonar();
39
40 Serial.print("Distance L / M / R / M2: "); //Left/Middle/Right/Middle2
41 for (int i = 0; i < 4; i++) {
42 Serial.print(distance[i]); //print ultrasonic in 45°, 90°, 135°, 90°
43 Serial.print("/");
44 }
45 Serial.print('\n'); //next content will be printed in new line
46 }
47
48 float getSonar() {
49 unsigned long pingTime;
50 float distance;
51 digitalWrite(PIN_SONIC_TRIG, HIGH); // make trigPin output high level lasting for 10μs to
52 triger HC_SR04,
53 delayMicroseconds(10);
54 digitalWrite(PIN_SONIC_TRIG, LOW);
55 pingTime = pulseIn(PIN_SONIC_ECHO, HIGH, SONIC_TIMEOUT); // Wait HC-SR04 returning to the
56 high level and measure out this waiting time
57 if (pingTime != 0)
58 distance = (float)pingTime * SOUND_VELOCITY / 2 / 10000; // calculate the distance
59 according to the time
60 else
61 distance = MAX_DISTANCE;
62 return distance; // return the distance value
63 }
www.freenove.com
72 Chapter 2 Obstacle avoidance [email protected]
Code
02.3.1_Automatic_Obstacle_Avoidance
You need remove Bluetooth Module Module first when you upload code.
Upload code in Sketches\02.3.1_Automatic_Obstacle_Avoidance.
Then disconnect USB cable. Turn on the power of car. And put the car in a place with enough space to move.
The code is below:
1 #include <Servo.h>
2 #define PIN_SERVO 2
3
4 #define PIN_DIRECTION_LEFT 4
5 #define PIN_DIRECTION_RIGHT 3
6 #define PIN_MOTOR_PWM_LEFT 6
7 #define PIN_MOTOR_PWM_RIGHT 5
8
9 #define PIN_SONIC_TRIG 7
10 #define PIN_SONIC_ECHO 8
11
12 #define PIN_BATTERY A0
13
14 #define OBSTACLE_DISTANCE 40
15 #define OBSTACLE_DISTANCE_LOW 15
16
17 #define MAX_DISTANCE 300 //cm
18 #define SONIC_TIMEOUT (MAX_DISTANCE*60)
19 #define SOUND_VELOCITY 340 //soundVelocity: 340m/s
20
21 Servo servo;
22 char servoOffset = 0;
23 int speedOffset;//batteryVoltageCompensationToSpeed
24
25 void setup() {
26 pinMode(PIN_DIRECTION_LEFT, OUTPUT);
27 pinMode(PIN_MOTOR_PWM_LEFT, OUTPUT);
28 pinMode(PIN_DIRECTION_RIGHT, OUTPUT);
29 pinMode(PIN_MOTOR_PWM_RIGHT, OUTPUT);
30
31 pinMode(PIN_SONIC_TRIG, OUTPUT);// set trigPin to output mode
32 pinMode(PIN_SONIC_ECHO, INPUT); // set echoPin to input mode
33 servo.attach(PIN_SERVO);
www.freenove.com
[email protected] Chapter 2 Obstacle avoidance 73
34 calculateVoltageCompensation();
35 }
36
37 void loop() {
38 updateAutomaticObstacleAvoidance();
39 }
40
41 void updateAutomaticObstacleAvoidance() {
42 int distance[3], tempDistance[3][5], sumDisntance;
43 static u8 leftToRight = 0, servoAngle = 0, lastServoAngle = 0; //
44 const u8 scanAngle[2][3] = { {150, 90, 30}, {30, 90, 150} };
45
46 for (int i = 0; i < 3; i++)
47 {
48 servoAngle = scanAngle[leftToRight][i];
49 servo.write(servoAngle);
50 if (lastServoAngle != servoAngle) {
51 delay(130);
52 }
53 lastServoAngle = servoAngle;
54 for (int j = 0; j < 5; j++) {
55 tempDistance[i][j] = getSonar();
56 delayMicroseconds(2 * SONIC_TIMEOUT);
57 sumDisntance += tempDistance[i][j];
58 }
59 if (leftToRight == 0) {
60 distance[i] = sumDisntance / 5;
61 }
62 else {
63 distance[2 - i] = sumDisntance / 5;
64 }
65 sumDisntance = 0;
66 }
67 leftToRight = (leftToRight + 1) % 2;
68
69 if (distance[1] < OBSTACLE_DISTANCE) { //Too little distance ahead
70 if (distance[0] > distance[2] && distance[0] > OBSTACLE_DISTANCE) { //Left distance is
71 greater than right distance
72 motorRun(-(150 + speedOffset), -(150 + speedOffset)); //Move back
73 delay(100);
74 motorRun(-(150 + speedOffset), (150 + speedOffset));
75 }
76 else if (distance[0] < distance[2] && distance[2] > OBSTACLE_DISTANCE)
77 { //Right distance is greater than left distance
www.freenove.com
74 Chapter 2 Obstacle avoidance [email protected]
We use analogWrite(PIN_MOTOR, PWM value) to make motor work. The PWM value represents different
speeds when the voltage of battery changes. So we set a speedOffset to compensate the difference.
1 void calculateVoltageCompensation() {
2 float voltageOffset = 8.4 - getBatteryVoltage();
3 speedOffset = voltageOffset * 20;
4 }
20 is tested value. You can try to test what is the most proper value.
www.freenove.com
76 Chapter 2 Obstacle avoidance [email protected]
Then make the car react according to the distances above. About its logic, please refer to flow chart.
1 //make the car react according to the distances
2 if (distance[1] < OBSTACLE_DISTANCE) { //obstacle in front
3 if (distance[0] > distance[2] && distance[0] > OBSTACLE_DISTANCE) { //Left distance is
4 greater than right distance
5 motorRun(-(150 + speedOffset), -(150 + speedOffset)); //Move back a little
6 delay(100);
7 motorRun(-(150 + speedOffset), (150 + speedOffset));
8 delay(50);
9 }
10 else if (distance[0] < distance[2] && distance[2] > OBSTACLE_DISTANCE)
11 { //Right distance is greater than left distance
12 motorRun(-(150 + speedOffset), -(150 + speedOffset)); //Move back a little
13 delay(100);
14 motorRun((150 + speedOffset), -(150 + speedOffset)); //Turn right
www.freenove.com
[email protected] Chapter 2 Obstacle avoidance 77
15 delay(50);
16 }
17 else { //Get into the dead corner, move back a little, then spin.
18 motorRun(-(150 + speedOffset), -(150 + speedOffset)); //Move back
19 delay(100);
20 motorRun(-(150 + speedOffset), (150 + speedOffset)); //Turn left
21 delay(50);
22 }
23 }
24 else { //No obstacles ahead
25 if (distance[0] < OBSTACLE_DISTANCE_LOW) { //Obstacles on the left front.
26 motorRun(-(150 + speedOffset), -(150 + speedOffset)); //Move back
27 delay(100);
28 motorRun((180 + speedOffset), (50 + speedOffset)); //Turn right with large radius
29 delay(50);
30 }
31 else if (distance[2] < OBSTACLE_DISTANCE_LOW) { //Obstacles on the right front.
32 motorRun(-(150 + speedOffset), -(150 + speedOffset)); //Move back
33 delay(100);
34 motorRun((50 + speedOffset), (180 + speedOffset)); //Turn left with large radius
35 delay(50);
36 }
37 else { //Cruising, no obstacle closed
38 motorRun((80 + speedOffset), (80 + speedOffset));
39 }
40 }
41 }
42
www.freenove.com
78 Chapter 2 Obstacle avoidance [email protected]
www.freenove.com
[email protected] Chapter 2 Obstacle avoidance 79
02.3.2_Liberary_Automatic_Obstacle_Avoidance
Code in sketches\02.3.2_Liberary_Automatic_Obstacle_Avoidance includes a library
The code function and content is similar to previous section. There are little difference. Previous code is
more simple.
www.freenove.com
80 Chapter 2 Obstacle avoidance [email protected]
12
13 #define OA_SERVO_CENTER (90)
14 #define OA_SCAN_ANGLE_INTERVAL 50
15 #define OA_SCAN_ANGLE_MIN (OA_SERVO_CENTER - OA_SCAN_ANGLE_INTERVAL)
16 #define OA_SCAN_ANGLE_MAX (OA_SERVO_CENTER + OA_SCAN_ANGLE_INTERVAL)
17 #define OA_WAITTING_SERVO_TIME 130
18
19 #define OA_CRUISE_SPEED (110 + oa_VoltageCompensationToSpeed)
20
21 #define OA_ROTATY_SPEED_LOW (120 + oa_VoltageCompensationToSpeed)
22 #define OA_ROTATY_SPEED_NORMAL (150 + oa_VoltageCompensationToSpeed)
23 #define OA_ROTATY_SPEED_HIGH (180 + oa_VoltageCompensationToSpeed)
24
25 #define OA_TURN_SPEED_LV4 (180 + oa_VoltageCompensationToSpeed)
26 #define OA_TURN_SPEED_LV1 (50 + oa_VoltageCompensationToSpeed )
27
28 #define OA_BACK_SPEED_LOW (110 + oa_VoltageCompensationToSpeed)
29 #define OA_BACK_SPEED_NORMAL (150 + oa_VoltageCompensationToSpeed)
30 #define OA_BACK_SPEED_HIGH (180 + oa_VoltageCompensationToSpeed)
31
32 #define OA_OBSTACLE_DISTANCE 40
33 #define OA_OBSTACLE_DISTANCE_LOW 15
34
35 #define OA_SPEED_OFFSET_PER_V 35
36
37 #define OA_SERVO_OFFSET_ADDR_IN_EEPROM 0
38
39 #define MAX_DISTANCE 300 //cm
40 #define SONIC_TIMEOUT (MAX_DISTANCE*60)
41 #define SOUND_VELOCITY 340 //soundVelocity: 340m/s
42
43
44 extern Servo servo;
45 extern int servoOffset;
46
47 void servoSetup(); //initialize the servo
48 void setServoOffset(int offset); //Set servo offset
49 void writeServo(u8 n); //set servo to an angle, offset has been considered
50 void writeServoOffsetToEEPROM();
51 void getServoOffsetFromEEPROM();
52
53 float getSonar();
54 void oa_CalculateVoltageCompensation(); // Calculate Voltage Compensation
55 void updateAutomaticObstacleAvoidance();
www.freenove.com
[email protected] Chapter 2 Obstacle avoidance 81
56 #endif
.h file used to define pins, variables and functions.
You can get information of what you can use from .h file.
www.freenove.com
82 Chapter 2 Obstacle avoidance [email protected]
84 lastServoAngle = servoAngle;
85 for (int j = 0; j < 5; j++) {
86 tempDistance[i][j] = getSonar();
87 delayMicroseconds(2 * SONIC_TIMEOUT);
88 sumDisntance += tempDistance[i][j];
89 }
90 distance[i] = sumDisntance / 5;
91 sumDisntance = 0;
92 }
93 cnt = 0;
94 }
95
96 if (distance[1] < OA_OBSTACLE_DISTANCE) { //Too little distance ahead
97 if (distance[0] > OA_OBSTACLE_DISTANCE || distance[2] > OA_OBSTACLE_DISTANCE) {
98 motorRun(-OA_BACK_SPEED_LOW, -OA_BACK_SPEED_LOW); //Move back a little
99 delay(100);
100 if (distance[0] > distance[2]) { //Left distance is greater than
101 right distance
102 motorRun(-OA_ROTATY_SPEED_LOW, OA_ROTATY_SPEED_LOW);
103 }
104 else { //Right distance is greater than
105 left distance
106 motorRun(OA_ROTATY_SPEED_LOW, -OA_ROTATY_SPEED_LOW);
107 }
108 }
109 else { //Get into the dead corner, move
110 back a little, then spin.
111 motorRun(-OA_BACK_SPEED_HIGH, -OA_BACK_SPEED_HIGH);
112 delay(100);
113 motorRun(-OA_ROTATY_SPEED_NORMAL, OA_ROTATY_SPEED_NORMAL);
114 }
115 }
116 // following code is different from last section. Last section is more simple
117 else { //No obstacles ahead
118 if (distance[0] < OA_OBSTACLE_DISTANCE) { //Obstacles on the left front.
119 if (distance[0] < OA_OBSTACLE_DISTANCE_LOW) { //Very close to the left front
120 obstacle.
121 motorRun(-OA_BACK_SPEED_LOW, -OA_BACK_SPEED_LOW); //Move back
122 delay(100);
123 }
124 motorRun(OA_TURN_SPEED_LV4, OA_TURN_SPEED_LV1);
125 }
126 else if (distance[2] < OA_OBSTACLE_DISTANCE) { //Obstacles on the right
127 front.
www.freenove.com
84 Chapter 2 Obstacle avoidance [email protected]
Since the servo may not be installed to 90°, we need adjust it. But we don’t want to adjust it every time, so
we can save the servoOffset in a place and next time, we can use it directly.. The microcontroller on the
Arduino and Genuino boards have 1024 bytes of EEPROM.
It is useful when we use remote control to calibrate the servo.
1 void writeServoOffsetToEEPROM() {
2 servo.write(90 + servoOffset);
3 EEPROM.write(OA_SERVO_OFFSET_ADDR_IN_EEPROM, servoOffset);
4 }
5
6 void getServoOffsetFromEEPROM() {
7 servoOffset = EEPROM.read(OA_SERVO_OFFSET_ADDR_IN_EEPROM);
8 servoOffset = constrain(servoOffset, -10, 10);
9 }
EEPROM
The microcontroller on the Arduino and Genuino boards have 1024 bytes of EEPROM.
EEPROM.write(address, val); write val to address
value = EEPROM.read(address); read the data saved in address
for example,
EEPROM.write(0, 3);
EEPROM.write(1, 5);
EEPROM.write(2, 8);
Value0= EEPROM.read(0); then Value0 = 3
Value1 = EEPROM.read(2); then Value2 = 8
For more information, refer to https://www.arduino.cc/en/Reference/EEPROM
www.freenove.com
[email protected] Chapter 3 Line tracking 85
There are three Reflective Optical Sensors on this car. When the infrared light emitted by infrared diode shines
on the surface of different objects, the sensor will receive light with different intensities after reflection.
As we know, black objects absorb light better. So when black lines are drawn on the white plane, the sensor
can detect the difference. The sensor can also be called Line Tracking Sensor.
Warning:
Reflective Optical Sensor (including Line Tracking Sensor) should be avoided using in environment with
infrared interference, like sunlight. Sunlight contains a lot of invisible light such as infrared and ultraviolet.
Under environment with intense sunlight, Reflective Optical Sensor cannot work normally.
The following table shows the values of all cases when three Tracking Sensors detect objects of different colors.
Among them, black objects or no objects were detected to represent 1, and white objects were detected to
represent 0.
Left Middle Right Value(binary) Value(decimal)
0 0 0 000 0
0 0 1 001 1
0 1 0 010 2
0 1 1 011 3
1 0 0 100 4
1 0 1 101 5
1 1 0 110 6
1 1 1 111 7
Code
03.1_Tracking_Sensor
You need remove Bluetooth Module Module first when you upload code.
Upload code in Sketches\03.1_Tracking_Sensor, turn on the power, and open the serial monitor. Put
something black under the sensor. Move it and you will see different LEDs light up.
www.freenove.com
86 Chapter 3 Line tracking [email protected]
14 void loop() {
15 sensorValue[0] = digitalRead(PIN_TRACKING_LEFT);
16 sensorValue[1] = digitalRead(PIN_TRACKING_CENTER);
17 sensorValue[2] = digitalRead(PIN_TRACKING_RIGHT);
18 sensorValue[3] = sensorValue[0] << 2 | sensorValue[1] << 1 | sensorValue[2];
19 Serial.print("Sensor Value (L / M / R / ALL) : ");
20 for (int i = 0; i < 4; i++) {
21 Serial.print(sensorValue[i]);
22 Serial.print('\t'); //means Tab
23 }
24 Serial.print('\n'); //means new line
25 delay(500);
26 }
27
Bitwise Operators
There are some Bitwise Operators.
<< (bitshift left)
If sensorValue[0] =1, sensorValue[1]= 1, sensorValue[2]=1
sensorValue[0] << 2 then sensorValue[0]=100,(Binary), namely 4(Decimal)
sensorValue[1] << 1 then sensorValue[0]=010,(Binary), namely 2(Decimal)
sensorValue[2]=001(Binary)
| (bitwise or)
The code turns to: 100 | 010 | 001 =111(Binary), namely 7(Decimal)
www.freenove.com
88 Chapter 3 Line tracking [email protected]
The car will make different actions according to the value transmitted by the line-tracking sensor.
When
www.freenove.com
[email protected] Chapter 3 Line tracking 89
Code
03.2_Automatic_Tracking_Line
You need remove Bluetooth Module Module first when you upload code.
Upload code in Sketches\03.3_One_Code_Automatic_Tracking_Line. Turn on the power. Use a black tape
to build a line and then put your car on it as below.
www.freenove.com
90 Chapter 3 Line tracking [email protected]
23 switch (trackingSensorVal)
24 {
25 case 0: //000
26 motorRun(TK_FORWARD_SPEED, TK_FORWARD_SPEED); //car move forward
27 break;
28 case 7: //111
29 motorRun(TK_STOP_SPEED, TK_STOP_SPEED); //car stop
30 break;
31 case 1: //001
32 motorRun(TK_TURN_SPEED_LV4, TK_TURN_SPEED_LV1); //car turn
33 break;
34 case 3: //011
35 motorRun(TK_TURN_SPEED_LV3, TK_TURN_SPEED_LV2); //car turn right
36 break;
37 case 2: //010
38 case 5: //101
39 motorRun(TK_FORWARD_SPEED, TK_FORWARD_SPEED); //car move forward
40 break;
41 case 6: //110
42 motorRun(TK_TURN_SPEED_LV2, TK_TURN_SPEED_LV3); //car turn left
43 break;
44 case 4: //100
45 motorRun(TK_TURN_SPEED_LV1, TK_TURN_SPEED_LV4); //car turn right
46 break;
47 default:
48 break;
49 }
50 }
51
52 void tk_CalculateVoltageCompensation() {
53 getBatteryVoltage(); //from Freenove_4WD_Car_for_Arduino.h library
54 float voltageOffset = 7 - batteryVoltage;
55 tk_VoltageCompensationToSpeed = 30 * voltageOffset;
56 }
57
58 //when black line on one side is detected, the value of the side will be 0, or the value is 1
59 u8 getTrackingSensorVal() {
60 u8 trackingSensorVal = 0;
61 trackingSensorVal = (digitalRead(PIN_TRACKING_LEFT) == 1 ? 1 : 0) << 2 |
62 (digitalRead(PIN_TRACKING_CENTER) == 1 ? 1 : 0) << 1 | (digitalRead(PIN_TRACKING_RIGHT) == 1 ?
63 1 : 0) << 0;
64 return trackingSensorVal;
65 }
www.freenove.com
[email protected] Chapter 3 Line tracking 91
switch...case
switch (var) {
case 1:
//do something when var equals 1
break;
case 2:
//do something when var equals 2
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
For more information, please refer to:
https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/
www.freenove.com
92 Chapter 4 IR control [email protected]
Chapter 4 IR control
In this chapter, we will introduce infrared remote and receiver and make an IR remote control car.
If you have any concerns, please feel free to contact us via [email protected]
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 with
different encodings. Infrared remote control technology is widely used, such as TV, air conditioning, etc. Thus,
it makes it possible for you to switch TV programs and adjust the temperature of the air conditioning wheb
you are away from them. The remote control we use is shown below:
This infrared remote control uses NEC encoding with a signal period of 108ms.
Infrared Emitter
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.
www.freenove.com
[email protected] Chapter 4 IR control 93
Code
04.1_IR_Receiver
You need remove Bluetooth Module Module first when you upload code.
Then upload code in Sketches\04.1_IR_Receiver, turn on the power and open the serial monitor.
And then pull off the plastic piece closed to the battery, and press following keys in IR remote.
FF02FD
FFE01F FF906F
FFA857
FF9867
After receiving the signal from Infrared Emitter, the controller will recognize which key has been pressed. And
print it in the monitor as below
www.freenove.com
94 Chapter 4 IR control [email protected]
Abnormal code
When you press one key lasting for some time, FFFFFFFF will be shown. It indicates that the key is in pressing
state.
IR communication is not very stable, so it is easily to be interfered. When used, the transmitting LED of remote
control must be aimed at the receiver. Otherwise, it may result in no data being received or incorrect data
being received.
In addition, sometimes the code received is abnormal. Except key codes and FFFFFFFF, other codes received
are abnormal. When we process the code, we need skip this kind of data.
Different key code corresponds to different key.
1 #include <IRremote.h> // include IRremote library
2 #define PIN_IRREMOTE_RECV 9 // Infrared receiving pin
3 IRrecv irrecv(PIN_IRREMOTE_RECV); // Create a class object used to receive
4 decode_results results; // Create a decoding results class object
5
6 void setup()
7 {
8 Serial.begin(9600); // Initialize the serial port and set the baud rate to 9600
9 irrecv.enableIRIn(); // Start the receiver
10 }
11
12 void loop() {
13 if (irrecv.decode(&results)) { // Waiting for decoding
14 Serial.println(results.value, HEX); // Print out the decoded results
15 irrecv.resume(); // Receive the next value
16 }
17 delay(100);
18 }
www.freenove.com
[email protected] Chapter 4 IR control 95
Code
04.2_IR_Remote_Car
You need remove Bluetooth Module Module first when you upload code.
First, upload the code in Sketches\04.2_IR_Remote_Car, and turn on the power of car.
Key graph Key define Key code Function
IR_REMOTE_KEYCODE_UP 0xFF02FD move forward
www.freenove.com
96 Chapter 4 IR control [email protected]
Since the emission period of the infrared remote control is 108 ms, the signal timeout time is set to a rough
value of 120 ms. If the timeout is less than 108 ms, the data will be read ahead of time and cannot be read. It
will cause a misunderstanding that the signal is lost. If the timeout time is set too large, such as 1000ms, the
delay of car action will be more serious.
11 #define IR_UPDATE_TIMEOUT 120
……
54 if (millis() - lastIRUpdateTime > IR_UPDATE_TIMEOUT) {
55 if (!isStopFromIR) {
56 isStopFromIR = true;
57 motorRun(0, 0);
58 setBuzzer(false);
59 }
60 lastIRUpdateTime = millis();
61 }
……
You can change value of IR_CAR_SPEED to change speed of the car in range (0~255). In fact, since motor need
enough voltage to make the car move so the minimum value is not 0.
12 #define IR_CAR_SPEED 180
millis()
Returns the number of milliseconds passed since the Arduino board began running the current program
lastIRUpdateTime = millis(); //write down current time
}
else {
if (millis() – lastIRUpdateTime)
millis() – lastIRUpdateTime is the time from lastIRUpdateTime to current line.
www.freenove.com
98 Chapter 4 IR control [email protected]
In this project, we will add a LED bar function compared to the last section, so the infrared remote control car
will have more functions.
You need remove Bluetooth Module Module first when you upload code.
Open the code in Sketches\04.4_One_Code_Multifunctional_IR_Remote_Car. Upload it into car.
You can also choose to Sketches\04.3_Multifunctional_IR_Remote_Car
www.freenove.com
[email protected] Chapter 4 IR control 99
After the code is successfully uploaded, turn on the power of the car and use the infrared remote control to
control the car and other functions. The corresponding keys and their functions are shown in the following
table:
www.freenove.com
100 Chapter 4 IR control [email protected]
Code
You need remove Bluetooth Module Module first when you upload code.
This project has many labels.
“Freenove_IR_Remote_Keycode.h” is used to save key code of IR remote control.
Freenove_IR_Remote_Keycode.h
1 // Freenove_IR_Remote_Keycode.h
2 #ifndef _FREENOVE_IR_REMOTE_KEYCODE_h
3 #define _FREENOVE_IR_REMOTE_KEYCODE_h
4 #if defined(ARDUINO) && ARDUINO >= 100
5 #include "arduino.h"
6 #else
7 #include "WProgram.h"
8 #endif
9 #include <IRremote.h>
10
11 #define IR_REMOTE_KEYCODE_POWER 0xFFA25D
12 #define IR_REMOTE_KEYCODE_MENU 0xFF629D
13 #define IR_REMOTE_KEYCODE_MUTE 0xFFE21D
14
15 #define IR_REMOTE_KEYCODE_MODE 0xFF22DD
16 #define IR_REMOTE_KEYCODE_UP 0xFF02FD
17 #define IR_REMOTE_KEYCODE_BACK 0xFFC23D
18
19 #define IR_REMOTE_KEYCODE_LEFT 0xFFE01F
20 #define IR_REMOTE_KEYCODE_CENTER 0xFFA857
21 #define IR_REMOTE_KEYCODE_RIGHT 0xFF906F
22
23 #define IR_REMOTE_KEYCODE_0 0xFF6897
24 #define IR_REMOTE_KEYCODE_DOWN 0xFF9867
25 #define IR_REMOTE_KEYCODE_OK 0xFFB04F
26
27 #define IR_REMOTE_KEYCODE_1 0xFF30CF
28 #define IR_REMOTE_KEYCODE_2 0xFF18E7
29 #define IR_REMOTE_KEYCODE_3 0xFF7A85
30
31 #define IR_REMOTE_KEYCODE_4 0xFF10EF
32 #define IR_REMOTE_KEYCODE_5 0xFF38C7
33 #define IR_REMOTE_KEYCODE_6 0xFF5AA5
34
35 #define IR_REMOTE_KEYCODE_7 0xFF42BD
36 #define IR_REMOTE_KEYCODE_8 0xFF4AB5
37 #define IR_REMOTE_KEYCODE_9 0xFF52AD
www.freenove.com
[email protected] Chapter 4 IR control 101
38 #endif
04.3_ Multifunctional_IR_Remote_Car.ino
1 #include "Freenove_4WD_Car_for_Arduino.h"
2 #include "Freenove_IR_Remote_Keycode.h"
3 #include "Freenove_WS2812B_RGBLED_Controller.h"
4 ////////////////////////////////////////////
5 ////Definitions related to IR-remote
6 #define IR_UPDATE_TIMEOUT 110
7 #define IR_CAR_SPEED 180
8
9 IRrecv irrecv(PIN_IRREMOTE_RECV);
10 decode_results results;
11 u32 currentKeyCode, lastKeyCode;
12 bool isStopFromIR = false;
13 u32 lastIRUpdateTime = 0;
14 ////////////////////////////////////////////
15 ////Definitions related to Led-strip
16 #define STRIP_I2C_ADDRESS 0x20
17 #define STRIP_LEDS_COUNT 10
18
19 u8 colorPos = 0;
20 u8 colorStep = 50;
21 u8 stripDisplayMode = 1;
22 u8 currentLedIndex = 0;
23 u16 stripDisplayDelay = 100;
24 u32 lastStripUpdateTime = 0;
25 Freenove_WS2812B_Controller strip(STRIP_I2C_ADDRESS, STRIP_LEDS_COUNT, TYPE_GRB);
26 ///////////////////////////////////////////
27
28 void setup() {
29 strip.begin();
30 irrecv.enableIRIn(); // Start the receiver
31 }
32
33 void loop() {
34 if (irrecv.decode(&results)) {
35 isStopFromIR = false;
36 currentKeyCode = results.value;
37 if (currentKeyCode != 0xFFFFFFFF) {
38 lastKeyCode = currentKeyCode;
39 }
40 switch (lastKeyCode) {
41 case IR_REMOTE_KEYCODE_UP:
42 motorRun(IR_CAR_SPEED, IR_CAR_SPEED);
www.freenove.com
102 Chapter 4 IR control [email protected]
43 break;
44 case IR_REMOTE_KEYCODE_DOWN:
45 motorRun(-IR_CAR_SPEED, -IR_CAR_SPEED);
46 break;
47 case IR_REMOTE_KEYCODE_LEFT:
48 motorRun(-IR_CAR_SPEED, IR_CAR_SPEED);
49 break;
50 case IR_REMOTE_KEYCODE_RIGHT:
51 motorRun(IR_CAR_SPEED, -IR_CAR_SPEED);
52 break;
53 case IR_REMOTE_KEYCODE_CENTER:
54 setBuzzer(true);
55 break;
56 case IR_REMOTE_KEYCODE_0:
57 break;
58 case IR_REMOTE_KEYCODE_1:
59 stripDisplayMode = 1;
60 break;
61 case IR_REMOTE_KEYCODE_2:
62 colorStep += 5;
63 if (colorStep > 100)
64 {
65 colorStep = 100;
66 }
67 break;
68 case IR_REMOTE_KEYCODE_3:
69 colorStep -= 5;
70 if (colorStep < 5)
71 {
72 colorStep = 5;
73 }
74 break;
75 case IR_REMOTE_KEYCODE_4:
76 stripDisplayMode = 0;
77 break;
78 case IR_REMOTE_KEYCODE_5:
79 stripDisplayDelay -= 20;
80 if (stripDisplayDelay < 20)
81 {
82 stripDisplayDelay = 20;
83 }
84 break;
85 case IR_REMOTE_KEYCODE_6:
86 stripDisplayDelay += 20;
www.freenove.com
[email protected] Chapter 4 IR control 103
www.freenove.com
104 Chapter 4 IR control [email protected]
131 }
132 break;
133 default:
134 break;
135 }
136 }
Compared to the previous project, this code has more switch-case branches of the remote key code for
controlling the light bar.
1 ……
2 case IR_REMOTE_KEYCODE_1:
3 stripDisplayMode = 1;
4 break;
5 case IR_REMOTE_KEYCODE_2:
6 colorStep += 5;
7 if (colorStep > 100)
8 {
9 colorStep = 100;
10 }
11 break;
12 case IR_REMOTE_KEYCODE_3:
13 colorStep -= 5;
14 if (colorStep < 5)
15 {
16 colorStep = 5;
17 }
18 break;
19 case IR_REMOTE_KEYCODE_4:
20 stripDisplayMode = 0;
21 break;
22 case IR_REMOTE_KEYCODE_5:
23 stripDisplayDelay -= 20;
24 if (stripDisplayDelay < 20)
25 {
26 stripDisplayDelay = 20;
27 }
28 break;
29 case IR_REMOTE_KEYCODE_6:
30 stripDisplayDelay += 20;
31 if (stripDisplayDelay > 300)
32 {
33 stripDisplayDelay = 300;
34 }
break;
www.freenove.com
[email protected] Chapter 4 IR control 105
……
In the loop(), control the behavior of the light bar based on these variables above.
The variable stripDisplayMode is used to control the display mode of the LED.
The variable stripDisplayDelay is used to control the cycle time of the LED, that is, the speed of change.
The variable colorStep is used to control the color value change for each iteration.
1 switch (stripDisplayMode)
2 {
3 case 0:
4 if (millis() - lastStripUpdateTime > stripDisplayDelay)
5 {
6 for (int i = 0; i < STRIP_LEDS_COUNT; i++) {
7 strip.setLedColorData(i, strip.Wheel(colorPos + i * 25));
8 }
9 strip.show();
10 colorPos += colorStep;
11 lastStripUpdateTime = millis();
12 }
13 break;
14 case 1:
15 if (millis() - lastStripUpdateTime > stripDisplayDelay)
16 {
17 strip.setLedColor(currentLedIndex, strip.Wheel(colorPos));
18 currentLedIndex++;
19 if (currentLedIndex == STRIP_LEDS_COUNT)
20 {
21 currentLedIndex = 0;
22 colorPos += colorStep; }
23 lastStripUpdateTime = millis();
24 }
25 break;
26 default:
27 break;
28 }
29
www.freenove.com
106 Chapter 5 RF Remote Control [email protected]
www.freenove.com
[email protected] Chapter 5 RF Remote Control 107
05.1_RF24_Remote_Controller
The code is below:
1 // RF24L01
2 #include <SPI.h>
3 #include "RF24.h"
4 RF24 radio(9, 10); // define the object to control RF24L01
5 const byte addresses[6] = "Free1";// define communication address which should correspond to
6 the control board of car
7 // wireless communication
8 int dataWrite[8]; // define array used to save the write data
9 // pin
10 const int pot1Pin = A0, // define POT1 Potentiometer
11 pot2Pin = A1, // define POT2 Potentiometer
12 joystickXPin = A2, // define pin for direction X of joystick
13 joystickYPin = A3, // define pin for direction Y of joystick
14 joystickZPin = 7, // define pin for direction Z of joystick
15 s1Pin = 4, // define pin for S1
16 s2Pin = 3, // define pin for S2
17 s3Pin = 2, // define pin for S3
www.freenove.com
108 Chapter 5 RF Remote Control [email protected]
18 led1Pin = 6, // define pin for LED1 which is close to POT1 and used to
19 indicate the state of POT1
20 led2Pin = 5, // define pin for LED2 which is close to POT2 and used to
21 indicate the state of POT2
22 led3Pin = 8; // define pin for LED3 which is close to RF24L01 and used to
23 indicate the state of RF24L01
24
25 void setup() {
26 // RF24L01
27 radio.begin(); // initialize RF24
28 radio.setPALevel(RF24_PA_MAX); // set power amplifier (PA) level
29 radio.setDataRate(RF24_1MBPS); // set data rate through the air
30 radio.setRetries(0, 15); // set the number and delay of retries
31 radio.openWritingPipe(addresses); // open a pipe for writing
32 radio.openReadingPipe(1, addresses);// open a pipe for reading
33 radio.stopListening(); // stop listening for incoming messages
34
35 // pin
36 pinMode(joystickZPin, INPUT); // set led1Pin to input mode
37 pinMode(s1Pin, INPUT); // set s1Pin to input mode
38 pinMode(s2Pin, INPUT); // set s2Pin to input mode
39 pinMode(s2Pin, INPUT); // set s3Pin to input mode
40 pinMode(led1Pin, OUTPUT); // set led1Pin to output mode
41 pinMode(led2Pin, OUTPUT); // set led2Pin to output mode
42 pinMode(led3Pin, OUTPUT); // set led3Pin to output mode
43 }
44
45 void loop()
46 {
47 // put the values of rocker, switch and potentiometer into the array
48 dataWrite[0] = analogRead(pot1Pin); // save data of Potentiometer 1
49 dataWrite[1] = analogRead(pot2Pin); // save data of Potentiometer 2
50 dataWrite[2] = analogRead(joystickXPin); // save data of direction X of joystick
51 dataWrite[3] = analogRead(joystickYPin); // save data of direction Y of joystick
52 dataWrite[4] = digitalRead(joystickZPin); // save data of direction Z of joystick
53 dataWrite[5] = digitalRead(s1Pin); // save data of switch 1
54 dataWrite[6] = digitalRead(s2Pin); // save data of switch 2
55 dataWrite[7] = digitalRead(s3Pin); // save data of switch 3
56
57 // write radio data
58 if (radio.write(dataWrite, sizeof(dataWrite)))
59 {
60 digitalWrite(led3Pin, HIGH);
61 delay(20);
www.freenove.com
[email protected] Chapter 5 RF Remote Control 109
62 digitalWrite(led3Pin, LOW);
63 }
64
65 // make LED emit different brightness of light according to analog of potentiometer
66 analogWrite(led1Pin, map(dataWrite[0], 0, 1023, 0, 255));
67 analogWrite(led2Pin, map(dataWrite[1], 0, 1023, 0, 255));
68 }
Install RF module on the car. RF module and IR receiver use the same receiver pins.
www.freenove.com
110 Chapter 5 RF Remote Control [email protected]
Then connect car control board to computer. And upload code in Sketches\05.2_Receive_Data.
You need remove Bluetooth Module first when you upload code.
www.freenove.com
[email protected] Chapter 5 RF Remote Control 111
Data to components
P1(POT1)
P2(POT2)
S1 Z
S2
S3 X
www.freenove.com
112 Chapter 5 RF Remote Control [email protected]
Code
05.2_Receive_Data
The code is below.
1 #include <SPI.h>
2 #include "RF24.h"
3
4 #define PIN_SPI_CE 9
5 #define PIN_SPI_CSN 10
6
7 RF24 radio(PIN_SPI_CE, PIN_SPI_CSN); // define an object to control RF24L01
8 const byte addresses[6] = "Free1"; //set commutation address, same to remote controller
9 int RFDataRead[8]; //define an array to save data from remote controller
10 void setup() {
11 Serial.begin(9600);
12
13 // RF24L01 initialization steps
14 if (radio.begin()) { // initialize RF24
15 radio.setPALevel(RF24_PA_MAX); // set power amplifier (PA) level
16 radio.setDataRate(RF24_1MBPS); // set data rate through the air
17 radio.setRetries(0, 15); // set the number and delay of retries
18 radio.openWritingPipe(addresses); // open a pipe for writing
19 radio.openReadingPipe(1, addresses);// open a pipe for reading
20 radio.startListening(); // start monitoringtart listening on the pipes opened
21 Serial.println("Start listening remote data ... ");
22 }
23 else {
24 Serial.println("Not found the RF chip!");
25 }
26 }
27
28 void loop() {
29 if (radio.available()) { // if receive the data
30 while (radio.available()) { // read all the data
31 radio.read(RFDataRead, sizeof(RFDataRead)); // read data
32 }
33 Serial.print("P1/P2/X/Y/Z/S1/S2/S3 : ");
34 for (int i = 0; i < sizeof(RFDataRead) / 2; i++) {
35 Serial.print(RFDataRead[i]);
36 Serial.print('\t');
37 }
38 Serial.print('\n');
39 }
www.freenove.com
[email protected] Chapter 5 RF Remote Control 113
40 }
41
The communication is as follows:
RF module 1 (on your car) RF module 2 (on remote controller)
RX RX
TX TX
www.freenove.com
114 Chapter 5 RF Remote Control [email protected]
After successfully receiving the data sent by the RF remote control, we can use the data to control car
movement, buzzer sounds, etc.
Connect Car to computer with USB cable, and upload code in Sketches\05.3_RF24_Remote_Car.ino.
You need remove Bluetooth Module first when you upload code.
Then disconnect the USB cable and turn on the RF Remote Control and Car power switches. Operate the
joystick to control the movement of the car. Press the joystick to turn on the buzzer.
www.freenove.com
[email protected] Chapter 5 RF Remote Control 115
Code
The project has five labels, of which "RF24_Remote.h" and "RF24_Remote.cpp" store contents about data
reading and data processing for the RF24 remote control. These contents are called in
"05.3_RF24_Remote_Car.ino".
RF24_Remote.h
1 #ifndef _RF_REMOTE_h
2 #define _RF_REMOTE_h
3
4 #include "Freenove_4WD_Car_for_Arduino.h"
5 #include "RF24.h"
6
7 extern RF24 radio;
8
9 enum RemoteData
10 {
11 POT1 = 0,
12 POT2 = 1,
13 JOYSTICK_X = 2,
14 JOYSTICK_Y = 3,
15 JOYSTICK_Z = 4,
16 S1 = 5,
17 S2 = 6,
18 S3 = 7
19 };
20 enum RemoteMode {
21 ON_ON_ON = 0,
22 ON_ON_OFF = 1, //Servo calibration mode.
23 ON_OFF_ON = 2,
24 ON_OFF_OFF = 3, //Ultrasonic obstacle avoidance mode.
25 OFF_ON_ON = 4,
26 OFF_ON_OFF = 5, //Line tracking mode.
27 OFF_OFF_ON = 6, //
28 OFF_OFF_OFF = 7 //Remote control mode.
29 };
30 enum RemoteModeSwitchState {
31 MODE_SWITCHING_IS_INITIALIZING = 0,
32 MODE_SWITCHING_IS_PROCESSING = 1,
33 MODE_SWITCHING_IS_CONFIRMING = 2,
34 MODE_SWITCHING_WAS_FINISHED = 3
35 };
36
37 #define MODE_REMOTE_CONTROL OFF_OFF_OFF
www.freenove.com
116 Chapter 5 RF Remote Control [email protected]
Where enum RemoteData defines the order of the remote control data received, using more meaningful
variable names instead of numbers. For example, if you want to use the X-axis data of the remote control,
you can use RFDataRead[JOYSTICK_X] instead of the no meaningless RFDataRead[2]. It like define
enum RemoteData
{
POT1 = 0, // similar to #define POT1 0
POT2 = 1,
JOYSTICK_X = 2,
JOYSTICK_Y = 3,
JOYSTICK_Z = 4,
S1 = 5,
S2 = 6,
S3 = 7
};
The enum RemoteMode defines all states of the remote control switches S1, S2, S3. The enum
RemoteModeSwitchState defines the state when the remote control switches modes. These contents will also
be used in the next project.
enum RemoteMode {
ON_ON_ON = 0,
ON_ON_OFF = 1, //Servo calibration mode.
ON_OFF_ON = 2,
ON_OFF_OFF = 3, //Ultrasonic obstacle avoidance mode.
OFF_ON_ON = 4,
OFF_ON_OFF = 5, //Line tracking mode.
OFF_OFF_ON = 6, //
OFF_OFF_OFF = 7 //Remote control mode.
};
enum RemoteModeSwitchState {
MODE_SWITCHING_IS_INITIALIZING = 0,
MODE_SWITCHING_IS_PROCESSING = 1,
www.freenove.com
[email protected] Chapter 5 RF Remote Control 117
MODE_SWITCHING_IS_CONFIRMING = 2,
MODE_SWITCHING_WAS_FINISHED = 3
};
bool RF24L01Setup();
Initialize RF24L01. If success, return true, if not, return false.
bool getRF24L01Data();
Read data from remote control. If there is data read, return true; if not, return false.
void updateCarActionByRFRemote();
Control car actions (mainly for motor and buzzer) according to data received.
void resetRFDataBuf();
Set values of RFData array to default values.
u8 updateRFCarMode();
Combine data of S1 S2 S3 of remote control into one value and return it.
05.3_RF24_Remote_Car.ino
1 #include "Freenove_4WD_Car_for_Arduino.h"
2 #include "RF24_Remote.h"
3
4 #define RF_UPDATE_TIMEOUT 1000
5 u32 lastRFUpdateTime = 0;
6
7 void setup() {
8 pinsSetup();
9 if (!RF24L01Setup()) {
10 alarm(4, 2);
11 }
12 }
13
14 void loop() {
15 if (getRF24L01Data()) {
16 updateCarActionByRFRemote();
17 lastRFUpdateTime = millis();
18 }
19 if (millis() - lastRFUpdateTime > RF_UPDATE_TIMEOUT) {
20 lastRFUpdateTime = millis();
21 resetRFDataBuf();
22 updateCarActionByRFRemote();
23 }
24 }
In setup(), initialize pins and RF24L01. In loop(), receive data from the remote control and process the data. If
receiving data is time out, the remote control signal is considered to be lost and the car will be placed in the
initialization state.
www.freenove.com
118 Chapter 5 RF Remote Control [email protected]
This project combines almost all functions of the car, such as obstacle avoidance mode, line tracking mode,
remote control mode, RGB LED display mode, servo position calibration and so on. The switching among
different functions is realized by switching the states of S1, S2, and S3 on the remote controller.
The project code is more complicated, but the components and knowledge used have been introduced in the
previous project. The only difference is that they are integrated into one project, which is quite large.
Disconnect the USB cable. Turn on the power of the remote control and the car. By default, the car is in
manual remote control mode, and the S1, S2, and S3 switches on the remote control are off.
www.freenove.com
[email protected] Chapter 5 RF Remote Control 119
1, Change the switch state of S1, S2, and S3, and the car will stop moving.
2, Press the Z axis of the joystick and the buzzer B sounds to indicate that the mode is successfully switched.
The following table shows the modes indicated by different states of the three switches S1, S2, and S3. The
LED next to the switch illumination to indicate ON and OFF state of switches. The three switches can form
2x2x2=8 modes.
S1 S2 S3 Mode No. Mode
ON ON ON 0 None
ON ON OFF 1 Calibrate servo mode
ON OFF ON 2 None
ON OFF OFF 3 Obstacle avoidance mode
OFF ON ON 4 None
OFF ON OFF 5 Line tracking mode
OFF OFF ON 6 Switch LED mode
OFF OFF OFF 7 Manuel control mode / Default mode
Mode 0, 2, 4
Reserved. We did not assign functions for them.
www.freenove.com
120 Chapter 5 RF Remote Control [email protected]
In this mode, you can adjust potentiometer 2 (POT2) to fine tune the angle of the servo. When you adjust the
servo to the correct angle, press the Z-axis of joystick to save calibration data to EEPROM. It will be saved
permanently unless it is modified.
Mode 3-obstical avoidance, Mode 5-line tracking mode
These two modes have been learned separately in the previous project, and their running logic and codes are
consistent with the previous project.
The difference is that in this project, the car can respond to commands from the remote control at any time.
Therefore, in this project, it is still necessary to communicate with the remote controller in these two modes.
When the remote control signal is disconnected, the car will stop. Therefore, the normal communication
between the remote control and the car should be maintained at any time. Poor communication conditions
may cause these two modes to work abnormally.
Mode 6-switch LED display mode
There are three display modes for the LEDs on the car, which are 0-flowing rainbow, 1-flowing water led, 2-
Blink. In this mode, the display mode of the LED can be switched.
In any mode, the LEDs can be adjusted with potentiometers P1 and P2. P1 is used to adjust the color change
of the LED, and P2 is used to adjust the change frequency of LED.
P1(POT1)
P2(POT2)
You can switch the
display mode of the
LED by turning the
joystick in the
direction of the X axis.
www.freenove.com
[email protected] Chapter 5 RF Remote Control 121
Code
There are 9 (file) labels for this project, 8 of which have appeared in previous projects. In the file
"05.4_Multifunctional_RF24_Remote_Car.ino", it is mainly the logical management of each module function,
such as switching of the car mode, switching of the LED display mode.
05.4_Multifunctional_RF24_Remote_Car.ino
1 #include "Automatic_Tracking_Line_Mode.h"
2 #include "Automatic_Obstacle_Avoidance_Mode.h"
3 #include "Freenove_4WD_Car_for_Arduino.h"
4 #include "Freenove_WS2812B_RGBLED_Controller.h"
5 #include "RF24_Remote.h"
6
7 #define RF_UPDATE_TIMEOUT 1000
8
9 u32 lastRFUpdateTime = 0;
10 u8 RFCarMode = OFF_OFF_OFF, lastRFCarMode = OFF_OFF_OFF;
11 u8 switchModeState = MODE_SWITCHING_WAS_FINISHED;
12 u8 joystickSwitchState = MODE_SWITCHING_WAS_FINISHED;
13
14 #define STRIP_I2C_ADDRESS 0x20
15 #define STRIP_LEDS_COUNT 10
16
17 #define MAX_NUMBER_OF_DISP_MODES 3
18
19 u8 colorPos = 0;
20 u8 colorStep = 50;
21 u8 stripDisplayMode = 1;
22 u8 currentLedIndex = 0;
23 u16 stripDisplayDelay = 100;
24 u32 lastStripUpdateTime = 0;
25 Freenove_WS2812B_Controller strip(STRIP_I2C_ADDRESS, STRIP_LEDS_COUNT, TYPE_GRB);
26
27 void setup() {
28 pinsSetup();
29 if (!RF24L01Setup()) {
30 alarm(4, 2);
31 }
32 servoSetup();
33 while (!strip.begin());
34 strip.setAllLedsColor(0xFF0000);
35 }
36
37 void loop() {
www.freenove.com
122 Chapter 5 RF Remote Control [email protected]
38 if (getRF24L01Data()) {
39 RFCarMode = updateRFCarMode();
40 if (RFCarMode != lastRFCarMode) {
41 if (switchModeState == MODE_SWITCHING_WAS_FINISHED) {
42 switchModeState = MODE_SWITCHING_IS_INITIALIZING;
43 }
44 switch (switchModeState)
45 {
46 case MODE_SWITCHING_IS_INITIALIZING:
47 //Serial.println("Switching Mode Init...");
48 resetCarAction();
49 writeServo(90);
50 switchModeState = MODE_SWITCHING_IS_PROCESSING;
51 break;
52 case MODE_SWITCHING_IS_PROCESSING:
53 if (RFDataRead[JOYSTICK_Z] == 0) {
54 //Serial.println("Switching Mode ...");
55 setBuzzer(true);
56 switchModeState = MODE_SWITCHING_IS_CONFIRMING;
57 }
58 break;
59 case MODE_SWITCHING_IS_CONFIRMING:
60 if (RFDataRead[JOYSTICK_Z] == 1) {
61 //Serial.println("Comfirm Switched.");
62 setBuzzer(false);
63
64 switchModeState = MODE_SWITCHING_WAS_FINISHED;
65 lastRFCarMode = RFCarMode;
66 switch (RFCarMode)
67 {
68 case MODE_OBSTACKE_AVOIDANCE:
69 oa_CalculateVoltageCompensation();
70 break;
71 case MODE_LINE_TRACKING:
72 tk_CalculateVoltageCompensation();
73 break;
74 default:
75 break;
76 }
77 //Serial.println("Switch mode finished !");
78 }
79 break;
80 case MODE_SWITCHING_WAS_FINISHED:
81 break;
www.freenove.com
[email protected] Chapter 5 RF Remote Control 123
82 default:
83 break;
84 }
85 }
86 else {
87 if (switchModeState != MODE_SWITCHING_WAS_FINISHED) {
88 switchModeState = MODE_SWITCHING_WAS_FINISHED;
89 }
90 switch (RFCarMode)
91 {
92 case ON_ON_ON:
93 break;
94 case ON_ON_OFF: //S1,S2 ON, S3 OFF
95 setServoOffset(map(nrfDataRead[1], 0, 1023, -20, 20));
96 if (RFDataRead[JOYSTICK_Z] == 0) {
97 setBuzzer(true);
98 writeServoOffsetToEEPROM();
99 }
100 else {
101 setBuzzer(false);
102 }
103 break;
104 case ON_OFF_ON:
105 break;
106 case ON_OFF_OFF: ////Sonic Obstacle Avoidance Mode, S1 is ON and S2, S3 are
107 OFF
108 updateAutomaticObstacleAvoidance();
109 break;
110 case OFF_ON_ON:
111 break;
112 case OFF_ON_OFF: //Tracking Mode,S2 is ON and S1, S3 are OFF.
113 updateAutomaticTrackingLine();
114 break;
115 case OFF_OFF_ON: //S3 is ON and S1, S2 are OFF
116 //stripDisplayMode = RFDataRead[POT2] / 512;
117 switch (joystickSwitchState)
118 {
119 static u8 switchCounter = 0;
120 case MODE_SWITCHING_IS_INITIALIZING:
121 if (RFDataRead[JOYSTICK_X] > 900)
122 {
123 setBuzzer(true);
124 switchCounter++;
125 joystickSwitchState = MODE_SWITCHING_IS_PROCESSING;
www.freenove.com
124 Chapter 5 RF Remote Control [email protected]
126 }
127 else if (RFDataRead[JOYSTICK_X] < 200)
128 {
129 setBuzzer(true);
130 switchCounter--;
131 joystickSwitchState = MODE_SWITCHING_IS_PROCESSING;
132 }
133 break;
134 case MODE_SWITCHING_IS_PROCESSING:
135 if ((RFDataRead[JOYSTICK_X] < 600) && (RFDataRead[JOYSTICK_X] > 400))
136 {
137 setBuzzer(false);
138 joystickSwitchState = MODE_SWITCHING_IS_CONFIRMING;
139 }
140 break;
141 case MODE_SWITCHING_IS_CONFIRMING:
142 stripDisplayMode += switchCounter;
143 if (stripDisplayMode == 0xff)
144 {
145 stripDisplayMode = MAX_NUMBER_OF_DISP_MODES - 1;
146 }
147 stripDisplayMode %= MAX_NUMBER_OF_DISP_MODES;
148 joystickSwitchState = MODE_SWITCHING_WAS_FINISHED;
149 break;
150 case MODE_SWITCHING_WAS_FINISHED:
151 switchCounter = 0;
152 joystickSwitchState = MODE_SWITCHING_IS_INITIALIZING;
153 break;
154 default:
155 break;
156 }
157 break;
158 case OFF_OFF_OFF: //Remote Mode, all switch leds are OFF
159 updateCarActionByRFRemote();
160 break;
161 default:
162 break;
163 }
164 }
165 colorStep = map(RFDataRead[POT1], 0, 1023, 0, 255);
166 stripDisplayDelay = RFDataRead[POT2];
167 lastRFUpdateTime = millis();
168 }
169
www.freenove.com
[email protected] Chapter 5 RF Remote Control 125
www.freenove.com
126 Chapter 5 RF Remote Control [email protected]
214 }
215 ledState = !ledState;
216 lastStripUpdateTime = millis();
217 }
218 break;
219 default:
220 break;
221 }
222 }
In setup(), initialize pins and RF24L01 and LED module. In loop(), receive data from the remote control and
process the data. If receiving data is time out, the remote control signal is considered to be lost. LED display
code is added in this code, which is different from code in the previous project.
void setup() {
pinsSetup();
if (!RF24L01Setup()) {
alarm(4, 2);
}
servoSetup();
while (!strip.begin());
strip.setAllLedsColor(0xFF0000);
}
void loop() {
if (getRF24L01Data()) {
……
}
www.freenove.com
[email protected] Chapter 5 RF Remote Control 127
After reading the remote control data, judge whether the mode of the car has changed according to the state
of S1, S2, S3. If the mode is changed, the code of the corresponding mode will be executed. Otherwise, the
subsequent code will be executed.
if (getRF24L01Data()) {
RFCarMode = updateRFCarMode();
if (RFCarMode != lastRFCarMode) {
if (switchModeState == MODE_SWITCHING_WAS_FINISHED) {
switchModeState = MODE_SWITCHING_IS_INITIALIZING;
}
switch (switchModeState)
{
……
}
……
}
else {
……
}
When the state of S1, S2, S3 changes, it means that the user wants to change the mode of the car, but in
order to ensure that this change is not an erroneous operation, the user needs to press the Z axis of the
joystick to confirm.
This series of actions can be implemented using the idea of a finite state machine. When the switch state
changes, the state "MODE_SWITCHING_IS_INITIALIZING" is entered, the car's power module, motor and servo
are initialized to prevent the car from running uncontrolledly.
case MODE_SWITCHING_IS_INITIALIZING:
//Serial.println("Switching Mode Init...");
resetCarAction();
writeServo(90);
switchModeState = MODE_SWITCHING_IS_PROCESSING;
break;
Then enter next state "MODE_SWITCHING_IS_PROCESSING" and wait for the user to press the rocker Z axis
to confirm. If the user presses the Z axis of the joystick, the buzzer sounds and enters the next state
"MODE_SWITCHING_IS_CONFIRMING", waiting for the user to release the joystick. When the user releases
the joystick, the buzzer stops sounding and changes the value of the variable switchModeState that holds the
car mode. After the mode is switched, the completion status "MODE_SWITCHING_WAS_FINISHED" is entered.
case MODE_SWITCHING_IS_PROCESSING:
if (RFDataRead[JOYSTICK_Z] == 0) {
//Serial.println("Switching Mode ...");
setBuzzer(true);
switchModeState = MODE_SWITCHING_IS_CONFIRMING;
}
break;
www.freenove.com
128 Chapter 5 RF Remote Control [email protected]
case MODE_SWITCHING_IS_CONFIRMING:
if (RFDataRead[JOYSTICK_Z] == 1) {
//Serial.println("Comfirm Switched.");
setBuzzer(false);
switchModeState = MODE_SWITCHING_WAS_FINISHED;
lastRFCarMode = RFCarMode;
switch (RFCarMode)
{
case MODE_OBSTACKE_AVOIDANCE:
oa_CalculateVoltageCompensation();
break;
case MODE_LINE_TRACKING:
tk_CalculateVoltageCompensation();
break;
default:
break;
}
//Serial.println("Switch mode finished!");
}
break;
case MODE_SWITCHING_WAS_FINISHED:
break;
default:
break;
}
Next, use the switch-case statement to let the car perform the corresponding function or action according to
the value of the car mode variable RFCarMode.
switch (RFCarMode)
{
case ON_ON_ON:
break;
case ON_ON_OFF: //S1,S2 ON, S3 OFF
……//Set Servo offset
case ON_OFF_ON:
break;
case ON_OFF_OFF: ////Sonic Obstacle Avoidance Mode, S1 is ON and S2, S3 are OFF
updateAutomaticObstacleAvoidance();
break;
case OFF_ON_ON:
break;
case OFF_ON_OFF: //Tracking Mode, S2 is ON and S1, S3 are OFF.
updateAutomaticTrackingLine();
break;
www.freenove.com
[email protected] Chapter 5 RF Remote Control 129
In the calibration servo mode, the angle of the servo is adjusted according to the value of the potentiometer
POT2. When the rocker Z-axis is pressed, the adjusted data is written into the EEPROM, and the buzzer will
make a sound to confirm the writing.
case ON_ON_OFF: //S1,S2 ON, S3 OFF
setServoOffset(RFDataRead[1] / 100);
if (RFDataRead[JOYSTICK_Z] == 0) {
setBuzzer(true);
writeServoOffsetToEEPROM();
}
else {
setBuzzer(false);
}
break;
In the mode of switching the LED display, the idea of finite state machine is still used.
First, enter the initialization state, waiting for the joystick to move in the direction of the X axis. If there is, the
variable switchCounter will be self-added or self-decremented according to the positive and negative
directions. Then enter next state, wait for the joystick to return to the middle. When the joystick returns to the
middle, enter the next state, process the data, after the data processing is completed, enter the completion
state.
switch (joystickSwitchState)
{
static u8 switchCounter = 0;
case MODE_SWITCHING_IS_INITIALIZING:
if (RFDataRead[JOYSTICK_X] > 900)
{
setBuzzer(true);
switchCounter++;
joystickSwitchState = MODE_SWITCHING_IS_PROCESSING;
}
else if (RFDataRead[JOYSTICK_X] < 200)
{
setBuzzer(true);
switchCounter--;
www.freenove.com
130 Chapter 5 RF Remote Control [email protected]
joystickSwitchState = MODE_SWITCHING_IS_PROCESSING;
}
break;
case MODE_SWITCHING_IS_PROCESSING:
if ((RFDataRead[JOYSTICK_X] < 600) && (RFDataRead[JOYSTICK_X] > 400))
{
setBuzzer(false);
joystickSwitchState = MODE_SWITCHING_IS_CONFIRMING;
}
break;
case MODE_SWITCHING_IS_CONFIRMING:
stripDisplayMode += switchCounter;
if (stripDisplayMode == 0xff)
{
stripDisplayMode = MAX_NUMBER_OF_DISP_MODES - 1;
}
stripDisplayMode %= MAX_NUMBER_OF_DISP_MODES;
joystickSwitchState = MODE_SWITCHING_WAS_FINISHED;
break;
case MODE_SWITCHING_WAS_FINISHED:
switchCounter = 0;
joystickSwitchState = MODE_SWITCHING_IS_INITIALIZING;
break;
default:
break;
}
break;
The variable that controls the LED display color change and the variable of the display frequency are updated
every time according to remote control data.
colorStep = map(RFDataRead[POT1], 0, 1023, 0, 255);
stripDisplayDelay = RFDataRead[POT2];
Finally, the LED display mode variable stripDisplayMode, the color change amplitude variable colorStep, the
display period variable stripDisplayDelay.
switch (stripDisplayMode)
{
case 0:
if (millis() - lastStripUpdateTime > stripDisplayDelay)
{
for (int i = 0; i < STRIP_LEDS_COUNT; i++) {
strip.setLedColorData(i, strip.Wheel(colorPos + i * 25));
}
strip.show();
www.freenove.com
[email protected] Chapter 5 RF Remote Control 131
colorPos += colorStep;
lastStripUpdateTime = millis();
}
break;
case 1:
if (millis() - lastStripUpdateTime > stripDisplayDelay)
{
strip.setLedColor(currentLedIndex, strip.Wheel(colorPos));
currentLedIndex++;
if (currentLedIndex == STRIP_LEDS_COUNT)
{
currentLedIndex = 0;
colorPos += colorStep; //
}
lastStripUpdateTime = millis();
}
break;
case 2:
colorPos = colorStep;
if (millis() - lastStripUpdateTime > stripDisplayDelay)
{
static bool ledState = true;
if (ledState)
{
strip.setAllLedsColor(strip.Wheel(colorPos));
}
else
{
strip.setAllLedsColor(0x00);
}
ledState = !ledState;
lastStripUpdateTime = millis();
}
break;
default:
break;
}
www.freenove.com
132 Chapter 6 Bluetooth control [email protected]
Download and install app. You can use app to control the robot.
You can download Freenove App through below ways:
View or download on Google Play:
https://play.google.com/store/apps/details?id=com.freenove.suhayl.Freenove
Download APK file directly
https://github.com/Freenove/Freenove_App_for_Android/raw/master/freenove.apk
Then install it on your Android phone.
You can also use following APP to control this car. In addition, there are videos about robot projects shared
by others on this APP, as well as videos of our company's products. You can also share your own videos on
this APP. In addition, you can also chat with other users on this video. You are welcome to use this APP. You
can download it on google play:
https://play.google.com/store/apps/details?id=com.robotech.boogoo
www.freenove.com
[email protected] Chapter 6 Bluetooth control 133
www.freenove.com
134 Chapter 6 Bluetooth control [email protected]
The Bluetooth module uses the serial port to communicate with the Arduino. The serial communication is also
used to upload the program to Arduino. Therefore, when uploading the program to Arduino, the
Bluetooth module should be unplugged; otherwise, the program upload will fail!
When the Bluetooth module is not connected by other device, the Bluetooth module can be configured using
the AT command. Once connected, the Bluetooth module acts as a data pipe and cannot be configured.
By default, the Bluetooth module has a baud rate of 9600, no parity, 8 data bits, and 1 stop bit. Bluetooth
name "BT05", role mode is slave mode.
Set name of bluetooth
If you have multiple Bluetooth modules with the same name around you, you will be confused when you
connect. Which one is the Bluetooth module I want to connect to?
In the next project, we will introduce how to use the AT command to modify the name of the Bluetooth
module and the master-slave role in the program.
For AT commands and more information about the Bluetooth module, refer to the documentation in the
package for Datasheets/BT05-Instruction.pdf
www.freenove.com
[email protected] Chapter 6 Bluetooth control 135
This project uses the AT command to make some settings for the Bluetooth module, then uses the Bluetooth
module to receive data from the app and print the data on the serial monitor.
You need remove Bluetooth Module first when you upload code.
Then upload code in Sketches/06.1_Receive_Bluetooth_Data.ino.
Note, when upload code, we need unplug Bluetooth first. Or the uploading will fail.
www.freenove.com
136 Chapter 6 Bluetooth control [email protected]
www.freenove.com
[email protected] Chapter 6 Bluetooth control 137
Next, open the app and click the 4WD Car for Arduino.
www.freenove.com
138 Chapter 6 Bluetooth control [email protected]
If the connection successes, it will be connected. Operate the app. And observe the monitor.
www.freenove.com
[email protected] Chapter 6 Bluetooth control 139
Code
06.1_Receive_Bluetooth_Data
The data of the Bluetooth module is sent to the Arduino through the serial port. The project code comes from
the Arduino example code "SerialEvent". Receive data from the serial port and print the data when ‘\n’ is
received.
The code is below:
1 String inputString = ""; // a String to hold incoming data
2 bool stringComplete = false; // whether the string is complete
3
4 void setup() {
5 // initialize serial:
6 Serial.begin(9600); //default data transmission baud rate of the Bluetooth module is 9600
7 Serial.println("AT+NAMEBT05");// Or use Serial.print("AT+NAMEBT05\r\n");
8 delay(200);
9 Serial.println("AT+ROLE0");
10 delay(200);
11 // reserve 200 bytes for the inputString:
12 inputString.reserve(200);
13 }
14
www.freenove.com
140 Chapter 6 Bluetooth control [email protected]
15 void loop() {
16 // print the string when a newline arrives:
17 if (stringComplete) {
18 Serial.println(inputString);
19 // clear the string:
20 inputString = "";
21 stringComplete = false;
22 }
23 }
24
25 /*
26 SerialEvent occurs whenever a new data comes in the hardware serial RX. This
27 routine is run between each time loop() runs, so using delay inside loop can
28 delay response. Multiple bytes of data may be available.
29 */
30 void serialEvent() {
31 while (Serial.available()) {
32 // get the new byte:
33 char inChar = (char)Serial.read();
34 // add it to the inputString:
35 inputString += inChar;
36 // if the incoming character is a newline, set a flag so the main loop can
37 // do something about it:
38 if (inChar == '\n') {
39 stringComplete = true;
40 }
41 }
42 }
The default data transmission baud rate of the Bluetooth module is 9600, so set serial port baud rate to 9600.
Serial.begin(9600); //default data transmission baud rate of the Bluetooth module is 9600
Then use the AT command to set the name of the Bluetooth module to "BT05". The format of the command
is "AT+NAMExxx\r\n", where "AT+NAME" is a fixed format, and the following "xxx" is the set name. The
maximum length of the name is 18 characters. The command must be followed by "\r\n" ends. Since the
Serial.pirntln() function adds "\r\n" to the end, there is no need to add it in the program. The delay is 200ms
to ensure that the Bluetooth module has enough time to complete the setup.
Serial.println("AT+NAMEBT05");// Or use Serial.print("AT+NAMEBT05\r\n");
delay(200);
www.freenove.com
[email protected] Chapter 6 Bluetooth control 141
Similarly, continue to use the AT command to set the Bluetooth module's role mode to slave mode. The
Bluetooth module can be set to master mode or slave mode. In master mode, the Bluetooth module can
actively search for and connect to other Bluetooth devices, but cannot be searched and connected by other
devices. In order to be searched by the mobile app via Bluetooth, the Bluetooth role module needs to be set
to the slave mode. According to the Bluetooth manufacturer's manual, 0 is the slave mode and 1 is the master
mode.
Serial.println("AT+ROLE0");
delay(200);
In loop(), keep querying if stringComplete is true. If it is true, it indicates that the complete data has been
received. The data will be printed on the serial monitor, and then the data is cleared. And then the array is
ready to receive new data.
if (stringComplete) {
Serial.println(inputString);
// clear the string:
inputString = "";
stringComplete = false;
}
Function serialEvent() is used to receive the data transmitted by the serial port. When the newline character is
received, the flag stringComplete is set to true, and the received data will be printed in loop().
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag so the main loop can
// do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
Bluetooth AT Command
AT command mode when the module is not connected.
AT command, which belongs to the character line instruction, is parsed according to the line
(That is, AT command must be returned by carriage return or \r\n, hexadecimal number is 0D0A).
For more details about AT command, please refer to Datasheets/BT05-Instruction.pdf.
void serialEvent()
SerialEvent occurs whenever a new data comes in the hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay response. Multiple bytes of data may be available.
www.freenove.com
142 Chapter 6 Bluetooth control [email protected]
After learning how to receive the app's data via Bluetooth and the meaning of data formats, use the data to
let the car do something. Control the car movement, the buzzer sounds, and the LED switches the display
mode.
You need remove Bluetooth Module first when you upload code.
And connect car to computer with USB cable.
Then upload code in Sketches/06.2_Bluetooth_Remote_Car.ino.
After the code is successfully uploaded, unplug the USB cable and plug the Bluetooth module on car.
Turn on the car power switch.
www.freenove.com
[email protected] Chapter 6 Bluetooth control 143
According to the previous way, the Bluetooth module of the car is connected through app, then the car can
be controlled by clicking or sliding the operation panel on the APP.
Code
The project has 4 labels, the label "BluetoothOrders.h" stores Bluetooth communication, and command
characters are used to control the car, only a part of which is used. The main label
"06.2_Bluetooth_Remote_Car.ino" is the main content of this project.
BluetoothOrders.h
1 #ifndef _BLUETOOTHORDERS_h
2 #define _BLUETOOTHORDERS_h
3
4 #define ACTION_MOVE 'A'
5 #define ACTION_STOP 'B'
6 #define ACTION_RGB 'C'
7 #define ACTION_BUZZER 'D'
8 #define ACTION_ULTRASONIC 'E'
9 #define ACTION_LIGHT_TRACING 'F'
10 #define ACTION_TRACKING 'G'
11 #define ACTION_CAR_MODE 'H'
www.freenove.com
144 Chapter 6 Bluetooth control [email protected]
06.2_Bluetooth_Remote_Car.ino
1 #include "Freenove_4WD_Car_for_Arduino.h"
2 #include "BluetoothOrders.h"
3
4 #define UPLOAD_VOL_TIME 3000
5 #define COMMANDS_COUNT_MAX 8
6 #define INTERVAL_CHAR '#'
7
8 u32 lastUploadVoltageTime;
9 String inputStringBLE = "";
10 bool stringComplete = false;
11
12 void setup() {
13 pinsSetup();
14 Serial.begin(9600);
15
16 }
17
18 void loop() {
19 if (millis() - lastUploadVoltageTime > UPLOAD_VOL_TIME) {
20 upLoadVoltageToApp();
21 lastUploadVoltageTime = millis();
22 }
23 if (stringComplete) {
24 String inputCommandArray[COMMANDS_COUNT_MAX];
25 int paramters[COMMANDS_COUNT_MAX], paramterCount = 0;
26 String inputStringTemp = inputStringBLE;
27 for (u8 i = 0; i < COMMANDS_COUNT_MAX; i++) {
28 int index = inputStringTemp.indexOf(INTERVAL_CHAR);
29 if (index < 0) {
30 break;
31 }
32 paramterCount = i; //
33 inputCommandArray[i] = inputStringTemp.substring(0, index);
34 inputStringTemp = inputStringTemp.substring(index + 1);
35 paramters[i] = inputCommandArray[i].toInt();
36 }
37 stringComplete = false;
www.freenove.com
[email protected] Chapter 6 Bluetooth control 145
38 inputStringBLE = "";
39
40 char commandChar = inputCommandArray[0].charAt(0);
41 switch (commandChar)
42 {
43 case ACTION_MOVE:
44 if (paramterCount == 2) {
45 motorRun(paramters[1], paramters[2]);
46 }
47 break;
48 case ACTION_BUZZER:
49 if (paramterCount == 1) {
50 setBuzzer(paramters[1]);
51 }
52 break;
53 default:
54 break;
55 }
56 }
57 }
58
59 void upLoadVoltageToApp() {
60 int voltage = 0;
61 if (getBatteryVoltage()) {
62 voltage = batteryVoltage * 1000;
63 }
64 String sendString = String(ACTION_GET_VOLTAGE) + String(INTERVAL_CHAR) +
65 String((voltage)) + String(INTERVAL_CHAR);
66 Serial.println(sendString);
67 }
68
69 void serialEvent() {
70 while (Serial.available()) {
71 char inChar = (char)Serial.read();
72 inputStringBLE += inChar;
73 if (inChar == '\n') {
74 stringComplete = true;
75 }
76 }
77 }
www.freenove.com
146 Chapter 6 Bluetooth control [email protected]
lastUploadVoltageTime = millis();
}
In the sub-function upLoadVoltageToApp(), first read the battery voltage, then convert the voltage unit to
mv, and send it in the format of "I#xxx#". Use Serial.println() to send a Newline character '\n', after sending
the previous data,
void upLoadVoltageToApp() {
int voltage = 0;
if (getBatteryVoltage()) {
voltage = batteryVoltage * 1000;
}
String sendString = String(ACTION_GET_VOLTAGE) + String(INTERVAL_CHAR) +
String((voltage)) + String(INTERVAL_CHAR);
Serial.println(sendString);
}
Then in loop(), if the required data is received, the data will be parsed into commands and parameters and
will be saved in an array.
Suppose you receive a command string of "A#100#200#". First use the String.indexOf() function to find the
position of the separator "#". And then use the String.substring() function to split the command string into "
A" and "100#200#", and save the first element "A" that is split in the array "inputCommandArray".
And then continue to repeat this operation on the split string "100#200#". You can split the element "A" into
"100" and "200" respectively and save them in arrays. Finally, convert these elements to integer types and
save them in the parameter array paramters.
if (stringComplete) {
String inputCommandArray[COMMANDS_COUNT_MAX];
int paramters[COMMANDS_COUNT_MAX], paramterCount = 0;
String inputStringTemp = inputStringBLE;
for (u8 i = 0; i < COMMANDS_COUNT_MAX; i++) {
int index = inputStringTemp.indexOf(INTERVAL_CHAR);
if (index < 0) {
break;
}
paramterCount = i; //
inputCommandArray[i] = inputStringTemp.substring(0, index);
inputStringTemp = inputStringTemp.substring(index + 1);
paramters[i] = inputCommandArray[i].toInt();
}
……
Finally, let the car perform different actions according to the commands and parameters.
char commandChar = inputCommandArray[0].charAt(0);
switch (commandChar)
www.freenove.com
[email protected] Chapter 6 Bluetooth control 147
{
case ACTION_MOVE:
if (paramterCount == 2) {
motorRun(paramters[1], paramters[2]);
}
break;
case ACTION_BUZZER:
if (paramterCount == 1) {
setBuzzer(paramters[1]);
}
break;
default:
break;
}
indexOf()
Description
Locates a character or String within another String. By default, it searches from the beginning of the String,
but it can also start from a given index, allowing for the locating of all instances of the character or String.
Syntax
myString.indexOf(val)
myString.indexOf(val, from)
Parameters
myString: a variable of type String.
val: the value to search for. Allowed data types: char, String.
from: the index to start the search from.
Returns
The index of val within the String, or -1 if not found.
substring()
Description
Get a substring of a String. The starting index is inclusive (the corresponding character is included in the
substring), but the optional ending index is exclusive (the corresponding character is not included in the
substring). If the ending index is omitted, the substring continues to the end of the String.
Syntax
myString.substring(from)
myString.substring(from, to)
Parameters
myString: a variable of type String.
from: the index to start the substring at.
to (optional): the index to end the substring before.
Returns
The substring.
toInt()
Description
www.freenove.com
148 Chapter 6 Bluetooth control [email protected]
Converts a valid String to an integer. The input String should start with an integer number. If the String
contains non-integer numbers, the function will stop performing the conversion.
Syntax
myString.toInt()
Parameters
myString: a variable of type String.
Returns
If no valid conversion could be performed because the String doesn’t start with an integer number, a zero
is returned. Data type: long.
www.freenove.com
[email protected] Chapter 6 Bluetooth control 149
This project adds the function of LED display and the function of LED display mode switching on the basis of
the previous project.
After the code is successfully uploaded, unplug the USB cable and plug the Bluetooth module on car. Turn
on the car power switch.
www.freenove.com
150 Chapter 6 Bluetooth control [email protected]
According to the previous method, connect Bluetooth module of the car with the app, and the operation
panel of the APP can be clicked or swiped to control the movement of the car. And the color palette of the
lower right corner can be clicked to control the display mode and color of the LED. Among them,
Mode 0 is a flowing rainbow,
Mode 1 is a flowing water LED with color changing.
Mode 2 is a color-adjustable Blink.
Mode 3 displays the selected color of the current color picker for all LEDs.
Code
The code for this project is based on the previous engineering code, adding code related to LED control.
Nothing else has changed.
06.3_Multifunctional_Bluetooth_Remote_Car
1 #include "Freenove_4WD_Car_for_Arduino.h"
2 #include "Automatic_Obstacle_Avoidance_Mode.h"
3 #include "Automatic_Tracking_Line_Mode.h"
4 #include "BluetoothOrders.h"
5 #include "Freenove_WS2812B_RGBLED_Controller.h"
6
www.freenove.com
[email protected] Chapter 6 Bluetooth control 151
www.freenove.com
152 Chapter 6 Bluetooth control [email protected]
95 case 0:
96 colorStep = 5;
97 stripDisplayDelay = 100;
98 break;
99 case 1:
100 colorStep = 50;
101 stripDisplayDelay = 50;
102 break;
103 case 2:
104 colorStep = 5;
105 stripDisplayDelay = 500;
106 break;
107 case 3:
108 break;
109 default:
110 break;
111 }
112 }
113 break;
114 default:
115 break;
116 }
117 }
118 switch (bleCarMode)
119 {
120 case MODE_NONE: case MODE_GRAVITY:
121 break;
122 case MODE_ULTRASONIC:
123 upLoadSonarValueToApp();
124 updateAutomaticObstacleAvoidance();
125 break;
126 case MODE_TRACKING:
127 updateAutomaticTrackingLine();
128 break;
129 default:
130 break;
131 }
132 static u8 lastColor[3];
133 switch (stripDisplayMode)
134 {
135 case 0:
136 if (millis() - lastStripUpdateTime > stripDisplayDelay)
137 {
138 for (int i = 0; i < STRIP_LEDS_COUNT; i++) {
www.freenove.com
154 Chapter 6 Bluetooth control [email protected]
www.freenove.com
156 Chapter 6 Bluetooth control [email protected]
break;
case MODE_ULTRASONIC:
oa_CalculateVoltageCompensation();
break;
case MODE_TRACKING:
tk_CalculateVoltageCompensation();
break;
default:
break;
}
}
break;
In the app, four LED display modes can be switched and different color change ranges and color change
periods are set according to different modes. That is, the values of the variables colorStep and
stripDisplayDelay.
switch (commandChar)
{
case ACTION_MOVE:
if (paramterCount == 2) {
motorRun(paramters[1], paramters[2]);
}
break;
case ACTION_CAR_MODE:
if (paramterCount == 1) {
bleCarMode = paramters[1];
switch (bleCarMode)
{
case MODE_NONE: case MODE_GRAVITY:
resetCarAction();
writeServo(OA_SERVO_CENTER);
break;
case MODE_ULTRASONIC:
oa_CalculateVoltageCompensation();
break;
case MODE_TRACKING:
tk_CalculateVoltageCompensation();
break;
default:
break;
}
}
break;
case ACTION_BUZZER:
www.freenove.com
[email protected] Chapter 6 Bluetooth control 157
if (paramterCount == 1) {
setBuzzer(paramters[1]);
}
break;
case ACTION_RGB:
if (paramterCount == 4) {
stripDisplayMode = paramters[1];
switch (stripDisplayMode)
{
case 0:
colorStep = 5;
stripDisplayDelay = 100;
break;
case 1:
colorStep = 50;
stripDisplayDelay = 50;
break;
case 2:
colorStep = 5;
stripDisplayDelay = 500;
break;
case 3:
break;
default:
break;
}
}
break;
default:
break;
}
}
In loop(), the LED is displayed based on the received mode and parameters.
static u8 lastColor[3];
switch (stripDisplayMode)
{
case 0:
if (millis() - lastStripUpdateTime > stripDisplayDelay)
{
for (int i = 0; i < STRIP_LEDS_COUNT; i++) {
strip.setLedColorData(i, strip.Wheel(colorPos + i * 25));
}
strip.show();
www.freenove.com
158 Chapter 6 Bluetooth control [email protected]
colorPos += colorStep;
lastStripUpdateTime = millis();
}
break;
case 1:
if (millis() - lastStripUpdateTime > stripDisplayDelay)
{
strip.setLedColor(currentLedIndex, strip.Wheel(colorPos));
currentLedIndex++;
if (currentLedIndex == STRIP_LEDS_COUNT)
{
currentLedIndex = 0;
colorPos += colorStep; //
}
lastStripUpdateTime = millis();
}
break;
case 2:
colorPos = colorStep;
if (millis() - lastStripUpdateTime > stripDisplayDelay)
{
static bool ledState = true;
if (ledState)
{
strip.setAllLedsColor(paramters[2], paramters[3], paramters[4]);
}
else
{
strip.setAllLedsColor(0x00);
}
ledState = !ledState;
lastStripUpdateTime = millis();
}
break;
case 3:
if (lastColor[0] != paramters[2] || lastColor[1] != paramters[3] || lastColor[2] !=
paramters[4])
{
strip.setAllLedsColor(paramters[2], paramters[3], paramters[4]);
lastColor[0] = paramters[2];
lastColor[1] = paramters[3];
lastColor[2] = paramters[4];
}
break;
www.freenove.com
[email protected] Chapter 6 Bluetooth control 159
default:
break;
}
}
www.freenove.com
160 What is next? [email protected]
What is next?
THANK YOU for participating in this learning experience!
We have reached the end of this Tutorial. If you find errors, omissions or you have suggestions and/or
questions about the Tutorial or component contents of this Kit, please feel free to contact us:
[email protected]
We will make every effort to make changes and correct errors as soon as feasibly possible and publish a
revised version.
If you want to learn more about Arduino, Raspberry Pi, Smart Cars, Robotics and other interesting products
in science and technology, please continue to visit our website. We will continue to launch fun, cost-effective,
innovative and exciting products.
http://www.freenove.com/
www.freenove.com