Using Python smbus on Raspberry Pi - confused with syntax

I am trying to use python-smbus on a raspberry Pi to communicate with the MMA7660 accelerometer chip using I2C.

In the code below, I read the registers 0x00, 0x01, 0x02 and 0x03 of the chip, and I get the exact values ​​for all. Looking at the values ​​and tilting the chip, I see that they all correspond to register 0x00, the register of values ​​of X.

Output:

... 1 1 1 2 3 3 3 3 1 1 1 1 59 60 60 60 51 51 51 51 58 58 58 58 3 3 3 3 62 62 62 62 58 58 58 58 62 62 62 62 ... 

code:

  import smbus import time bus = smbus.SMBus(1) # I2C address for MMA7660 addr = 0x4C try: bus.write_byte_data(addr, 0x07, 0x00) bus.write_byte_data(addr, 0x06, 0x10) bus.write_byte_data(addr, 0x08, 0x00) bus.write_byte_data(addr, 0x07, 0x01) except IOError, err: print err while True: try: x = bus.read_byte_data(addr,0x00) y = bus.read_byte_data(addr,0x01) z = bus.read_byte_data(addr,0x02) tr = bus.read_byte_data(addr,0x03) print x, y, z, tr time.sleep(0.25) except: print 'exiting...' break 

Am I something wrong with smbus syntax? I looked at the documentation here .

I checked that the chip is working - I can communicate with it using Arduino and set the registers in the same order as above.

Update # 1 (June 28, 2013) :

According to Sylvain's comment, I connect the oscilloscope output for SDA / SCL lines for the following code:

 bus.write_byte(addr, 0x01) print bus.read_byte(addr) 

enter image description here

Update # 2:

I guess the known issue with I2C on Raspberry Pi is that there is no restart.

https://raspberrypi.stackexchange.com/questions/7138/mma8452-i2c-module

According to Linux SMBus specification:

 SMBus Read Byte: i2c_smbus_read_byte_data() ============================================ This reads a single byte from a device, from a designated register. The register is specified through the Comm byte. S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P 

But when I tried it, the osciiloscope clearly shows STOP (P) before restarting (S).

So, I think I’m not lucky that I used the I2C hardware on the Pi to talk to the MMA7760.

+4
source share
4 answers

if you read all the necessary registers immediately, it works fine:

 import smbus bus = smbus.SMBus(1) Register = bus.read_i2c_block_data(0x4c, 0x99,4) acc_x = Register[0]*1.0 acc_y = Register[1]*1.0 acc_z = Register[2]*1.0 acc_tilt = Register[3] 
+2
source

I am absolutely not sure if this is a problem, but according to the specifications of p22:

The MMA7660FC is read using its registration address internally stored as an address pointer, just as a stored register address is used as an address pointer for writing. The pointer is usually automatically incremented every time each byte of data is read using the same rules as for writing (table 5). Thus, the reading begins with the first setting of the device register address by writing (Figure 11), followed by a second start. Now the master can read "n" consecutive bytes from it, and the first byte of data is read from the register addressed by the address of the initialized register.

As I understand it, to "read" from the register, you need to start by writing the register address, and then blindly read the byte. I don't know if SMBus.read_byte_data takes care of this, but you can try it manually:

  bus.write_byte(addr,0x00) x = bus.read_byte(addr) bus.write_byte(addr,0x01) y = bus.read_byte_data(addr) bus.write_byte(addr,0x02) z = bus.read_byte(addr) bus.write_byte(addr,0x03) tr = bus.read_byte(addr) 

It might even work:

  bus.write_byte(addr,0x00) x = bus.read_byte(addr) y = bus.read_byte_data(addr) z = bus.read_byte(addr) tr = bus.read_byte(addr) 
+1
source

After looking at your example, as well as the class written for MMA7455, I was able to write the following:

 import smbus import time import os import math # Define a class for the accelerometer readings class MMA7660(): bus = smbus.SMBus(1) def __init__(self): self.bus.write_byte_data(0x4c, 0x07, 0x00) # Setup the Mode self.bus.write_byte_data(0x4c, 0x06, 0x10) # Calibrate self.bus.write_byte_data(0x4c, 0x08, 0x00) # Calibrate self.bus.write_byte_data(0x4c, 0x07, 0x01) # Calibrate def getValueX(self): return self.bus.read_byte_data(0x4c, 0x00) def getValueY(self): return self.bus.read_byte_data(0x4c, 0x01) def getValueZ(self): return self.bus.read_byte_data(0x4c, 0x02) mma = MMA7660() for a in range(1000): x = mma.getValueX() y = mma.getValueY() z = mma.getValueZ() print("X=", x) print("Y=", y) print("Z=", z) time.sleep(0.2) os.system("clear") 

That should do the trick.

0
source

The Raspberry PI PI I2C kernel driver did not support restarts for a specific time. However, the I2C kernel driver has been updated and now supports restarting, although this feature must be activated explicitly.

To set combined gears 'on'

sudo sh -c '/bin/echo Y > /sys/module/i2c_bcm2708/parameters/combined'

To set combined gears 'off'

sudo sh -c '/bin/echo N > /sys/module/i2c_bcm2708/parameters/combined'

Information found here: http://raspberrypi.znix.com/hipidocs/topic_i2c_rs_and_cs.htm

0
source

Source: https://habr.com/ru/post/1488252/


All Articles