Calculation of degree of accelerometer (nunchuck)

Hi
Does anyone know how to do this?
This is result I get in Serial monitor:
joy:120,123 acc:182,146,80 but:1,1

Here is code I found here on this forum

/*
 * NunchuckPrint
 *
 * 2007 Tod E. Kurt, http://todbot.com/blog/
 *
 * The Wii Nunchuck reading code is taken from Windmeadow Labs
 *   http://www.windmeadow.com/node/42
 */
 
#include <Wire.h>
uint8_t ctrlr_type[6];
void setup()
{
  Serial.begin(19200);
  nunchuck_setpowerpins(); // use analog pins 2&3 as fake gnd & pwr
  nunchuck_init(); // send the initilization handshake
  Serial.print ("Finished setup\n");
}

void loop()
{
  nunchuck_get_data();
  nunchuck_print_data();
  delay(1000);
}


//
// Nunchuck functions
//

static uint8_t nunchuck_buf[6];   // array to store nunchuck data,

// Uses port C (analog in) pins as power & ground for Nunchuck
static void nunchuck_setpowerpins()
{
#define pwrpin PORTC3
#define gndpin PORTC2
    DDRC |= _BV(pwrpin) | _BV(gndpin);
    PORTC &=~ _BV(gndpin);
    PORTC |=  _BV(pwrpin);
    delay(100);  // wait for things to stabilize        
}

// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
void nunchuck_init()
{ 
 byte cnt;

Wire.begin();
            
// init controller
delay(1);
Wire.beginTransmission(0x52);      // device address
Wire.send(0xF0);                    // 1st initialisation register
Wire.send(0x55);                    // 1st initialisation value
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0xFB);                    // 2nd initialisation register
Wire.send(0x00);                    // 2nd initialisation value
Wire.endTransmission();
delay(1);
            
// read the extension type from the register block        
Wire.beginTransmission(0x52);
Wire.send(0xFA);                    // extension type register
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6);               // request data from controller
for (cnt = 0; cnt < 6; cnt++) {
    if (Wire.available()) {
        ctrlr_type[cnt] = Wire.receive(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
    }
}
Wire.endTransmission();
delay(1);
            
// send the crypto key (zeros), in 3 blocks of 6, 6 & 4.
Wire.beginTransmission(0x52);
Wire.send(0xF0);                    // crypto key command register
Wire.send(0xAA);                    // sends crypto enable notice
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0x40);                    // crypto key data address
for (cnt = 0; cnt < 6; cnt++) {
    Wire.send(0x00);                    // sends 1st key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);                    // sends memory address
for (cnt = 6; cnt < 12; cnt++) {
    Wire.send(0x00);                    // sends 2nd key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40);                    // sends memory address
for (cnt = 12; cnt < 16; cnt++) {
    Wire.send(0x00);                    // sends 3rd key block (zeros)
}
Wire.endTransmission();
delay(1);
// end device init 


}

// Send a request for data to the nunchuck
// was "send_zero()"
void nunchuck_send_request()
{
  Wire.beginTransmission(0x52);      // transmit to device 0x52
  Wire.send(0x00);            // sends one byte
  Wire.endTransmission();      // stop transmitting
}

// Receive data back from the nunchuck, 
int nunchuck_get_data()
{
    int cnt=0;
    Wire.requestFrom (0x52, 6);      // request data from nunchuck
    while (Wire.available ()) {
      // receive byte as an integer
      nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive());
      cnt++;
    }
    nunchuck_send_request();  // send request for next data payload
    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5) {
     return 1;   // success
    }
    return 0; //failure
}

// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits.  That is why I
// multiply them by 2 * 2
void nunchuck_print_data()
{ 
  static int i=0;
  int joy_x_axis = nunchuck_buf[0];
  int joy_y_axis = nunchuck_buf[1];
  int accel_x_axis = nunchuck_buf[2]; // * 2 * 2; 
  int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
  int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;

  int z_button = 0;
  int c_button = 0;

  // byte nunchuck_buf[5] contains bits for z and c buttons
  // it also contains the least significant bits for the accelerometer data
  // so we have to check each bit of byte outbuf[5]
  if ((nunchuck_buf[5] >> 0) & 1) 
    z_button = 1;
  if ((nunchuck_buf[5] >> 1) & 1)
    c_button = 1;

  if ((nunchuck_buf[5] >> 2) & 1) 
    accel_x_axis += 2;
  if ((nunchuck_buf[5] >> 3) & 1)
    accel_x_axis += 1;

  if ((nunchuck_buf[5] >> 4) & 1)
    accel_y_axis += 2;
  if ((nunchuck_buf[5] >> 5) & 1)
    accel_y_axis += 1;

  if ((nunchuck_buf[5] >> 6) & 1)
    accel_z_axis += 2;
  if ((nunchuck_buf[5] >> 7) & 1)
    accel_z_axis += 1;

  Serial.print(i,DEC);
  Serial.print("\t");
  
  Serial.print("joy:");
  Serial.print(joy_x_axis,DEC);
  Serial.print(",");
  Serial.print(joy_y_axis, DEC);
  Serial.print("  \t");

  Serial.print("acc:");
  Serial.print(accel_x_axis, DEC);
  Serial.print(",");
  Serial.print(accel_y_axis, DEC);
  Serial.print(",");
  Serial.print(accel_z_axis, DEC);
  Serial.print("\t");

  Serial.print("but:");
  Serial.print(z_button, DEC);
  Serial.print(",");
  Serial.print(c_button, DEC);

  Serial.print("\r\n");  // newline
  i++;
}

// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_decode_byte (char x)
{
  x = (x ^ 0x17) + 0x17;
  return x;
}

this is result I get in Serial monitor:
joy:120,123 acc:182,146,80 but:1,1

Yes, gravity seems to be working where you are.

What's the question?

I would like to use my Arduino together with the nunchuck to measure how many degrees my motorhome is tilted and show this on my display (to correct it manually in a horizontal position when I'm parked on the campsite) it would be fun to do this

This was discussed recently - http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1263756306

Tricky for small angles with only 8/10 bit resolution.

I dont have my results in Voltage? I dont read my data with cables connection, I use Nunchuck adapter. Now ,how to do this with my output? acc:182,146,80

have you any idea?

Yes, check the datasheet to find out the number of counts (or volts, whatever) per g.

I'm a little concerned about the 182 / 146 values for what I assume are x & y axes - if the accelerometer is level, they should be the same value.

Do the values change as you tilt the device?

Yes Its change when i chance position of my nunchuck for example X=124,y=122,z=177 I´m not realy sure if I have this accelerometer in my nunckuck, but my code is for this accelerometer and not for orginal nunchuck. Here is the link for datasheet http://pdf1.alldatasheet.com/datasheet-pdf/view/171987/STMICROELECTRONICS/LIS3L02AL.html

Tanks for help sorry for my english

OK, so using your figures, and assuming the device is roughly level, then it looks to me like a count of about 124 represents an acceleration of 0g, and 177 an acceleration of 1g.

So, your resolution is 53 counts per g, or 0.0188g per count.

The rest is just trigonometry, as in the other thread.

(Note: these values are only my estimates)

can you please show me where to find this topic or how/what to search Thank you

If your accelerometer reads, say, 124 when level, and the sensitivity of the device is 53 counts per g, then tilting the accelerometer by 5 degrees will mean the count will change by sin (5) * 53 = 0.0871 * 53 = 4.6, so the new reading will be 120 or 128.

Ok I´m starting to figure out how it works but how did you get resolution is 53 counts per g, or 0.0188g per count. do you have some formula...because I´m not realy sure that my nunckuck is in level, I would like to calculate by my self

Thank you...

but how did you get resolution is 53 counts per g, or 0.0188g per count

Well, at first I guessed estimated from your figures, then I read the datasheet of the I2C version of the device here:
http://www.st.com/stonline/products/literature/ds/12726.pdf, which gives a sensitivity of 18mg per count (55.5 counts per g).

Not bad, huh? :slight_smile:

You are really skilled I have begun to understand this with the accelerometer. Have a last question before I start doing some math Where do you find (55.5 counts per g) or how do you know this?

Once again, thank you for guiding me about the accelerometer Better support, you can not find Best regards

Where do you find (55.5 counts per g) or how do you know this?

In the datasheet linked by AWOL above, page 10, section 2.1 Mechanical characteristics, table 3 - Sensitivity FS bit set to 0, 18 mg/digit, or (+/- 2g range) FS bit set to 1, 72 mg/digit (+/- 8g range)

1 / 18mg = 55.5 counts per g.

Hi. Lets take things from the start. In my nunchuck in the horizontal position im taking x=132 y=132 z=182 when i turn it 90o degree to the right im taking x=182 y=120 z=122 So Vdif=Vstart-Vend=182-132=50 Now im trying to put all the data in an equation for 45 degree Vmyangle=(sin(45) * 50) +Vstart = (0,707 * 50) +Vstart = 35,35 + Vstart = 35,35 +132 = 167,35 By looking in my readingw from my nunchuck whet im taking for 45o degree is 167 so my calcylations seems to be correct To make it more general 167 = ( sin(x) * (Vstart-Vend) ) + Vstart OR Vmyangle = ( sin(x) * (Vstart-Vend) ) + Vstart OR sinx = (Vmyangle - vstart)/(Vstart-Vend) Where Vmyangle=my readings in the angle i want to calculate Im doing it correct so far ??? If yes..how can i calculate the last equation in real code ??? Thnx in advance

sin-1((Vend - Vhoriz) / (volts_per_g))

or

sin-1((Countend - Counthoriz) / (counts_per_g))

Thnx for your reply Groove :)

sin-1((Vend - Vhoriz) / (volts_per_g)) or sin-1((Countend - Counthoriz) / (counts_per_g)

this is equal to asin( (Countend - Counthoriz) / (counts_per_g) ) right ???

asin is correct - just remember the result will be in radians, not degrees.

Also, for small angles, it may be useful to remember that sin(x) is approximately x

Thnx AWOL for your reply. I v read here http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf that the resolution in this method is much lower than calculating of angles in all 3 axis. In page 4 there are 3 equations for [ch961] , [ch966] , [ch952] . What you belive.. it is better to use the 3 axis calculation ??? Once again thnx :)

Certainly yes, if you can, use the other axes.