30
Jan
0

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:

Connections and links between components

PLEASE REFERE TO THE DOCUMENTATION OF ATMEGA128 & ACCELEROMETER

montage

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,

cv - new

cv project

Use the code wizard ^^

cv wiazrd

Then configure your micro-controller:

cv chip selection

cv adc config

cv portA input

cv portC output

cv timer interupt

cv uart1 config

In the code :D

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).

 

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.

Comments are closed.

Celadon theme by the Themes Boutique