Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Issues with accelero and gyro sensitivity

Mon Feb 20, 2017 10:43 am

Hi,

I am working on a project to record acceleration and rotation values of a moving object around a vertical axis.

The Sense HAT is equipped with an LSM9DS1 inertial module, and its datasheet states that it has various measurement ranges, each range having its own sensitivity.

For the moment, I'm only working with the accelerometer, and I have this issue : the X, Y, and Z values don't seem to be correct.

For example, with the RPi + SenseHat being still, the following Python 3 code :

Code: Select all

from sense_hat import SenseHat

SH = SenseHat()

while True:

    acceleration = sense.get_accelerometer_raw()

    print("x: " + str(acceleration['x']))
    print("y: " + str(acceleration['y']))
    print("z: " + str(acceleration['z']))
returns values like :

Code: Select all

x: 0.030790632590651512
y: 0.03836122900247574
z: 0.9808798432350159
Using I2C instead of SenseHat functions returns values like :

Code: Select all

x: 35980
y: 23644
z: 45746
I'm aware that sensors can't have 100 % accuracy, but I assume that the z value should be closer to 1, which leads me to my questions :
  • Am I doing something wrong ?
  • Do I need to use the sensitivity values provided by the datasheet ? And if I have to, how ?
  • How to use the sensitivity on the I2C-obtained values to have the "real" ones ?
Thank you in advance for your help !
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

scotty101
Posts: 3597
Joined: Fri Jun 08, 2012 6:03 pm

Re: Issues with accelero and gyro sensitivity

Mon Feb 20, 2017 11:16 am

As with any off-the-shelf sensor. It needs calibration.

If you expect 1g in on the axis pointing towards the centre of the earth then you can provide a lookup table to give you the exact values and rotate the sensor to measure how far off each axis is and adjust appropriately.
Do this for all 3 axis (and ideally over a range of temperatures) and you'll have more accurate values.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Mon Feb 20, 2017 1:19 pm

I followed these instructions in the "CALIBRATION" section, and obtained an .ini file that I copied in /etc, then I slightly modified it to match my needs : +/- 2 g range for the accelerometer, +/- 250 dps range for the gyroscope.

What about now ? Do I need to import this file in my .py file ?
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

User avatar
Davespice
Forum Moderator
Forum Moderator
Posts: 1662
Joined: Fri Oct 14, 2011 8:06 pm
Location: The Netherlands
Contact: Twitter

Re: Issues with accelero and gyro sensitivity

Mon Feb 20, 2017 2:58 pm

Hi Grozhibou

The xyz values for the raw accelerometer measurements in the original post look normal to me. It's quite common to get close to 1G on the Z axis and a small amount on other axes at the same time. This can happen if, for instance, the surface the Sense HAT is on is not level.

One thing you can do is just round the numbers to one or two decimal places.

Code: Select all

round(acceleration['x'], 1)
The calibration you mentioned only affects the magnetometer as far as I know. But if you want to use your own RTIMULib.ini file you should copy it into /etc but then also remove the cached file found in the location below before you run your Python code:

Code: Select all

~/.config/sense_hat
Cheers
Dave

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Tue Feb 21, 2017 7:32 am

Thanks for your answer !

Rounded values are indeed closer to what I was expecting, but I still have an issue : I put my RPi + Sense HAT on a rotating platform which is rotating at 90 dps (+/- 1 dps). I record the X, Y, and Z values, expecting values around 0 dps for X and Y, and around 90 dps for Z.

The problem is I have values between -15 and 25 for X, between -6 and 7 for Y, and between -78 and -68 for Z (as shown on the attached PNG file).

I assume the negative Z values are just a wrong direction of rotation, but why those values ?

I used the following code to record them :

Code: Select all

from sense_hat import SenseHat

SH = SenseHat()
bus = smbus.SMBus(1) # Got the 1 value with [i]i2cdetect -y 1[/i].

# Turning on the gyroscope and the accelerometer.
bus.write_byte_data(0x6a, 0x22, 0x04) # Got these values with [i]i2cdetect -y 1[/i].
bus.write_byte_data(0x6a, 0x20, 0xe0)
bus.write_byte_data(0x6a, 0x10, 0x0c3)

