Intro: Gesture Controlled Rover Using an Accelerometer and an RF Transmitter-Receiver Pair
Ever desired building a rover that you could steer by simple hand gestures but could never muster the courage to venture into the intricacies of image processing and interfacing a webcam with your microcontroller, not to mention the uphill battle to surmount poor range and line-of-sight issues? Well, fear not...for there’s an easy way out! Behold, as I present to you the mighty ACCELEROMETER! *ba dum tsss*
An accelerometer is a really cool device that measures gravitational acceleration along a linear axis. It represents this as a voltage level fluctuating between ground and the supply voltage, which our microcontroller reads in as an analog value. If we apply our brains a bit (just a little math and some Newtonian physics), not only can we use it to measure linear motion along an axis, but we can also use it to determine the angle of tilt and sense vibrations. Don’t fret! We won’t be needing the math or the physics; we’re just gonna be dealing with raw values that the accelerometer spits out. In fact, you actually don’t need to concern yourselves much regarding the technicalities of an accelerometer for this project. I will just touch upon a few specifics and elaborate only as much as you need to understand the big picture. Although, if you are interested in studying its inner mechanics have a look here.
You just need to keep this in mind for now: an accelerometer is the gizmo (often coupled with a gyroscope) that opens doors to all those motion sensor games that we play on our smartphones; a car racing game for instance, where we steer the vehicle simply by tilting our devices in either direction. And, we can mimic this very effect by sticking an accelerometer (with a few auxiliaries, of course) onto a glove. We just put our magic gloves on and tilt our hands left or right, forward or backward and see our rovers dance to our tunes. All we’re required to do here is to translate the accelerometer’s readings to digital signals that the motors on the rover can interpret and devise a mechanism to transmit these signals to the rover. To accomplish this, we call upon the good ol’ Arduino and its aides for today’s experiment, an RF transmitter-receiver pair operating at 434MHz thereby yielding a range of about 100-150m in open space, which also saves us from line-of-sight issues.
Quite a nifty hack, eh? Let’s dive in…
Step 1: Gather Your Supplies
|• Arduino Nano||x1|
|• Accelerometer (ADXL335)||x1|
|• 5V DC Motor + Wheels||x2 each|
|• Bovine wheel*||x1|
|• L293D Motor Driver + 16 pin IC socket||x1 each|
|• 434 MHz RF Transmitter||x1|
|• 434 MHz RF Receiver||x1|
|• HT-12E Encoder IC + 18 pin IC socket||x1 each|
|• HT-12D Decoder IC + 18 pin IC socket||x1 each|
|• LM7805 Voltage Regulator||x1|
|• Pushbutton Switch||x2|
|• Red LED + 330O resistor||x2 each|
|• Yellow LED + 330O resistor||x1 each|
|• Green LED + 330O resistor (optional)||x4 each|
|• 51kO and 1MO Resistors||x1 each|
|• 10µF Radial Capacitors||x2|
|Batteries, Battery Connectors, USB Cable, Jumper Wires, Female Headers, 2-pin Screw Terminals, PCB, Chasis and your usual Soldering Accessories|
If you’re wondering why we’re using a bovine wheel, the thing is that, the RF transmitter and receiver modules have only got 4 data pins, which means that we can only drive 2 motors and hence the use of a bovine wheel to support the structure. However, if you feel that your rover would look a tad more cool with four wheels, don’t worry, there’s a work around! In this case, just scratch the bovine wheel off the list and add another pair of 5V DC motors, accompanied by a wheel each, and look out for the simple hack discussed towards the end of step 3.
Finally, for the bravehearted, there’s scope for another slight modification in design, which kinda involves engineering your own Arduino. Head over to the bonus section in next step and see for yourself. You’ll also need a few extra supplies: an ATmega328P, a 28pin IC socket, a 16Mhz crystal oscillator, two 22pF ceramic caps, another 7805 voltage regulator, two more 10μF radial caps and 10kΩ, 680Ω, 330Ω resistors, and yes, minus the Arduino!
Step 2: Wire Up the Transmitter
We’ll break the project down to two constituents: the transmitter and the receiver circuits. The transmitter consists of an accelerometer, an Arduino and an RF transmitter module coupled with an HT-12E encoder IC, all wired up as per the attached schematic.
The accelerometer, as introduced earlier, serves to recognize our hand gestures. We’re gonna be using a three-axis accelerometer (basically three single-axis accelerometers in one) to meet our needs. It can be used to measure acceleration in all three dimensions, and as you might have guessed, it yields not one, but a set of three analog values relative to its three axes (x, y and z). Actually, we only need the acceleration along the x and y axes since we can only drive the rover in four directions: froward or backward (i.e. along the y axis) and left or right (i.e. along the x axis). We would’ve needed the z axis if we were building a drone, so that we could also control its ascend or descend by means of gestures. In any case, these analog values that the accelerometer yields must be converted to digital signals in order to be able to drive the motors. This is taken care of by the Arduino which also transmits these signals, upon conversion, to the rover via the RF transmitter module.
The RF transmitter has only got one job: to transmit the “serial” data available at pin 3 out the antenna at pin 1. This advocates the use of the HT-12E, a 12 bit parallel-to-serial data encoder, which collects upto 4 bits of parallel data from the Arduino at the lines AD8 through AD11, thereby enabling us to make room for upto 24=16 different I/O combinations as opposed to the single data pin on the RF transmitter. The remaining 8 bits, drawn from the lines A0 through A7 on the encoder, constitute the address byte, which facilitates pairing the RF transmitter with a corresponding RF receiver. The 12 bits are then put together and serialized, and passed on to the data pin of the RF transmitter, which in turn, ASK-modulates the data onto a 434MHz carrier wave and shoots it out via the antenna at pin 1.
Conceptually, any RF receiver listening at 434Mhz should be able to intercept, demodulate and decode this data. However, the address lines on the HT-12E, and those on the HT-12D counterpart (a 12 bit serial-to-parallel data decoder), allow us to render an RF transmitter-receiver pair unique by routing the data only to the intended receiver thereby limiting communication with all others. All that’s required of us is to configure the address lines identically on both fronts. For example, since we’ve grounded all the address lines for our HT-12E, we must do the same for the HT-12D at the receiving end or else the rover won’t be able to receive the signals. This way, we can also control multiple rovers with a single transmitter circuit by identically configuring the address lines on the HT-12Ds at each of the receivers. Or, we could put on two gloves, each affixed with a transmitter circuit containing a distinct address line configuration (say, one with all address lines grounded and the other with all held high, or one with one line grounded while the remaining seven being held high and the other with two lines grounded while the remaining six being held high, or any other combination thereof) and each steering multiple identically configured rovers. Play the maestro at an android symphony!
One important thing to note while assembling the circuit is the value of Rosc. The HT-12E has an internal oscillator circuit between pins 15 and 16, which is enabled by connecting a resistor, called Rosc, between those pins. The value selected for Rosc actually determines the oscillator frequency, which may vary depending upon the supply voltage. Selecting an appropriate value for Rosc is crucial to the functioning of the HT-12E! Ideally, the HT-12E’s oscillator frequency should be 1/50 times that of the HT-12D counterpart. Therefore, since we’re operating on 5V, we chose 1MΩ and 51kΩ resistors as Rosc for the HT-12E and HT-12D circuits respectively. Should you plan to operate the circuits on a different supply voltage, refer to the “Oscillator Frequency vs Supply Voltage” graph on page 11 of the attached HT-12E datasheet to determine the exact oscillator frequency and resistor to be used.
Also, as a side note, we’ll be employing female headers here (serving a similar purpose as IC sockets) to plug the accelerometer, the RF transmitter and the Arduino in the circuit instead of directly soldering them onto the PCB. The intention being accommodation of a little component reusability. Say, it’s been a while since you engineered your gesture-controlled rover and its just sitting there, half covered in dust, atop your trophy shelf and you stumble upon another great instructable which leverages the efficacy of an accelerometer. So what do you do? You simply yank it out of your rover and push it in to your new circuit. No need to summon the “Amazons” to get you a new one :-p
Bonus: Do away with the Arduino, and yet Don’t!
Just in case you’re feeling a little more adventurous, and especially if you think that expending this beautifully designed marvel (the Arduino, of course) for such a trivial task as ours is a bit of an overkill, bear with me a little longer; and if not, feel free to skip to the next step.
Our goal here is to make the Arduino (the brains of the Arduino, in fact; yes, I’m talking about the ATmega IC!) a permanent member of the team. The ATmega would be programmed to run just a single sketch over and over again so that it could serve as a perpetual part of the circuit, just like the HT-12E—a mere IC, just sitting there, doing what it is supposed to. Ain’t this how any real embedded system is supposed to be?
Anyways, in order to proceed with this upgrade, just modify the circuit as per the second schematic attached. Here, we simply replace the female headers for the Arduino with an IC socket for the ATmega, add a 10K pull-up resistor at the reset pin (pin 1) of the IC and pump it up with an external clock between pins 9 and 10. Unfortunately, if we do away with the Arduino, we also let go of its built-in voltage regulators; ergo, we must replicate the LM7805-circuit that we had employed for the receiver here as well. Additionally, we also make use of a voltage divider to draw the 3.3V required to power the accelerometer.
Now, the only other catch here is programming the ATmega to do its job. You’ll have to wait for it until step 4, though. So, stay tuned…
Step 3: And, the Receiver
The receiver consists of an RF receiver module coupled with an HT-12D decoder IC and a pair of DC motors operated with the help of an L293D motor driver, all wired up as per the attached schematic.
The RF receiver’s only job is to demodulate the carrier wave (received via its antenna at pin 1) and render the retrieved “serial” data at pin 7 from where it is picked up by the HT-12D for deserialization. Now, assuming that the address lines (A0 through A7) on the HT-12D are configured identical to its HT-12E counterpart, the 4 parallel bits of data are extracted and passed on, via the data lines (D8 through D11) on the HT-12D, to the motor driver, which in turn interprets these signals to drive the motors.
Again, pay attention to the value of Rosc. The HT-12D, too, has an internal oscillator circuit between pins 15 and 16, which is enabled by connecting a resistor, called Rosc, between those pins. The value selected for Rosc actually determines the oscillator frequency, which may vary depending upon the supply voltage. Selecting an appropriate value for Rosc is crucial to the functioning of the HT-12D! Ideally the HT-12D’s oscillator frequency should be 50 times that of the HT-12E counterpart. Therefore, since we’re operating on 5V, we chose 1MΩ and 51kΩ resistors as Rosc for the HT-12E and HT-12D circuits respectively. Should you plan to operate the circuits on a different supply voltage, refer to the “Oscillator Frequency vs Supply Voltage” graph on page 5 of the attached HT-12D datasheet to determine the exact oscillator frequency and resistor to be used.
Also, don’t forget the female headers for the RF receiver.
Optionally, an LED can be connected via a 330Ω current limiting resistor to each of the 4 data pins of the HT-12D so as to help determine the bit received at that pin. The LED would light up if the bit received is HIGH (1) and would dim down if the bit received is LOW (0). Alternatively, a single LED could be tied to the VT pin of the HT-12D (again, via a 330Ω current limiting resistor), which would light up in the event of a valid transmission.
Now, if you’re looking for the hack with the motors that I was talking about in step one, it’s damn easy! Just wire the two motors in each set in parallel as shown in the second schematic. This works the way it’s supposed to because the motors in each set (the front and rear motors on the left and the front and rear motors on the right) are never driven in opposite directions. That is, in order to turn the rover right, the front and rear motors on the left must both be driven forward and the front and rear motors on the right must both be driven backwards. Similarly, to have the rover turn left, the front and rear motors on the left must both be driven backwards and the front and rear motors on the right must both be driven forward. Therefore, it is safe to feed in the same pair of voltages to both the motors in a set. And, the way to go about it is by simply hooking them motors up in parallel.
Step 4: On to the Code
There’s just one thing left to do to get the rover up and running. Yes, you guessed it right! (I hope you did) We’ve still got to translate the accelerometer readings into a form that the motor driver can interpret to be able to drive the motors. If you’re thinking that since the accelerometer readings are analog and the motor driver expects digital signals, we’ll have to implement some sort of an ADC, well, not technically, but that’s what we kinda need to do. And its quite straightforward.
We know that an accelerometer measures gravitational acceleration along a linear axis and that this acceleration is represented as a voltage level fluctuating between the ground and the supply voltage, which our microcontroller reads in as an analog value varying between 0 and 1023. But, since we’re operating the accelerometer at 3.3V, it’s advisable that we set the analog reference for the 10-bit ADC (that comes integrated in the ATmeaga aboard an Arduino) to 3.3V. It’ll just make things simpler to understand; although, it won’t matter much for our little experiment even if we didn’t (we'll just have to tweak the code a bit). To do so, however, we simply wire the AREF pin on the Arduino (pin 21 on the ATmega) to 3.3V and denote this change in code by calling analogReference(EXTERNAL).
Now, when we lay the accelerometer flat and analogRead the acceleration along the x and y axes (remember? we only need these two axes), we get a value of about 511 (i.e. half way between 0 and 1023), which is just a way of saying that there’s 0 acceleration along these axes. Rather than digging into the details of the fact, just imagine this as the x and y axes on a graph, with the value 511 denoting the origin and 0 and 1023 the endpoints as depicted in the figure; orient the accelerometer in such a way that its pins point down and are held closer to you or else you might invert/interchange the axes. This means that, if we tilt the accelerometer to the right, we should read a value greater than 511 along the x-axis, and if we tilt the accelerometer to the left, we should get a value lower than 511 along the x-axis. Similarly, if we tilt the accelerometer forward, we should read a value greater than 511 along the y-axis, and if we tilt the accelerometer backward, we should read a value lower than 511 along the y-axis. And this is how we deduce, in code, the direction that the rover should be driven in. But this also means that we must keep the accelerometer really steady and aligned parallel to a flat surface to be able to read a 511 along both the axes in order to have the rover parked still. To ease this task up a bit, we define certain thresholds forming a boundary, as the figure depicts, so that the rover remains stationary as long as the x and y readings lie within bounds and we know for sure that the rover must be set in motion once the threshold is exceeded.
For example, if the y-axis reads 543, we know that the accelerometer is tilted forward ergo we must steer the rover forward. We do this by setting pins D2 and D4 HIGH and pins D3 and D5 LOW. Now, since these pins are wired directly to the HT-12E, the signals are serialized and fired out the RF transmitter only to be caught by the RF receiver sitting on the rover, which with the help of the HT-12D deserializes the signals and passes them on to the L293D, which in turn interprets these signals and drives the motors forward
You might wanna change these thresholds, though, in order to calibrate the sensitivity. An easy way to do so is to simply wire your accelerometer to your Arduino and run a sketch that spits out the x and y readings on to the serial monitor. Now just move the accelerometer around a bit, glance through the readings and decide upon the thresholds.
And, that’s it! Upload the code to your Arduino and enjoy!! Or, perhaps not so soon :-( If you didn’t skip the bonus section, uploading the code to your ATmega would mean a little more work. You’ve got two options:
Option A:Use a USB to Serial device such as the FTDI FT232 basic breakout board. Simply run wires from the TTL header to the corresponding pins on the ATmega as per the mapping below:
|Pins on the Breakout Board||Pins on the Microcontroller|
|DTR/GRN||RST/Reset (Pin 1) via 0.1µF cap|
|Rx||Tx (Pin 3)|
|Tx||Rx (Pin 2)|
Now, plug one end of a USB cable into the breakout board and the other into your PC and upload the code as you normally would: launch the Arduino IDE, select an appropriate serial port, set the board type, compile the sketch and hit upload.
Option B:Use an UNO if you’ve got one lying around somewhere. Just plug your ATmega into the UNO, upload the code as you normally would, pull the IC out and push it back into the transmitter circuit. As easy as pie!
Either of these options should work, assuming you were smart enough to burn the bootloader before hand on your ATmega, or, if you were even smarter to purchase an ATmega with the bootloader already installed in the first place. If not, go ahead and do so by following the steps outlined here.
Andddd, we’re officially done! I hope you enjoyed this bizarrely lengthy instructable. Now, go on, finish building your rover if you’re not done already, play with it for a while and do come back to flood the comments section down below with queries and/or constructive criticisms.
P.S. The reason I didn’t upload any pics of the finished project is, well, because I didn’t complete it myself. Halfway through building it, I thought of some augmentations, such as speed control, obstacle avoidance and perhaps an LCD on the rover, which is actually not so difficult if we use a microcontroller on both the transmitting and the receiving ends. But, why not do it the hard way?! So, I’m currently working in that direction and I’ll post an update as soon as it bears any fruit. However, I did test out the code and the design with the help of a quick prototype that I built using modules from one of my previous projects; you can have a look at the video here.