Projects Research & Design Hub

Build a Bluetooth Accelerometer Car

Interested in building a gesture-based, remote-controlled vehicle? Try replicating the AccelCar, which is a compact vehicle that a user controls by tilting a remote. Tilt data is transmitted from the remote to the vehicle via Bluetooth.

  • How to build a gesture-based, remoted controlled car

  • How to development the circuitry

  • How to configure the MCU’s communication over I2C

  • How to make use of the Bluetooth module (HC-05)

  • How to calculate and the map the tilting angles for the romote

  • How to design and build the physical car

  • Microchip (formerly Atmel) Atmel ATmega1284P MCU

  • InvenSense MPU-6050 accelerometer/gyroscope sensor

  • Bluetooth transceiver (HC-05)

  • Four AA batteries

  • TB6612FNG motor driver breakout board from Sparkfun

  •  Peter Fleury’s I2C library for AVR

For our final project for Cornell University’s ECE 4760 class, we built a car and a Bluetooth remote that controls the car’s movement and speed by the tilt angle of the remote (similar to a Nintendo Wii remote). The project consists of a car and a remote that we both made and customized (see Photo 1). Figure 1 shows the essential components of the car and remote. The remote comprises a Microchip (formerly Atmel) ATmega1284P microcontroller with a prototype board designed by Dr. Bruce Land, an InvenSense MPU-6050 accelerometer/gyroscope sensor, and a Bluetooth transceiver (HC-05) to transmit commands to the car. The microcontroller gets acceleration data from the accelerometer and calculates the angle of tilt of the remote and sends these angles through Bluetooth to the car. On the car side, the microcontroller receives the angle measurements through Bluetooth from the remote and translates these angle measurements into a direction and speed for the left and right motors.

Photo 1
Top view the AccelCar
Figure 1
Components of the car and remote

Now that you have a general idea of how the remote and car work together, let’s consider the actual hardware of the two components. The remote includes an HC-05 Bluetooth module that is powered by 5 V and connected directly to the ATmega1284P microcontroller’s RX and TX pins to communicate through UART (see Figure 2). The HC-05 on the remote was configured so that it would pair automatically with the other HC-05 Bluetooth module on the car and vice versa.

Figure 2
The remote’s circuitry
(Click to enlarge)

There is also a GY-521 breakout board for the MPU-6050, which is the accelerometer sensor used to measure the tilt angle of the remote. The SCL and SDA pins are pulled up to 5 V with a 4.1-kΩ resistor. The AD0 pin is pulled down to ground to ensure that the slave address of the board defaults to 0x68. If it was pulled up to 5 V, the slave address would otherwise be 0x69. In addition, there is a normally open button/switch connected to port D2 pulled down to ground for the user’s benefit. When the switch is closed, the microcontroller sends out a stop command in case the user wanted to stop the car or stop the car or reorient the remote/car without turning off either.

Figure 3

The car’s circuitry 
(Click to enlarge)

The main components of the car circuitry are the ATmega1284P, H-Bridge breakout board, motors and flyback diodes, an HC-05 Bluetooth module, and a voltage level converter (see Figure 3). Notice that there is a 6-V power source (four AA batteries) for just the motors and a 9-V battery to power just the microcontroller. The DC motors that were used are rated for 3 to 6 V, so the four AA batteries are enough to move them.

The TB6612FNG motor driver breakout board we used can supply up to 1.2 A for the motors, which is enough for the DC motors to produce enough torque to move the entire car. It also contains two H-bridges, which we needed to allow the car to move forward, move backward, and turn by turning the motors in a clockwise or counterclockwise direction. The breakout board datasheet contains specifications for different modes of operation: clockwise/counterclockwise turning of motor, change of speed, and stopping the car (see Table 1). We had to follow these specifications to control our motors. Ports A0 to A4 of the microcontroller control the direction in which the motor should be spinning (clockwise or counterclockwise) by controlling the voltage levels of the AIN or BIN pins of the H-bridge breakout. The STBY pin is always high when we want the motors turning. The two PWM signals coming from the microcontroller (ports B3 and B4) control the speed of each motor, and they go into the PWMA and PWMB pins of the motor driver board. The pins A01–A02 and B01–B02 are outputs of the motor driver to apply a voltage across the DC motors.

Table 1
Table of inputs for modes of TB6612FNG motor driver

The car also features a Bluetooth transceiver that receives commands coming from the other Bluetooth module on the remote. The Bluetooth transceiver is directly connected to the microcontroller’s RX and TX pins to communicate through UART. However, for this circuit, we have to read the STATE pin to see if the transceiver somehow lost connection with the other module. We measured that the STATE pin outputs 3.3 V when the Bluetooth transceiver is paired with another device and 0 V when it is not paired with anything. We want the car to automatically stop if it loses communication with the master Bluetooth control, and the microcontroller can read this change in voltage as an interrupt and stop the car. However, the microcontroller cannot register the digital level of a pin as HIGH unless the actual voltage on the pin is around 4 V or higher, so we had to use a voltage level shifter to shift the 3.3 to 5 V so the microcontroller could detect the change in voltage. The voltage level shifter breakout board is relatively easy to use, and you have to supply it with 5 and 3.3 V (on the HV and LV pin, respectively) for it to output 5 V on pin TX0 when the input (pin TX1) is 3.3 V and output 0 V when the input is 0 V.