# Values to calibrate the gyroscope.
calX = 0
calY = 0
calZ = 0

# Calibrating the gyroscope.
for i in range (100): # 100 values to calibrate the gyro.

    readX = bus.read_word_data(0x6a, 0x18)
    readY = bus.read_word_data(0x6a, 0x1a)
    readZ = bus.read_word_data(0x6a, 0x1c)

    if readX >= 0x800:
        readX -= 65536
    calX += readX

    if readY >= 0x800:
        readY -= 65536
    calY += readY

    if readZ >= 0x800:
        readZ -= 65536
    calZ += readZ
    time.sleep(0.05)

# Gaps between the measured and the real values.
gapX = calX/nbrOfCal
gapY = calY/nbrOfCal
gapZ = calZ/nbrOfCal

# Arrays for the 3 axis orientation (pitch, roll, yaw).
oriP = []
oriR = []
oriY = []

for i in range(0, 28000): # 28 000 measures is about 90 seconds.
    
    oriP.append(bus.read_word_data (0x6a,0x18))
    oriR.append(bus.read_word_data (0x6a,0x1a))
    oriY.append(bus.read_word_data (0x6a,0x1c))

# Formatting the values from raw to converted to the proper units.
for i in range(0, 28000):

    if oriP[i] >= 0x8000:
        oriP[i] -= 65536
    oriP[i] = (oriP[i] - gapX) * 245.0 / (65536 / 2)

    if oriR[i] >= 0x8000:
        oriR[i] -= 65536
    oriR[i] = (oriR[i]- gapY) * 245.0 / (65536 / 2)

    if oriY[i] >= 0x8000:
        oriY[i] -= 65536
    oriY[i] = (oriY[i] - gapZ) * 245.0 / (65536 / 2)

# Rounding the values.
for i in range(0, 28000):
    
    oriP[i] = round(oriP[i], 2)
    oriR[i] = round(oriR[i], 2)
    oriY[i] = round(oriY[i], 2)
Thank you in advance for you help ! :)
Attachments
courbesDps2 - Copie.png
courbesDps2 - Copie.png (27.65 KiB) Viewed 5440 times
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

User avatar
davidcoton
Posts: 3784
Joined: Mon Sep 01, 2014 2:37 pm
Location: Cambridge, UK

Re: Issues with accelero and gyro sensitivity

Tue Feb 21, 2017 8:04 pm

AIUI, if the SenseHat is rotating about a vertical axis and orientated so that the Z axis of the accelerometer is vertical, then you will get a constant 1g magnitude Z acceleration (+ or -). The X and Y values will be varying sinusoidally, in quadrature, at the rotation frequency (0.25Hz). The accelerometer does not read rotational acceleration, but linear.

Of course, I may have missed the point somewhere.... :?
Signature retired

User avatar
mwilliams03
Posts: 120
Joined: Mon Oct 29, 2012 2:56 pm
Contact: Website

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 5:26 am

What is this for?

Code: Select all

 oriY[i] = (oriY[i] - gapZ) * 245.0 / (65536 / 2)
To get dps from the gyro, you need to multiple the raw by the sensitivity level in mdps (milli).
The table in the datasheet shows for 2000dps it is 70 mdps.

So your math would be.
raw value x 0.07 = dps

more info here;
http://ozzmaker.com/berryimu/
Mark -- OzzMaker.com -- Creator of;
+ BerryIMU
+ Berry GPS-IMU
+BerryGPS-GSM
+ PiScreen - A 3.5" TFT for the Rasspberry Pi

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 8:01 am

Thank you for your answers. :)
davidcoton wrote:you will get a constant 1g magnitude Z acceleration (+ or -). The X and Y values will be varying sinusoidally, in quadrature, at the rotation frequency (0.25Hz). The accelerometer does not read rotational acceleration, but linear.
I agree with the +/- 1 g for the vertical Z axis, but why would the X and Y axis show sinusoidal values ?
On my attached drawing, the RPi is rotating with the platform, at the same angular speed, so why would X and Y accelerations would be changing as the rotation speed is constant ?
mwilliams03 wrote:What is this for?

