This is a short article explaining how to integrate an HC-O5 Bluetooth module into embedded robotics projects.
Costing less than $3, the nrf24lo1+ radio module is definitely the cheapest solution to most tasks. However, taxing and high pressure tasks such as rapid communicating with a moving object is beyond its capacity as I discovered while creating a tricopter. For these high performance situations, the 10 dollar HC-05 is a promising alternative. After reading this article, controlling robots from a computer while receiving real-time feedback will be easier and more functional than ever.
Note: I needed to do this for a tricopter so I had performance, not cost in mind.
Materials:
1. Arduino Mega (I used an Arduino Mega because of its built in Serial 2 and Serial 3. Using an Arduino Uno with the software serial library is another alternative, but not one I could choose from since software serial hogs necessary timers needed to control servos and ESCs)
2. 2 HC-05 Bluetooth modules (In truth, to establish bidirectional communication with an Arduino and a computer only requires one module. I used two because I needed two separate com ports.
3. Male to Female Jumper wires
Total Cost: ~40 dollars
Part 1: Circuit
With only 4 pins, this is an exceptionally easy circuit to create.
Here is the circuit I created using Fritzing:
Note: Make sure the rx and tx are crossed. That is HC-05 tx should be connected to Arduino rx, and HC-05 rx should be connected to Arduino tx.
Part 2: Code
I intended this code to be versatile and useful: almost like a library. However since it is so simple and only has a few functions, creating a library will probably not be very helpful. Here is the code to send multiple integers back and forth and parse them.
How to use this code:
This code was originally intended to be used for a tricopter (as one can guess from the variable names). To use this code for some other purpose, replace the variables Throttle, Yaw, Pitch, Roll and Sensor_A, Sensor_B, Sensor_C with your own variable names. Be sure to replace all instances of the variable. Add your own methods to gather sensor measurements and other methods to control actuators with the received Bluetooth data. If you understand the logic, it will not be hard to expand the bandwidth to transfer more than 4 variables. Furthermore, a quick google search on “processing proControll library” will help you edit the processing code and use the buttons on the joystick.
Part 3: Explanations
The code is commented, but even so the logic used to parse the incoming integers may be confusing. Here it is explained:
The most important parts of the software are listed below:
int w = constrain(int(a),0,100); //Set the scale 0-100
int x = constrain(int(b),0,100);
if (control % 2 == 0) {
out[0]=byte (w);
}
if (control % 2 ==1) {
out[0]=byte(x+101);
}
int y = constrain(int(c),0,100);//Set the scale 0-100
int z = constrain(int(d),0,100);
if (control % 2 == 0) {
out[1]=byte(y);
}
if (control % 2 ==1) {
out[1]=byte(z+101);
}
This code is for the transmitter. It sends data by first trying to minimize the number of packets it must send. And then trying to fit the maximum amount of information within those packets. For example here, processing can send a byte array of 2 elements. Each byte can hold data ranging from 0-256. But since the program needs to send 4 variables of max size 100, it needs to send 2 packets. But this is not as easy as it sounds. All it takes is one corrupt transmission or a delay and the two packets will be mixed up–a huge error. For that reason one packets values will be shifted up by a 101. This will be corrected later. All the Arduino has to do is check if the value is above 100 and then it know what package it came from.
void decodeBluetoothData() {
//////////////////////////////////////Read from first buffer and extract two values
if(numericalBuffer[0]<=100) {
joystick[0] = numericalBuffer[0];
}
else if(numericalBuffer[0] >= 101) {
joystick[1] = numericalBuffer[0]-101;
}
///////////////////////////////////////Read from second buffer and extract two values
if(numericalBuffer[1] <= 100) {
joystick[2] = numericalBuffer[1];
}
else if(numericalBuffer[1] >= 101) {
joystick[3] = numericalBuffer[1]-101;
}
/////////////////////////////////////////Check the delay in transmission
if(millis()-bluetoothLastUpdated > COM_DELAY_THRESHOLD) {
//TODO : Send Communication Error Message and shut down device
}
}
This code is from the receiver. It receives data by first gathering the raw data in correct order and storing it in a buffer. Next for both elements in the buffer, it checks if it came from the first or second packet (by checking if it is above or below 101). After checking, the Arduino correctly maps the value back into the correct scale and saves it to be retrieved later.