ATMega 128 & Accelerometer – From theory to practice
In this tutorial I will give the code and some explanations to use a accelerometer with a micro-controller.
In fact during a personal project, Franck (a friend) and I used a micro-controller to control a PC.
We used: STK128+/AVR atmega128, 3 axis accelerometer. But we also used a virtual reality glove (to get more interactivity) and a java application to control the computer (but I will not speak about that in this post).
What you need
You need several things, first the software components:
- CodeVision (the free version is enough)
- AVR studio (free download from ATMEL website)
- A RS232 – serial port monitor (you can easily find some on the web)
Second, the hardware components:
- A board and a micro-controller (here we are using a STK128 board and a atmega128)
- A 3 axis accelerometer. I used the DE-ACCM3D2 from dimensionengineering at http://www.dimensionengineering.com/DE-ACCM3D.htm, it is cheap and work well!
Connections and links between components
PLEASE REFERE TO THE DOCUMENTATION OF ATMEGA128 & ACCELEROMETER
The led
We need to connect the led to the Cx Pins.
If you are using the stk128 as I do, it is very easy, you just need to use a 7 wires block.
From here, we can use the led, we will use it to be sure that our program is running and see if the accelerometer is correctly used.
Buttons
The we need to connect the button, please connect the PA6 and PA7 to S0 and S1. This button will be used to reset the accelerometer position.
RS232 – serial port
To use the serial port (UART1) please connect RXD1/INT2 and TXD1/INT3 to 232TXD1 and 232RXD1.
We will use serial port to send data to the PC using serial port, but from this it is very easy to use Bluetooth instead of serial port.
Accelerometer
As you can see in the documentation of the atmega128 there is several input for the ADC. So please connect the VCC and ground of the accelerometer any where in the board, and connect X, Y and Z to ADC0, ADC1 and ADC2 pins.
Finally, connect the AVRISP to the ISP connector and give power to the board using the USB wire.
Software made easy with CodeVision
In the code what we need is:
- Make the PORTC as output
- Say that we want to use the ADC
- Prepare the UART1
- Prepare the timer and build interrupt function
All of this thing can be done with the Code Wizard of CodeVision.
Here are some screen shots:
Start a new project,


Use the code wizard ^^

Then configure your micro-controller:






In the code
What we just need:
- The variables to save the default position of the accelerometer
- The variables to save the speed in the different axis
So in the code, please a the top of the file add the following lines:
unsigned char xOrig; unsigned char yOrig; unsigned char zOrig; char xSpeed; char ySpeed; char zSpeed;
I used global variables for speed because I need it in other stuff, but you can do it in a different manner.
- In the timer interrupted function, we need to convert the value from the 3 axis and send the data, we will use the protocol: #X;Y;Z;#
It gives something like:
interrupt <a title="TIM0_OVF" href="TIM0_OVF">TIM0_OVF</a> void timer0_ovf_isr(void)
{
unsigned char result;
putchar1('#');
result = read_adc( 0 ); // read X
if( result > xOrig ){
xSpeed = result - xOrig ;
}
else{
xSpeed = xOrig - result ;
xSpeed |= 0x80; // set to negative number
}
putchar1(xSpeed);
putchar1(';');
result = read_adc( 1 ); // read Y
if( result > yOrig ){
ySpeed = result - yOrig ;
}
else{
ySpeed = yOrig - result ;
ySpeed |= 0x80;
}
putchar1(ySpeed);
putchar1(';');
result = read_adc( 2 ); // read Z
if( result > zOrig ){
zSpeed = result - zOrig ;
}
else{
zSpeed = zOrig - result ;
zSpeed |= 0x80;
}
putchar1(zSpeed);
putchar1(';');
// Then to be sure that it is working, let print the XSpeed in the led
printLed( xSpeed ) ;
}
To print the result on the led, we will simple turning on the led from the middle to the left or the right depending of the sign of the value and we will turn a number of led based of the importance of the value. Here is the code:
void printLed( signed char val ){
// can be done with binary operator
// but here it is easy to understand
if( !(val & 0x80) && val){ // if positive
// print on the right
if( val > 76 ) PORTC = 0x0F;
else if( val > 31 ) PORTC = 0x0E;
else if( val > 15 ) PORTC = 0x0C;
else PORTC = 0x08;
}
else if( val ){ // if negative
val = val & 0x7F;
// print on le left
if( val > 76 ) PORTC = 0xF0;
else if( val > 31 ) PORTC = 0x70;
else if( val > 15 ) PORTC = 0x30;
else PORTC = 0x10;
}
else PORTC = 0; // if zeros
}
Then in the main loop (and just before it) we need:
// Init variables
xSpeed = 0;
ySpeed = 0;
zSpeed = 0;
xOrig = read_adc( 0 );
yOrig = read_adc( 1 );
zOrig = read_adc( 2 );
// Global enable interrupts
#asm("sei")
while (1)
{
// The button is pressed
if( !( PINA & 0x80 ) ){
// Global disable interrupts
#asm("cli")
PORTC = 0x00;
PORTC = 0xFF;
// init variables
xOrig = read_adc( 0 );
yOrig = read_adc( 1 );
zOrig = read_adc( 2 );
xSpeed = 0;
ySpeed = 0;
zSpeed = 0;
while(!( PINA & 0x80 ));
PORTC = 0x00;
// Global enable interrupts
#asm("sei")
}
};
}
<pre>
So from here we have this behaviour: when you launch the program, a timer is executing a capture of the 3 axis of the micro-controller, then, the Xaxis is print to the led and if some one is pushing the button the default position are captured. As you can see we are not working with the speed but with the orientation (based on the power of the gravity on the accelerometer, if you want you can get the acceleration – and the speed – by using the frequency of the timer/capture of the axis values … let you do that if you need it).
Subscribe to the RSS feed and have all new posts delivered straight to you.