Code: Select all

 oriY[i] = (oriY[i] - gapZ) * 245.0 / (65536 / 2)
I use gapX/Y/Z values to calibrate respectively the pitch/roll/yaw measured values : when the Sense HAT is still, I record 100 measures on each axis, sum them, and then divide them by 100 to have an average still value. Then I subtract these values to their respectively measured values (I think it's called "zeroing" ? :? )

The * 245.0 / (65536 / 2) is here to convert raw values recorded with I2C to real values, according to the datasheet with the given ranges (+/- 2 g for the accelerometer, +/- 245 dps for the gyroscope).
mwilliams03 wrote:To get dps from the gyro, you need to multiple the raw by the sensitivity level in mdps (milli).
The table in the datasheet shows for 2000dps it is 70 mdps.

So your math would be.
raw value x 0.07 = dps
With 0.00875 then, as I am using the +/- 245 dps range. I have to try this, thank you ! ;)

EDIT : I've just tried, and got as raw values, one line for example :

Code: Select all

accX |  accY |  accZ | rotX | rotY | rotZ
 464 | 65148 | 49356 |  879 |  127 |   42
Which give, once converted (with * 0.000061 for the acceleration, and with * 0.00875 for the angular speed) and rounded :

Code: Select all

accX |  accY |  accZ | rotX | rotY | rotZ
0.03 |  3.97 |  3.01 | 7.69 | 1.11 | 0.37 
About 4 and 3 g is quite a lot, and so is 7 dps..! :?

The Python 3 code that I used :

Code: Select all

import smbus

nbrOfRec = 1000

bus = smbus.SMBus(1)

# Turning on the gyroscope and the accelerometer.
bus.write_byte_data(0x6a, 0x22, 0x04)
bus.write_byte_data(0x6a, 0x20, 0xe0)
bus.write_byte_data(0x6a, 0x10, 0x0c3)

# Arrays for the 3 axis acceleration (X, Y, Z).
accX = []
accY = []
accZ = []

# Arrays for the 3 axis orientation (pitch, roll, yaw).
oriP = []
oriR = []
oriY = []

# Processing.
for i in range(0, nbrOfRec):
    
    accX.append(bus.read_word_data (0x6a,0x28))
    accY.append(bus.read_word_data (0x6a,0x2a))
    accZ.append(bus.read_word_data (0x6a,0x2c))
    
    oriP.append(bus.read_word_data (0x6a,0x18))
    oriR.append(bus.read_word_data (0x6a,0x1a))
    oriY.append(bus.read_word_data (0x6a,0x1c))

# Converting the values.
for i in range(0, nbrOfRec):
    
    accX[i] = accX[i] * 0.000061
    accY[i] = accY[i] * 0.000061
    accZ[i] = accZ[i] * 0.000061
    
    oriP[i] = oriP[i] * 0.00875
    oriR[i] = oriR[i] * 0.00875
    oriY[i] = oriY[i] * 0.00875
    
# Rounding the values.
for i in range(0, nbrOfRec):
    
    accX[i] = round(accX[i], 1)
    accY[i] = round(accY[i], 1)
    accZ[i] = round(accZ[i], 1)
    
    oriP[i] = round(oriP[i], 1)
    oriR[i] = round(oriR[i], 1)
    oriY[i] = round(oriY[i], 1)

# The name of the file where the values will be written.
fileName = "recordings.csv"

file = open(fileName, 'a')

file.write("accX;")
file.write("accY;")
file.write("accZ;")
file.write("oriP;")
file.write("oriR;")
file.write("oriY;\n")

for i in range(0, nbrOfRec):
    
    file.write(str(accX[i]) + ';')
    file.write(str(accY[i]) + ';')
    file.write(str(accZ[i]) + ';')
    file.write(str(oriP[i]) + ';')
    file.write(str(oriR[i]) + ';')
    file.write(str(oriY[i]) + ';\n')

file.close()
Is this a problem that my rotation axis is not the same axis as the Sense HAT's gyroscope ? I assume it is not as I am measuring an angular speed, but I'm not sure...

