Introduction: Head-Motion Controlled Car
This project was made as part of a class at Vanderbilt University (BME 3300: Biomedical Instrumentation). It's meant to be a very basic prototype/model of how motion can control a vehicle with applications for patients experiencing quadriplegia or other forms of paralysis.
Motion is measured by an accelerometer, which measures the values of acceleration that the device is experiencing (usually due to gravity) and how it changes in relation to the three axes. These output values, in turn, input into an Arduino. The Arduino (microcontroller) hold code that thresholds certain movements and outputs them to a small "robot" car. The car realizes the movements of the head as movements of the car.
It's a really cool little toy to play around with and definitely has some potential to turn into something more polished and useful! Enjoy!
Step 1: Gather Materials
- Insulated wire
- 1 Arduino Uno Board (https://store.arduino.cc/usa/arduino/arduino-board...
- 1 Pololu Zumo Robot (https://www.pololu.com/category/169/zumo-robot-for...
- 1 ADXL337 Analog Accelerometer (https://www.sparkfun.com/products/12786)
- 1 Headband/strap (https://www.amazon.com/EverBrite-Headlamp-Flashlig...
- A few heat-shrink coverings
- Arduino Programming Application (https://www.arduino.cc/en/Main/Software)
- Soldering Iron
- Solder Flux
- 4 AA batteries (for the Zumo)
- 1 A-B USB cable
For the headband, we just removed the lamp from the headlamp and the band that goes over top of the head. This was just for orientation purposes (the accelerometer maxes out when in certain orientations, and we want a continuous range of values for the head motions that we are doing.
Step 2: Goals of the Project
For this project we're going to pursue the following head motion - car motion commands:
- Tilting head right (pitch, not yaw) will engage the left motor (moving the car forward and to the right).
- Tilting head left (pitch, not yaw) will engage the right motor (moving the car forward and to the left).
- If the head isn't tilted left or right, tilting the head forward will engage both motors in the forward direction.
- If the head isn't tilted left or right, tilting the head backward will engage both motor in the reverse direction.
See the video for an example!
Step 3: Circuit Diagram and Soldering
The circuit diagram is pretty simple. Since the accelerometer is analog, we can directly connect its three output voltages to the Arduino. The Zumo robot acts like a shield for the Arduino board, however. So, when the Arduino is attached to the bot, all of the ports are hidden. Luckily, the Zumo has pins that you can solder the wires to. Solder to make the appropriate connections between the ADXL337 and the Zumo.
**A few notes:
- The input to the ADXL337 is 3.3 V, so instead of connecting the Vcc port of the ADXL337 to an analog out, connect it directly to the "3.3V" pin on the Zumo.
- Connect the GND pin to the GND pin on the Zumo
- You don't need a connection to the ADXL337 "ST" pin.
- Connect x y and z as shown in the diagram, but you can alsways adjust which pin is what in the code.
At this time, you can also attach the ADXL337 to the headband. Make sure you attach in such that rotating your head will only change its output in one axis. This usually means attaching so that there is always an edge that is perpendicular to the arc of motion. i.e. Square it up with the front of your head and you should be fine.
Step 4: Calibration of Thresholds
Check out the images for some example code. The first part just initializes and names the inputs from the x, y, and z outputs of the ADXL337. Don't worry about groundpin and powerpin. We bypassed that by using the dedicated 3.3V and GND pin to power the accelerometer.
The second part of the code is the beginning of the loop that will display the values from the accelerometer for each of the three axes. Open the serial monitor to view these updating in real time. The serial monitor can be found in Tools -> Serial Monitor.
**Note: Make sure your Arduino is connected to your computer with the A-B USB while recording this data or the serial monitor will not display anything or will not open.**
When we did the project, we had the headband oriented such the the band went over the head and under the chin. This enabled the ADXL337 to sit flat on the top of the head. In this orientation, we got the values that you see in the third image for the motions we discussed earlier.
**Note: When setting your thresholds, you want to keep in mind that you want a "dead zone" - a range of motion (and thus a range of ADXL337 values) that won't activate the car in any way. So, set your actual threshold to be slightly more central than the two extremes. You also want to change only one axis at a time to isolate movement. If you tilt the ADXL337 when attaching it to the headband, then you may get skewed values.**
Step 5: Main Code (Thresholds and Nested If-Else Statements)
The command for activating the appropriate motors actually comes from a library that Pololu makes for its Zumo robots. You can import this with the #include <ZumoMotors.h> and the ZumoMotors motors; commands. You can see this in the first image. You'll also have to download this library from GitHub: https://github.com/pololu/zumo-shield/tree/master/...
Add the file that you get to the "libraries" folder in your Arduino folder on your computer. This will allow the code to pull the appropriate commands from the library.
The main code uses a series of if-else statements nested together. Essentially, you want to check if the head is tilted left or right first (use your own thresholds!). If it is, you want the car to turn in the appropriate way using motors.setxxxxSpeed(yyyy) - "xxxx" is either "Left" or "Right" and "yyyy" is a numerical value (negative values indicate reverse movement).
If the head does not match any of the above criteria (it's in the middle), then you want to check for forward or reverse tilting and make the car do the appropriate maneuver.
Finally, if the head completely in the middle (not forward, reverse, right, or left), you want the car to disengage both motors (the last part of the code).
Note: with this code, if you tilt your head left or right while trying to move forward or backward, the robot will prioritize the left or right movement even if you're tilting forward. You can change this in your code, but it's just something to be aware of.
Step 6: Test and Optimize!
You're done! Make sure you connect your Arduino to your Zumo and you compile and upload your code to your Arduino with the USB cable. Congratulations! But there's more you can do to expand on this project...
Some things to consider improving:
- Wireless capabilities (maybe look into bluetooth or WiFi as a way to do this - some Arduino boards come with WiFi capabilities.
- Filtering or data processing. The robot can sometimes be "twitchy" as a result of high sensitivity of the ADXL337. With some appropriate processing (a moving average algorithm, for example), you may be able to reduce some of this jittery-ness.
- Adding graded capabilities. This would entail adjusting the power of the motors based on the degree of head tilt.
- More robust code to allow for more smooth control. This would entail fixing the issue that the code currently prioritizes right-left movement over forward-reverse movement. This way, you'd be able to move forward and turn at the same time.
Have fun and thanks for coming along for the adventure!