Go Down

Topic: How to convert analogRead value from accelerometer (Read 2 times) previous topic - next topic


You can use float variables.  You may need to include math.h for some functions.  Like so:

float gvalue, adc;

adc = (float)(ADCvalue);
gvalue = ((adc*3.0)/1024.-1.5))/3.0;

Floating point takes a while on the ATMega, so be careful about timing.



Perhaps a stupid answer, but let's try it :

You said :
gvalue = [(ADCvalue * 3) / 1024 - 1.5] / 0.3 = [(ADCvalue * 3) / 1024 - (15/10)] / (3/10) = [(ADCvalue * 10) / 1024 - 5]

Assuming that << 10 divide by 1024

this 'll give you :

[((ADCvalue * 10)<<10)  - 5]   = [((ADCvalue * 5)<<9)  - 5] , but you will loose decimal precision

But if your target precision is around 1/10 of g (look at the datasheet or depend on what you want to do), you can compute :

10*gvalue = [((ADCvalue * 5*10)<<9)  - 5*10]  = [((ADCvalue * 25)<<8)  - 50]

This way you can avoid float

Not sure of what I am doing :-[, but CosineKitty (the Math expert) can probably confirm.



Nicolas: Doesn't N<<10 multipy N by 1024 while N>>10 divides, and those only return integers right?

Drd: That sounds easy to use float, I didn't know I could do that. I don't need very fast timing so hopefully it will do.

I'll try both ways and see what happens.



Sure you are right, so replace << by >> in my post (see the CosineKitty math tutorial, bit shift section http://www.arduino.cc/playground/Code/BitMath )

Thanks, others tipos ?



I have nearly finished my code. I tried following nrollands idea for my calculations and in theory it should work, at least it does when I test it on my calculator. However I'm getting strange results that I don't understand. An example is it sometimes displays something like "589 = 0.-22g" and the digit in front of the decimal point is always 0 when it should change to 1,2,3...

Here is my code:

Code: [Select]

//Definitions needed to for cbi (clear bit) and sbi (set bit)
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#define zerog_x 531 //X ADC value in the zero G position & is theoretically 512
#define calconst 1087//constant used when converting ADC values to g's

int xadc=0; //X ADC value
int yadc=0; //Y ADC value
int zadc=0; //Z ADC value
long xGval=0;   //X g value
int num1=0;    //digit in front of decimal place
int num2=0;    //digits after decimal place
void setup() {
 cbi(ADMUX, REFS1);   //set a2d reference voltage to external AREF pin ...
 cbi(ADMUX, REFS0);   //... so that ADC uses 3V instead of 5V
 Serial.begin(9600);  // use the serial port to send values back to the PC

void loop() {
     xadc=analogRead(0); //read x-axis values from analog in 0
     yadc=analogRead(1); //read y-axis values from analog in 1
     zadc=analogRead(2); //read z-axis values from analog in 2
     xadc = xadc / 2; //take an average for accuracy & less error
     yadc = yadc / 2;
     zadc = zadc / 2;
     if(xadc < zerog_x){ //calculations for negative g values
       xGval = calconst*(xadc-zerog_x);
       xGval = abs(xGval);
       xGval = xGval>>10;
       Serial.print("=  -");
     else{ //calculations for positive g values
     xGval = calconst*(xadc-zerog_x);
     xGval = xGval>>10;
     Serial.print("=   ");
     Serial.println("g"); // should look like: "xadc= num1.num2 g"
     delay(1000); //slow down so its easier to read the serial monitor

Any suggestions? I know my coding style is not very good, but I'm learning :)

Go Up