I'm sorry if some things are unclear, English is not my native language and I may have some issues describing my problem ; thanks for your help and patience !
Attachments
schema.png
schema.png (4.56 KiB) Viewed 5243 times
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

User avatar
mwilliams03
Posts: 120
Joined: Mon Oct 29, 2012 2:56 pm
Contact: Website

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 10:21 am

those raw values dont look correct.

I merged my code into your code, i am using the LSM9DS0 it has different registers but the math is the same.

The below code works for me.
I removed all the accelerometer values as you are looking for the Z gyro rotation.
There is no calibration, but you should be able to get results without it.

Code: Select all

from LSM9DS0 import *

import smbus

nbrOfRec = 1000

bus = smbus.SMBus(1)

bus.write_byte_data(GYR_ADDRESS, CTRL_REG1_G, 0b00001111)
bus.write_byte_data(GYR_ADDRESS, CTRL_REG4_G, 0b00000000)


def readGYRx():
        gyr_l = bus.read_byte_data(GYR_ADDRESS, OUT_X_L_G)
        gyr_h = bus.read_byte_data(GYR_ADDRESS, OUT_X_H_G)
        gyr_combined = (gyr_l | gyr_h <<8)

        return gyr_combined  if gyr_combined < 32768 else gyr_combined - 65536


def readGYRy():
        gyr_l = bus.read_byte_data(GYR_ADDRESS, OUT_Y_L_G)
        gyr_h = bus.read_byte_data(GYR_ADDRESS, OUT_Y_H_G)
        gyr_combined = (gyr_l | gyr_h <<8)

        return gyr_combined  if gyr_combined < 32768 else gyr_combined - 65536


def readGYRz():
        gyr_l = bus.read_byte_data(GYR_ADDRESS, OUT_Z_L_G)
        gyr_h = bus.read_byte_data(GYR_ADDRESS, OUT_Z_H_G)
        gyr_combined = (gyr_l | gyr_h <<8)

        return gyr_combined  if gyr_combined < 32768 else gyr_combined - 65536





# Arrays for the 3 axis orientation (pitch, roll, yaw).
oriP = []
oriR = []
oriY = []

# Processing.
for i in range(0, nbrOfRec):


    oriP.append(readGYRx())
    oriR.append(readGYRy())
    oriY.append(readGYRz())


# Converting the values.
for i in range(0, nbrOfRec):


    oriP[i] = oriP[i] * 0.00875
    oriR[i] = oriR[i] * 0.00875
    oriY[i] = oriY[i] * 0.00875

# Rounding the values.
for i in range(0, nbrOfRec):


    oriP[i] = round(oriP[i], 1)
    oriR[i] = round(oriR[i], 1)
    oriY[i] = round(oriY[i], 1)


# The name of the file where the values will be written.
fileName = "recordings.csv"

file = open(fileName, 'a')

file.write("oriP;")
file.write("oriR;")
file.write("oriY;\n")

for i in range(0, nbrOfRec):

    file.write(str(oriP[i]) + ';')
    file.write(str(oriR[i]) + ';')
    file.write(str(oriY[i]) + ';\n')

file.close()


Mark -- OzzMaker.com -- Creator of;
+ BerryIMU
+ Berry GPS-IMU
+BerryGPS-GSM
+ PiScreen - A 3.5" TFT for the Rasspberry Pi

User avatar
davidcoton
Posts: 3784
Joined: Mon Sep 01, 2014 2:37 pm
Location: Cambridge, UK

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 11:21 am

Grozhibou wrote:Thank you for your answers. :)
davidcoton wrote:you will get a constant 1g magnitude Z acceleration (+ or -). The X and Y values will be varying sinusoidally, in quadrature, at the rotation frequency (0.25Hz). The accelerometer does not read rotational acceleration, but linear.
I agree with the +/- 1 g for the vertical Z axis, but why would the X and Y axis show sinusoidal values ?
On my attached drawing, the RPi is rotating with the platform, at the same angular speed, so why would X and Y accelerations would be changing as the rotation speed is constant ?
:oops: I forgot that the Pi's x and y axes would rotate too! I'll try again now I've slept and had coffee.
With your diagram, the x-axis should show a constant acceleration proportional to the speed of rotation
and the y-axis should show zero acceleration (constant velocity).
This will vary if your Pi x-axis is not aligned with the radius of the platform.
Signature retired

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 12:44 pm

