Blue Hunters: Bluetooth RSSI Locator Robots

ECE 4760, Fall 2017

Jacob Glueck (jng55)

Jane Du (zd53)

Justin Cray (jgc232)

December 6, 2017



Introduction

We built 2 small cars which used Bluetooth Received Signal Strength Indicator (RSSI) measurements to navigate towards a stationary base station. The cars and base station used a Bluetooth Low Energy (BLE) 4.0 module to take the measurements and a PIC32MX250 microcontroller. The cars also used a 3 axis magnetometer as as compass in order to reliably turn, as well as 2 micro 9 g servos to drive. Each unit was powered with 3 AA batteries. Finally, the chassis and wheels of each car were 3D printed.

Video

Design

Chassis

The robots are made from 4 3D printed pieces: 2 wheels, the frame, and the caster in the back. The servos, a 3 AA battery holder, and a perfboard containing all the circuitry are mounted directly to the frame.

The robots where designed in OpenSCAD, and their source code is available in our git repository and below. There are three files, frame.scad, drag.scad, and wheel.scad, for each of the three parts. The main modules are defined in main.scad, and the other files just instantiate them. The following renderings show each part:

Robot chassis
Robot chassis
Caster wheel on back of robot
Caster wheel on back of robot
Robot wheel
Robot wheel

The parts were printed in ABS using Maker Select 3D Printer v2 printers. All parts were printed with a layer height of 0.3 mm, as there was no need for a smooth finish or high tolerances. The parts where sliced with Cura.

Pictures

Full system (base station and 2 robots):

Multiple views of the robots:

Top view Side view
Front view Inside

Electronics

Bluetooth modules

The HM-10 bluetooth modules we bought off Ebay were fakes: they were not made by Jnhuamao 1, and did not come with genuine Jnhuamao firmware. However, they did have real TI CC2541 chips. We realized they were fakes when they did not behave according to the Jnhuamao data sheet (see the data sheets section). Luckily, the hardware on the fake chips is the same as that of the genuine chips, minus an external crystal, and the genuine firmware checks for the presence of the crystal, and works even without it. 2 As such, we reprogrammed the chips with the genuine firmware according to an Arduino forum post:

  1. We soldered wires to the programming pins on the breakout boards, and connected those pins to an Arduino Teensy 3.2. We chose a Teensy because it is 3.3 V as opposed to 5, which would damage the 3.3 V CC2541.

    The pins were connected as follows:

    Name CC2541 Pin Arduino Pin
    DEBUG_CLOCK 7 5
    DEBUG_DATA 8 6
    RESET_N 11 4

    The layout of the HM-10 board is:

  2. We uploaded the CCLoader.ino sketch to the Arduino.
  3. Finally, we ran (in a Windows virtual machine) CCLoader.exe. This program takes 3 arguments:

    CCLoader.exe <COM Port> <Firmware.bin> 0

    The firmware file came from the same Arduino form post, and can be found here.

There is also an excellent YouTube video, which explains the firmware flashing process.

After flashing genuine firmware onto the chip, the next step was to update the firmware to the latest version. The firmware flashed onto the board was version 540, but Jnhuamao had (at the time we did this project) released version 603. 3 They also provide instructions on how to upgrade the firmware. The basic process is:

  1. Connect the HM-10 module to a computer using a 3.3 V FTDI to USB adapter. Then, use PUTTY to establish a serial session (9600 baud, 8N1). Send the chip AT; if it is connected properly, it will respond with OK.
  2. Send the chip AT+SBLUP to put it in firmware update mode. It will respond with OK+SBLUP. Terminate the PUTTY session.
  3. Run the HMSoft.exe program distributed in the firmware update download. We ran it in a Windows virtual machine because we did not trust it.
  4. Select the proper port and firmware file using the software, and hit “Load Image”. The software should handle the rest!
  5. To make sure it worked, establish a serial connection again using PUTTY. Send AT+VERS? to query the chip for version information.

Software