The remote comprises two main hardware components: the accelerometer/gyroscope breakout board and the HC-05 Bluetooth transceiver. The remote’s software therefore involves integrating the information received from and sent to these two components through the microcontroller.


The accelerometer board utilizes I2C protocol to communicate the values of the acceleration vector of the board in xyz-space. Therefore, we had to set up an I2C library in our code for the remote to do basic I2C signals such as the start and stop signals. We utilized Peter Fleury’s I2C library for AVR (, which contained the basic functions. We also referenced Brian Harding’s I2C code from his Spring 2011 project for ECE4760, FaceAccess, an example of using Peter Fleury’s library.

To get the accelerometer to return data to the microcontroller, it was very important for us to read from the MPU-6050 datasheet and register map, which had all of the relevant information for the sequence of commands we should send out to the accelerometer in order to get information or write information to the board. Refer to Table 2 to understand how I2C worked with the accelerometer board. The essential I2C terms are: S (Start Condition: SDA goes from high to low while SCL is high); AD (Slave I2C address); W (Write bit, 0); R (Read bit, 1); ACK (Acknowledge: SDA line is low while the SCL line is high at the ninth clock cycle); NACK (Not-Acknowledge: SDA line stays high at the ninth clock cycle); RA (MPU-60X0 internal register address); DATA (transmit or received data); and P (Stop condition: SDA going from low to high while SCL is high).

Table 2 
Several I2C commands are needed to write/read a given register on the gyroscope/accelerometer module. 

The HC-05 Bluetooth module is meant to be plug-and-play using the microcontroller’s UART pins. While we had some issues setting up the modules, once the hardware was set up, sending information over the Bluetooth modules was pretty intuitive. Refer to Appendix E in the “HC-05 Bluetooth” section of our project webpage ( to get specific instructions for how to configure the module. From the remote, we sent ordered pairs of integers, which were the tilt angle on the x-axis and the tilt angle on the y-axis of the accelerometer. The Bluetooth module on the car receives those ordered pairs and scans in the angles so that they can be converted to appropriate PWM values for the motors.

We actually had some trouble reading data coming in from Bluetooth (e.g., getting garbage data, getting only some values, etc.). When we were sure that the issue was not in hardware (i.e., baud rate, pin connections), we fixed the software by ensuring that the format/data type of the information coming in was the same as what was being sent. We also used a multitasking kernel called TinyRealTime to schedule different tasks that needed to be performed like motor control and reading in data coming in through Bluetooth without interference.[1] We found that the ordered pairs being sent over Bluetooth could not have a blank space as a delimiter, or we could not compare the strings coming in correctly. In other words, we sent (x_angle,y_angle) instead of (x_angle,<space>y_angle).

To calculate the angle at which the remote control was oriented, we used the following equations:

θX and θY are the pitch and roll of the accelerometer (due to how the accelerometer is oriented on the board), and A* is the measured acceleration data from the accelerometer module for the specified axis.[2] Since the atan function in C’s “math.h” library returns the inverse tangent in radians, the 57.295 factor simply converts the value from radians to degrees.


Once the tilt angle of the remote could be easily accessed by the microcontroller, we needed to figure out how to change the car’s speed and direction based on the tilt angles. We decided to map the tilt angles linearly to the speed of the motors. Since the speed is controlled by the duty cycle of the PWM signal going from the microcontroller to the motor driver, this simply meant mapping 0–90 to 0–255. In addition, the angles are signed (i.e., the X-angle is negative if the remote is tilted forward and positive if the remote is tilted backwards), so the signs of the angles determined whether the wheels should rotate forward or backward. Negative angles simply translated to spinning the wheel in the opposite direction; we never set OCR0A or OCR0B to negative values. Thus, if the remote was only tilted forward or backward (with no side-to-side tilting), the PWM values for the left and right motors (OCR0A and OCR0B) would be:

We determined that, in order have a quick turn for a large pitch and slower turn for a smaller pitch, the PWM values would have to be modified from the OCR0A/B calculated from the equation above. Furthermore, the tighter the turn, the greater difference we would need between the speed of the two wheels. We decided that for a left turn, we would keep the right wheel speed proportional to the pitch while also decreasing the left wheel speed. In short, the greater the sideways angle of the remote, the greater the decrease for the left wheel, and vice versa for a left turn.

If the remote was tilted sideways at its maximum angle, we want the tightest turn that we could get, so the wheels would be traveling in opposite directions (one forward, one backward). Thus, if the car was tightly turning right, the amount to subtract from the left wheel speed would be twice of what it originally was. If we wanted the car to turn less tightly, it would correspond to a smaller sideways tilt, and we would simply subtract less. So we calculate the OCR0* for the slower motor as follows:

θY is the angle of the remote’s roll. θMAX is the tilt angle at which we wanted the car to have its tightest turn.

Figure 4 describes how the wheels turn relative to the rest of the car when the car is moving forward, moving backward, making a sharp left turn, and making a sharp right turn. The two-tire diagrams show the direction of movement for each tire when viewed from the back of the car.

Figure 4
Wheel direction for overall car direction

The remote also has an “emergency stop” push button, which can be used to stop the car remotely. When this button is held down, it pulls the interrupt pin of the MCU (pin D.3) HIGH; when it is released, this pin is LOW. Thus, our remote code enables the external interrupt and has one interrupt service routine (ISR). The ISR is triggered on either a positive or negative edge of D.3, so when the button is pressed and held down, the ISR sets a flag that says that the car should stop. When the button is released, the ISR clears that flag. This flag is checked each time before the Bluetooth module sends a message over UART, to see if the message sent should be the actual angles read in by the accelerometer or just zeros.


The program on the car involves reading in data from the Bluetooth module (see section above for details), then mapping the angles read in (through UART) from the module to PWM signals. These two steps are done in two separate tasks on TinyRealTime so that angles can be read in parallel to the PWM values being updated. The mapping from angle to PWM value simply implements the math discussed above.

The car also has its own emergency stop, which is activated when a pin connected to the STATE pin of the HC-05 becomes LOW, signaling that the Bluetooth modules on the car and remote have become unpaired. This part is done by polling, since checking the state of one pin does not take much extra time and because we can afford to wait a couple extra milliseconds between polls due to the slow speed of the car.


Once most of the software and hardware was set up, we had to construct the physical car. The physical design of the car involved creating a car chassis to hold all of the electronics and batteries as well as have it easily mount with the motors and wheels. The car’s body is 7″ × 6.25″, which is just wide and long enough to fit the two motors, the soldered board, and the microcontroller. The chassis was made of plywood and holes were drilled to allow easy mounting of the two DC motors and the third ball bearing wheel. Plywood was also strong enough to hold the microcontroller, soldered car circuit, motors, wheels, and 4-AA battery pack. Some components were significantly heavier than others, so we had to distribute the weight evenly throughout the car to prevent flipping. The battery pack was placed between the two DC motors to keep the weight in the center. Photo 2 shows the bottom of the car.

Photo 1
Top view of our car

After the car and remote were tested and finalized, we ran the car outside our lab. While we were demonstrating the car, we handed the remote off to passersby so they could navigate the car after a couple of minutes. (Refer to the YouTube videos listed at the end of this article to see how the car works.) After testing, we found we were able to control the car from a distance of over 100 feet! Overall, the construction of our car was trickier than its operation, which has satisfied our goal of making a toy car that can race anywhere, anytime.


Some ideas that could be implemented for the future would be to possibly make more than one car so you can easily race with another person, just like Mario Kart. Another feature that could be implemented is programming an Android smartphone to send out the commands through Bluetooth and reconfigure the Bluetooth modules so anyone can connect to the cars. Most smartphones have an accelerometer built in, and there is a lot of documentation online for how to interface with the accelerometer and Bluetooth, since the Android community is very open-source. These two improvements can make this car easily accessible by all people and flexible in terms of hardware. If the remote were to break, you would have to remake it, but if the car was programmed so it can accept commands from any Bluetooth serial connection, you can avoid having to rebuild a remote and use your smartphone instead. You would only need to ensure that it sends the commands in a certain format, and the car would operate the same way. 

[1] B. Land, “Cornell University ECE4760: A preemptive kernel for Atmel Mega1284 microcontrollers,”
[2] STMicroelectronics, “Tilt Measurement Using a Low-g 3-Axis Accelerometer,” AN3182, 2010,

P. Fleury, “AVR-GCC Source Examples,” 2006, Harding and C. Jubinski, “FaceAccess: A Portable Face Recognition System,” 2011,
InvenSense, “MPU-6000 and MPU-6050 Product Specification,” Revision 3.1, PS-MPU-6000A-00, 2011.
B. Land, “Bluetooth Robot,” 2014,
B. Land, “Prototype Board for Atmel Mega644,”
C. Soong & S. Wang, “AccelCar,” 2014,
STMicroelectronics, “Tilt Measurement Using a Low-g 3-Axis Accelerometer,” Rev 1, AN3182, 2010,
S. Wang, “AccelCar Maneuverability Test,” 2014,

ATmega1284 Microcontroller
Microchip Technology (formerly Atmel) |
MPU-6050 MEMS MotionTracking Device
InvenSense |
Dual TB6612FNG motor driver
SparkFun Electronics |


Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
+ posts

Christine Soong ( is studying Electrical and Computer Engineering at Cornell University. Her interests include analog circuit design, digital VLSI design, and the development of electronics for aviation and aerospace systems.

Shela Wang ( graduated from Cornell University with a major in Electrical and Computer Engineering. Her interests include mobile app development and embedded systems.

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Build a Bluetooth Accelerometer Car

by Christine Soong and Shela Wang time to read: 12 min