mwilliams03 wrote:those raw values dont look correct.

I merged my code into your code, i am using the LSM9DS0 it has different registers but the math is the same.

The below code works for me.
I removed all the accelerometer values as you are looking for the Z gyro rotation.
There is no calibration, but you should be able to get results without it.
Thank you for the code, I must look at it and adapt the code for my needs.

Can you explain me the following points ? :
  • What are the two first bus.write_byte_data() doing ?
  • What are the differences between OUT_X_L_G and OUT_X_H_G ?
  • What are the return of your three read functions doing ?
  • What is (gyr_l | gyr_h << 8) doing ?
davidcoton wrote:With your diagram, the x-axis should show a constant acceleration proportional to the speed of rotation
And then become constant when the top angular speed is reached and constant, right ?
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

User avatar
mwilliams03
Posts: 120
Joined: Mon Oct 29, 2012 2:56 pm
Contact: Website

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 1:10 pm

I should have posted posted a link to all the code;
https://github.com/mwilliams03/BerryIMU ... el-compass

I also have a guide here;
http://ozzmaker.com/berryimu/
What are the two first bus.write_byte_data() doing ?
They enable the gyro and set the scale and ODR.

CTRL_REG1_G = register 0x20
CTRL_REG4_G = register 0x23.
What are the differences between OUT_X_L_G and OUT_X_H_G ?
The values are expressed in 2’s complement (MSB for the sign and then 15 bits for the value) so you will need to combine them.
What is (gyr_l | gyr_h << 8) doing ?
This is combining the readings from the two registers. gyr_l is the low byte and gyr_h is the high byte.

Code: Select all

What are the return of your three read functions doing ?
After we combine the values, we need to take into consideration that the left most bit is for the sign value. if the left most bit is zero (or below 32768) do nothing, if the left bit is set(higher than or equal to 32768) then the number should be a negative.
Mark -- OzzMaker.com -- Creator of;
+ BerryIMU
+ Berry GPS-IMU
+BerryGPS-GSM
+ PiScreen - A 3.5" TFT for the Rasspberry Pi

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 1:50 pm

It's my first time using I2C and the registers, so thank you for the explanations !

I took your code and "translated" it for the LSM9DS1, thanks to its datasheet and the LSM9DS0 one, and I left to the default values the things I wasn't sure about, and close values when yours weren't possible.

For example, you used 95 Hz for ODR and 12.5 for cutoff, but those values don't exist with the LSM9DS1, so I took 119 Hz and 38, which are the closest values.

What I got is the following :

Code: Select all

import smbus

nbrOfRec = 1000

bus = smbus.SMBus(1)

# Enable X, Y, Z for the gyroscope.
bus.write_byte_data(0x6a, 0x1e, 0b00111000)

# ODR, BW, FS for the gyroscope.
bus.write_byte_data(0x6a, 0x10, 0b011000000)

def readGYRx():
    gyr_l = bus.read_byte_data(0x6a, 0x18)
    gyr_h = bus.read_byte_data(0x6a, 0x19)
    gyr_combined = (gyr_l | gyr_h << 8)

    return gyr_combined  if gyr_combined < 32768 else gyr_combined - 65536

def readGYRy():
    gyr_l = bus.read_byte_data(0x6a, 0x1a)
    gyr_h = bus.read_byte_data(0x6a, 0x1b)
    gyr_combined = (gyr_l | gyr_h << 8)

    return gyr_combined  if gyr_combined < 32768 else gyr_combined - 65536

def readGYRz():
    gyr_l = bus.read_byte_data(0x6a, 0x1c)
    gyr_h = bus.read_byte_data(0x6a, 0x1d)
    gyr_combined = (gyr_l | gyr_h << 8)

    return gyr_combined  if gyr_combined < 32768 else gyr_combined - 65536

# Arrays for the 3 axis orientation (pitch, roll, yaw).
oriP = []
oriR = []
oriY = []

# Processing.
for i in range(0, nbrOfRec):

    oriP.append(readGYRx())
    oriR.append(readGYRy())
    oriY.append(readGYRz())