The robots were programmed in C, using the MPLAB X IDE v4.0, with the XC32 v1.4 compiler and the PIC 32 Legacy Peripheral Library (plib). The full source code is available in our git repository and below. The code is divided into 5 main units:

BLE

The BLE module used UART, at 9600 baud 8N1. We used UART1 on the PIC for communicating with the BLE module, and used UART2 for communicating with the computer (for debugging). The BLE files define a series of macros and PT_THREAD functions for printing characters and reading lines in a non-blocking fashion using protothreads. All of the PT_THREAD functions can be spawned with PT_SPAWN to run them.

The main.c file contains a thread which does all the communication with the Bluetooth chip using these functions. The commands it sends to the chip are:

One interesting thing to note about the chip is that commands do not have to end with newlines or carriage returns. However, if sent, the chip will ignore them.

IMU

The PIC commmunicates with the IMU via I2C. The IMU includes a breakout board for the QFN MPU-9250 module, which itself includes 2 dies. One contains the 3-axis gyroscope and 3-axis accelerometer, which were not used in this project, and the other die is the AK8963 3-axis magnetometer (compass).

It is connected to the rest of the MPU module via an auxillary I2C bus, so it is not connected to the MPU’s main I2C bus by default. While the accelerometer and gyroscope registers can be read after powering up the IMU, the compass also needs pass-through mode to be enabled on the IMU to make it an accessible slave on the I2C bus.

Some useful functions as defined in imu.h are described below:

Initializing the IMU involves opening the I2C module, and then configuring the IMU.

  1. We open the I2C2 module; I2C1 uses pins already used by the connections to the Bluetooth module. We open it with the baud rate generator value BRG = (Fpb / 2 / baudrate) - 2 = 4e7 / 2 / 4e5 - 2 = 48, as specified for OpenI2C2() in the peripheral libraries.
  2. Pass through is enabled, interrupts for data ready are enabled, the IMU as an I2C master function is disabled, and the sensor is powered up.

This enables the PIC to talk to the AK8963. The AK8963 has several modes of operation, and the chip must be set to power-down mode before switching to other modes. We read compass values with single measurement mode, as specified below:

  1. Set the compass to single measurement mode in 14 bit resolution.
  2. Read the 6 data registers (X low, X high, Y low, Y high, Z low, Z high)
  3. Read the Status 2 register to check for magnetic sensor overflow. Without reading this register, the read is not considered complete and further reads will fail.
  4. Wait; if the IMU is read too frequently, it will not have enough time to take measurements.

Additional helper methods used in I2C were defined in imu.c. These are largely based on the files from the self-balancing robot.

In order to calibrate the compass, the robots spun in place when powered on. They recorded the maximum and minimum values for each axes, and used that data to scale and center the magnetometer readings.

Servos

For the drive systems, we used the FS90R servos. These servos are continuous rotation servos with a stall torque of 1.5 kg-cm. Continuous rotation servos operate based on PWM duty cycle; since servos operate at a pulse width of 1 to 2 ms out of 20 ms, we used a timer with a prescaler of 32 and a maximum count of 25600, and set the pwm at numbers ranging from 1280 to 2560 (corresponding to the right pulse width).

A 50% duty cycle means the servos are still. A less than 50% duty cycle means the servo turns clockwise and a greater than 50% duty cycle means the servo turns counter-clockwise. To implement the PWM, we use the output capture on the PIC. We set the duty cycle using the built in timers. We set a max and min duty cycle value which were experimentally derived. The middle point is the average of the two. Tank drive is used to control the system where both wheels are driven forward or point turns where one wheel is turned in one direction and one is turned in the other direction.

Protothreads

While the provided protothreads library was very helpful, it did not work correctly when used in multiple compilation units. The reason for this was that it defined variables and functions in the header file, so if multiple source files included pt_cornell_1_2_2.h, linking would fail with duplicate symbol definitions. Furthermore, if multiple files included config_1_2_2.h, linking would fail with the obscure error:

section `.config_BFC00BF4' will not fit in region `config2'

