Hello, im using a raspberry pi 4, the MMA8452Q with I2C and im using the pigpio python library.
I already have some code which produces sensible output but it only works with 2g mode. Now i have some problems with implementing 4g and 8g mode. The output just doesnt make sense.
I will show the relevant parts of my working code and my code for 2g/4g/8g mode. It would be very nice if someone could give me some pointers how to improve my working code or fix the bug in the other code.
My Code:
def twos_comp(val, bits):
"""compute the 2's compliment of int value val"""
if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
val = val - (1 << bits) # compute negative value
return val
def readACCx():
comp_acc_x2 = pi.i2c_read_byte_data(acc_sensor, OUT_X_MSB)
comp_acc_x1 = pi.i2c_read_byte_data(acc_sensor, OUT_X_LSB)
acc_combined = ((comp_acc_x2 << <li-emoji id="lia_smiling-face-with-sunglasses" src=" " class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"></li-emoji> | comp_acc_x1) >>4
acc_combined = twos_comp(acc_combined, 12)
return acc_combined
def readACCy():
comp_acc_y2 = pi.i2c_read_byte_data(acc_sensor, OUT_Y_MSB)
comp_acc_y1 = pi.i2c_read_byte_data(acc_sensor, OUT_Y_LSB)
acc_combined = ((comp_acc_y2 << <li-emoji id="lia_smiling-face-with-sunglasses" src=" " class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"></li-emoji> | comp_acc_y1) >>4
acc_combined = twos_comp(acc_combined, 12)
return acc_combined
def readACCz():
comp_acc_z2 = pi.i2c_read_byte_data(acc_sensor, OUT_Z_MSB)
comp_acc_z1 = pi.i2c_read_byte_data(acc_sensor, OUT_Z_LSB)
acc_combined = ((comp_acc_z2 << <li-emoji id="lia_smiling-face-with-sunglasses" src=" " class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"></li-emoji> | comp_acc_z1) >>4
acc_combined = twos_comp(acc_combined, 12)
return acc_combined
while (time.time()-start_time) < RUNTIME:
try:
xAccl = readACCx()
yAccl = readACCy()
zAccl = readACCz()
# Output data to screen
print("Acceleration in X-Axis : ", xAccl/1000)
print("Acceleration in Y-Axis : ", yAccl/1000)
print("Acceleration in Z-Axis : ", zAccl/1000)
time.sleep(1)
except pigpio.error as e:
print("error: %s", e)
time.sleep(1)
The other code:
def readACCx():
comp_acc_x2 = pi.i2c_read_byte_data(acc_sensor, OUT_X_MSB)
comp_acc_x1 = pi.i2c_read_byte_data(acc_sensor, OUT_X_LSB)
acc_combined = ((comp_acc_x2 << <li-emoji id="lia_smiling-face-with-sunglasses" src=" " class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"></li-emoji> | comp_acc_x1) >>4
if (comp_acc_x2 > 0x7F):
acc_combined = ~acc_combined +1
acc_combined *= -1
return acc_combined
def readACCy():
comp_acc_y2 = pi.i2c_read_byte_data(acc_sensor, OUT_Y_MSB)
comp_acc_y1 = pi.i2c_read_byte_data(acc_sensor, OUT_Y_LSB)
acc_combined = ((comp_acc_y2 << <li-emoji id="lia_smiling-face-with-sunglasses" src=" " class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"></li-emoji> | comp_acc_y1) >>4
if (comp_acc_y2 > 0x7F):
acc_combined = ~acc_combined +1
acc_combined *= -1
return acc_combined
def readACCz():
comp_acc_z2 = pi.i2c_read_byte_data(acc_sensor, OUT_Z_MSB)
comp_acc_z1 = pi.i2c_read_byte_data(acc_sensor, OUT_Z_LSB)
acc_combined = ((comp_acc_z2 << <li-emoji id="lia_smiling-face-with-sunglasses" src=" " class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"></li-emoji> | comp_acc_z1) >>4
if (comp_acc_z2 > 0x7F):
acc_combined = ~acc_combined +1
acc_combined *= -1
return acc_combined
while (time.time()-start_time) < RUNTIME:
try:
xAccl = readACCx()
yAccl = readACCy()
zAccl = readACCz()
cx = float(xAccl)/float(1<<12)/(2*SCALE) #SCALE = 2
cy = float(yAccl)/float(1<<12)/(2*SCALE)
cz = float(zAccl)/float(1<<12)/(2*SCALE)
# Output data to screen
print("Acceleration in X-Axis : ", cx)
print("Acceleration in Y-Axis : ", cy)
print("Acceleration in Z-Axis : ", cz)
time.sleep(1)
except pigpio.error as e:
print("error: %s", e)
time.sleep(1)
Solved! Go to Solution.
Ok i managed to solve the problem. The Scale numbers were (hidden) at on of the last pages of the sensor datasheet as mg values. Even if i use 4G mode the output stays the same if the sensor lays flat. Sadly i cant really swing my arm at 4G to test the sensor
SCALE_2G = 1/1000
SCALE_4G = 2/1000
SCALE_8G = 3.9/1000
def readACCx():
comp_acc_x2 = pi.i2c_read_byte_data(acc_sensor, OUT_X_MSB)
comp_acc_x1 = pi.i2c_read_byte_data(acc_sensor, OUT_X_LSB)
acc_combined = ((comp_acc_x2 << | comp_acc_x1) >>4
return acc_combined if acc_combined < 2048 else acc_combined - 4096
pi.i2c_write_byte_data(acc_sensor, XYZ_DATA_CFG, 0b00000001) # Set to 4g scale
while (time.time()-start_time) < RUNTIME:
try:
xAccl = readACCx()
yAccl = readACCy()
zAccl = readACCz()
#Calculations are here
xAccl = xAccl * SCALE_4G
yAccl = yAccl * SCALE_4G
zAccl = zAccl * SCALE_4G
# Output data to screen
print("Acceleration in X-Axis : ", xAccl)
print("Acceleration in Y-Axis : ", yAccl)
print("Acceleration in Z-Axis : ", zAccl)
time.sleep(1)
except pigpio.error as e:
print("error: %s", e)
time.sleep(1)
Ok i managed to solve the problem. The Scale numbers were (hidden) at on of the last pages of the sensor datasheet as mg values. Even if i use 4G mode the output stays the same if the sensor lays flat. Sadly i cant really swing my arm at 4G to test the sensor
SCALE_2G = 1/1000
SCALE_4G = 2/1000
SCALE_8G = 3.9/1000
def readACCx():
comp_acc_x2 = pi.i2c_read_byte_data(acc_sensor, OUT_X_MSB)
comp_acc_x1 = pi.i2c_read_byte_data(acc_sensor, OUT_X_LSB)
acc_combined = ((comp_acc_x2 << | comp_acc_x1) >>4
return acc_combined if acc_combined < 2048 else acc_combined - 4096
pi.i2c_write_byte_data(acc_sensor, XYZ_DATA_CFG, 0b00000001) # Set to 4g scale
while (time.time()-start_time) < RUNTIME:
try:
xAccl = readACCx()
yAccl = readACCy()
zAccl = readACCz()
#Calculations are here
xAccl = xAccl * SCALE_4G
yAccl = yAccl * SCALE_4G
zAccl = zAccl * SCALE_4G
# Output data to screen
print("Acceleration in X-Axis : ", xAccl)
print("Acceleration in Y-Axis : ", yAccl)
print("Acceleration in Z-Axis : ", zAccl)
time.sleep(1)
except pigpio.error as e:
print("error: %s", e)
time.sleep(1)
Hello,
I hope all is great with you.
First, please note that the MMA8452Q device is obsolete (End of life). You may consider it for further design.
In this case, I would like to recommend the example code below. You may use it as a reference for your design. please review the device configuration and compare it with you code.
MMA8451Q - Bare metal example project
I hope this information helps.
Regards,
David
Hey thanks for your reply. I noticed too that this sensor is at End of Life but im a little bit under time pressure and cant wait for something else to arrive.
This code is very good, the only question i would have is what the SENSITIVITY_2G variable is since it isnt declared in the code and is very important for the conversion. Do you know this?