# Converting the values.
for i in range(0, nbrOfRec):

    oriP[i] = oriP[i] * 0.00875
    oriR[i] = oriR[i] * 0.00875
    oriY[i] = oriY[i] * 0.00875

# Rounding the values.
for i in range(0, nbrOfRec):

    oriP[i] = round(oriP[i], 1)
    oriR[i] = round(oriR[i], 1)
    oriY[i] = round(oriY[i], 1)

# The name of the file where the values will be written.
fileName = "recordings.csv"

file = open(fileName, 'a')

file.write("oriP;")
file.write("oriR;")
file.write("oriY;\n")

for i in range(0, nbrOfRec):

    file.write(str(oriP[i]) + ';')
    file.write(str(oriR[i]) + ';')
    file.write(str(oriY[i]) + ';\n')

file.close()
which returns with a still Sense HAT:

Code: Select all

oriP;oriR;oriY;
7.7;-3.8;3.5;
4.7;1.5;0.2;
7.3;1.1;1.2;
...
so I assume there is still a problem... Perhaps did I poorly "translated" your code and I am missing things.

What are the essential registers to set ?

EDIT : following your first link, I've just read the accelerometer to g article, and it's really good ! It allowed me to understand why we use 65 535 and the link between range et sensitivity, thanks !

The article triggers a question : I understand the "4,000 MilliGs / 65,535 = 0.061" calculus to obtain the accelerometer sensitivity (range is +/- 2 g, unit is mg/LSB, output is 16 bits => (2 * 2 * 1000) / (2^16) = 0.061), but I tried the same calculus with the gyroscope sensitivity and obtained results differents than those of the datasheet, for example : (245 * 2 * 1000) / (2^16) = 7.48 mg/LSB, while the datasheet states that the gyroscope sensitivity is 8.75 mg/LSB. What did I do wrong ?
Last edited by Grozhibou on Wed Feb 22, 2017 2:47 pm, edited 3 times in total.
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

User avatar
davidcoton
Posts: 3784
Joined: Mon Sep 01, 2014 2:37 pm
Location: Cambridge, UK

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 2:18 pm

Grozhibou wrote:
davidcoton wrote:With your diagram, the x-axis should show a constant acceleration proportional to the speed of rotation
And then become constant when the top angular speed is reached and constant, right ?
Yes, constant but non-zero. You are measuring the centripetal acceleration that keeps the Pi moving in a circle rather than a straight line.
When the angular velocity changes then the y-axis acceleration will also be non-zero until a new steady speed is reached.
Signature retired

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 2:50 pm

davidcoton wrote:[Yes, constant but non-zero. You are measuring the centripetal acceleration that keeps the Pi moving in a circle rather than a straight line.
When the angular velocity changes then the y-axis acceleration will also be non-zero until a new steady speed is reached.
Ok, I see, thanks for the explanation ! It's hard to estimate this kind of forces, even when I'm thinking of being in car driving on a perfect circular road like the RPi is on a circular platform !
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

User avatar
davidcoton
Posts: 3784
Joined: Mon Sep 01, 2014 2:37 pm
Location: Cambridge, UK

Re: Issues with accelero and gyro sensitivity

Wed Feb 22, 2017 4:40 pm

The classic thought experiment is to consider a stone tied to a string, being spun in a circle.
What forces are acting?
Obviously gravity, but not particularly relevant to the motion of the stone (first approximation :D)
Around the circumference of the circle? Basically nothing, because the string would bend if it tried to exert force that way.
But the string is in tension, it is constantly pulling the stone towards the centre of the circle.
Consequently we know that the acceleration of a stone moving at constant speed around a circle is directed towards the centre of the circle.
Signature retired

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Thu Feb 23, 2017 9:44 am

davidcoton wrote:The classic thought experiment is to consider a stone tied to a string, being spun in a circle.
What forces are acting?
Obviously gravity, but not particularly relevant to the motion of the stone (first approximation :D)
Around the circumference of the circle? Basically nothing, because the string would bend if it tried to exert force that way.
But the string is in tension, it is constantly pulling the stone towards the centre of the circle.
Consequently we know that the acceleration of a stone moving at constant speed around a circle is directed towards the centre of the circle.
Thanks for the detailed explanation ! There is also an article on Wikipedia that provides calculus :)