This happened because if multiple compilation units included #pragma config directives (which they did by including a #include "config_1_2_2.h" directive), then the linker would try to assign too many symbols to the configuration region.

The fix to this was twofold:

  1. We modified protothreads to have both a header and source file, with definitions only in the source file.
  2. We only included config_1_2_2.h in the main C file, and moved all macro definitions to the protothreads header.

The updated versions of protothreads can be found in Appendix B.

Gradient descent

The algorithm for deciding what path to follow is a basic version of gradient descent. The following image represents the decision-making state machine, where the starting state is Measure rssi twice, take average.

We also implemented and tested the following improved version that allows for correction; a car that has just moved forward and detected a weakened signal does not know whether the beacon to its left or right. If after turning, the signal is still weaker, it has picked the wrong turn. This decision process corrects this (same starting state: Measure rssi twice, take average):

It did not prove much more accurate than randomized gradient descent, largely due to noisy readings from IMU and Bluetooth signal strength. As such, we used the simplified version.

Testing

BLE

Once we flashed the Bluetooth chips with the proper firmware, we used the LightBlue app to test communications. Using the app, we could discover the Bluetooth chips, and send and receive data. By initially using a the iPhone app, which was known to work, we could debug the Bluetooth chips in isolation. Once that worked, we had the chips communicate with each other. Finally, we had the chips take RSSI measurements.

We also experimented with RSSI, as described in results. This data validated the effectiveness of RSSI as an approximate metric for distance measurement, though confirmed that it would be highly variable.

IMU

Servos

We tested the functionality of servo code by testing individual functionality on both the hardware and software side. We tested the servo code in stages, first implementing control at a fixed speed and then implementing directional motion and lastly turning. This allowed us to verify our parts of the code and the functionality of the servos.

Whole system

Results

In most cases, at least 1 of the 2 robots successfully made it to the base station. However, it was not as reliable as we initially hoped. One of the main reasons for this was the noise in RSSI measurements.

We expected that RSSI would vary with distance according to the following relation:

RSSI = A − 10nlog(d)

where A and n are RF propagation parameters in dBm, d is distance in meters, and RSSI is the measured RSSI in dBm. 4 We experimented with RSSI measurements to determine how well they worked by taking 2 Bluetooth modules, and measuring the RSSI while changing the distance between them. One remained stationary on the floor and the other was moved away from it 1 floor tile (each floor tile is a 1 foot square) at a time. At each point, we took 3 RSSI measurements and averaged them. The graph below displays the results:

While the chip reported RSSI in units proportional to dBm, and we measured distances in feet, not meters, we could still use the above formula without worrying about unit conversions. The constants A and n, provided we determined them empirically based on the data, would encode the conversions. As such, we fit the data using the above formula with A = −48 and n = 3, resulting in the blue curve above. While the general shape of the curve matches, there is significant noise in the averaged RSSI data. Furthermore, when we tried to reproduce the measurements, we could not do so precisely – it seemed to even depend on where our feet where! See Appendix B for the source data for the table.

Despite how noisy the RSSI measurements where, the robots were still able to perform a reasonably accurate gradient descent. In most cases, at least one of the 2 robots would find the beacon in a matter of minutes.

Conclusions

This assignment was an interesting exploration into short-range distance determination using Bluetooth, a generally unconventional approach. We were warned beforehand about the difficulties in using Bluetooth RSSI, a measurement particularly susceptible to multipath interference, as a distance sensor – both in the papers and reference materials researched before implementation, as well as by course staff in the early stages of our project. We worked with the course staff to simplify and stratify our project into workable milestones. Our final project is a reduced version of our original plan.

Our hunting bots worked reliably when they stayed within roughly 1 m of the beacon. After this, they entered the land of shallow gradients: the signal strength from the beacon (already noisy) would not change very much, and often only due to noise. The hunting bots normally could never recover from this. Our bots also worked better in larger, more open spaces, preferably without metal structures like tables or doors nearby. Both of these are reasonable given the operating range of BLE 4.0.