Back to my code, I started another one from the beginning, to identify step by step where my problem is, using mwilliams03's code.
For the moment, I just try to obtain the right raw values of the gyro with I2C, but I still don't manage to get coherent values...

The actual code is :

Code: Select all

import smbus
from LSM9DS1 import *

bus = smbus.SMBus(1)

# Turning on the gyroscope.
bus.write_byte_data(CIRC_ADDR, 0x10, 0b10100000)

def readGyr(outL, outH):

    gyrL = bus.read_byte_data(CIRC_ADDR, outL)
    gyrH = bus.read_byte_data(CIRC_ADDR, outH)

    gyrCom = gyrL | gyrH << 8

    return gyrCom if gyrCom < 32767 else gyrCom - 65535

# Arrays for the 3 axis orientation (pitch, roll, yaw).
oriP = []
oriR = []
oriY = []

# The program will run until it has reached the specified number of recordings.
for i in range(0, 1000):
    
    oriP.append(readGyr(OUT_X_L_G, OUT_X_H_G))
    oriR.append(readGyr(OUT_Y_L_G, OUT_Y_H_G))
    oriY.append(readGyr(OUT_Z_L_G, OUT_Z_H_G))

file = open("RawValuesI2C.csv", 'w')

file.write("oriP;oriR;oriY;\n")

for i in range(0, 1000):
    
    file.write(str(oriP[i]) + ';' + str(oriR[i]) + ';' + str(oriY[i]) + ';\n')

file.close()
from LSM9DS1 import * is a custom file that only contains hexadecimal addresses.
This code returns :

Code: Select all

oriP;oriR;oriY;
901;108;87;
887;117;66;
859;119;57;
...
So the raw values clearly aren't right, and I think the problem comes from my I2C initialization : I chose the +/- 245 dps range, but I know nothing about setting the output data rate or bandwith values...

Also, I've noticed that in the LSM9DS1 datasheet, some register share the same address (0x22 for CTRL_REG8 and CTRL_REG3_M, or 0x20 for CTRL_REG1_M and CTRL_REG6_XL for example) : is this normal ? How to make the difference when I write at a "shared" address ?
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

Grozhibou
Posts: 36
Joined: Wed Jul 16, 2014 12:01 pm

Re: Issues with accelero and gyro sensitivity

Wed Mar 01, 2017 10:08 am

Restarting from zero to understand what I do, I have the following short Python 3 code to get raw acceleration values :

Code: Select all

import smbus

# /dev/i2c-1
bus = smbus.SMBus(1)

# Leaving ODR power-down mode to 476 Hz.
bus.write_word_data(0x6a, 0x20, 0xa0)

while True:
    print("X: " + str(bus.read_word_data(0x6a, 0x28)))
    print("Y: " + str(bus.read_word_data(0x6a, 0x2a)))
    print("Z: " + str(bus.read_word_data(0x6a, 0x2c)) + "\n")
With the RPi + Sense HAT being still, this code returns values like :

Code: Select all

X: 65086
Y: 65142
Z: 16084
And if I apply the conversion (* 0.000061), I have :

Code: Select all

X: 3.97
Y: 3.97
Z: 0.98
0.98 is close to 1 and is the same value I have with the Sense HAT API, so I assume this one is ok ; but why the 3.97 values ?

I don't understand how I get this 3.97 when I'm in a +/- 2 g range and the value of the Z axis is correct with the same conversion.

EDIT : adding an if value >= 32767: value -= 65535 like in mwilliams03's code seems to solve the problem, as I now have values like :

Code: Select all

X: -461
Y: -377
Z: 16200
Which gives, once converted :

Code: Select all

X: -0.03
Y: -0.02
Z: 0.99
Now I have to do the same for the gyroscope !

Thank you all for your help and patience !
Raspberry Pi 3 + RetroPie, Raspberry Pi 3 + Sense HAT or Framboisedorf, Raspberry Pi 2 + OpenELEC

Return to “Astro Pi”