We reused some of the code from the Self-Balancing Robot as cited in our references section, and explained in IMU. The rest of the design is ours, and is not an infringement on intellectual property. We also used the Bluetooth firmware flashing technique we discovered on the Arduino forums.

We did not reverse-engineer any technology, and did not encounter any issues with trademarks or patents. We did not have to sign non-disclosure to get a sample part. We hope to further polish our findings and report, and will aim to publish them in a print magazine, ideally as a part of ECE 4920.

There are many potential avenues for improvements or further development. In addition to more circumstantial difficulties encountered during the project work period (such as extremely unbalanced servos, where one always ran faster than the other), two areas of potential improvement are as follows:

IEEE Code of Ethics

Our project, as well as the design and creation project thereof, adheres to the IEEE Code of Ethics. The project itself is relatively small and physically self-contained; it did not have any immediate impact on the environment or safety and health of potential users, we the creators, or any others. We chose the project’s topic out of interest and for a challenge, without any conflict of interest. Our report is honest and realistic; none of our data is fabricated, and our conclusions reflect our hard findings. We did not accept any form of bribery.

The project investigated the use of an emerging and popular technology (BLE) in a new application (distance sensing). We consistently received and built upon advice from our TAs and professor Bruce Land, and cite the work we used in the basis of our project.

Additionally, neither we nor our project presented any act of discrimination, and our project does not injure others in any way. We assisted our colleagues (both fellow group members and other classmates) when the occasion arose, such as by offering help debugging or lending a spare module before a demo.

Overall, our project complies with the IEEE Policies, 7.8 Code of Ethics.

Appendices

Appendix B: Source Listing

Our source code can be found on Github. Each file can also be found below:

Code

CAD

Sources
STL

RSSI data

Distance (feet) RSSI A RSSI B RSSI C RSSI Average Expected RSSI
1 -48 -48 -48 -48.00 -48.00
2 -56 -58 -52 -55.33 -57.03
3 -66 -66 -68 -66.67 -62.31
4 -64 -68 -65 -65.67 -66.06
5 -60 -70 -64 -64.67 -68.97
6 -80 -80 -76 -78.67 -71.34
7 -80 -79 -65 -74.67 -73.35
8 -68 -66 -72 -68.67 -75.09

Appendix C: Schematics

Appendix D: Bill Of Materials

Name Manufacturer Part Number Vendor Vendor Part Number Quantity Unit Cost Total Cost
BLE 4.0 Module (TI CC2541) HM-10 Ebay 142425748901 3 $3.99 $11.97
FEETECH FS90R (pack of 2) Continuous Rotation Robotic Servo FS90R Amazon B074BFQC3Q 2 $12.39 $24.78
HiLetgo 9-Axis 9 DOF 16 Bit Gyroscope Acceleration Magnetic Sensor MPU-9250 Amazon B01I1J0Z7Y 2 $8.49 $16.98
Small board Lab rental 3 $5.00 $15.00
PIC32MX250F128B PIC32MX250F128B Lab rental 3 $5.00 $15.00
6-inch Protoboard Lab rental 3 $2.50 $7.50
Male header pins Lab 129 $0.05 $6.45

Total: $97.68

Appendix E: Work Distribution

References

Data sheets

Code and designs borrowed from others

Other


  1. Jnhuamao is the company which makes the HM-10 module, along with other Bluetooth modules. Their English website is: http://www.jnhuamao.cn/bluetooth.asp?id=1.

  2. http://forum.arduino.cc/index.php?topic=393655.msg2709528#msg2709528.

  3. Jnhuamao’s firmware download page http://www.jnhuamao.cn/download_rom_en.asp?id=1#.

  4. L. Peneda, A. Azenha and A. Carvalho, “Trilateration for indoors positioning within the framework of wireless communications,” 2009 35th Annual Conference of IEEE Industrial Electronics, Porto, 2009, pp. 2732-2737.

    doi: 10.1109/IECON.2009.5415423

    URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=5415423&isnumber=5414636

  5. See the top of page 8 of http://www.ti.com/lit/ds/symlink/cc2541.pdf for compliance information.