Python 不同I2C传感器读数Raspberry Pi和Arduino
我使用的是Sensirion SFM3300流量传感器,可以使用Arduino读取正确的值,代码如下(I2C):Python 不同I2C传感器读数Raspberry Pi和Arduino,python,arduino,raspberry-pi,i2c,smbus,Python,Arduino,Raspberry Pi,I2c,Smbus,我使用的是Sensirion SFM3300流量传感器,可以使用Arduino读取正确的值,代码如下(I2C): #包括 无效设置(){ //将安装代码放在此处,以便运行一次: Wire.begin(); 序列号开始(115200); Wire.beginTransmission(字节(0x40)); Wire.write(字节(0x10)); Wire.write(字节(0x00)); 导线端传动(); } void循环(){ //将主代码放在此处,以便重复运行: 延迟(100); 请求自(0
#包括
无效设置(){
//将安装代码放在此处,以便运行一次:
Wire.begin();
序列号开始(115200);
Wire.beginTransmission(字节(0x40));
Wire.write(字节(0x10));
Wire.write(字节(0x00));
导线端传动();
}
void循环(){
//将主代码放在此处,以便重复运行:
延迟(100);
请求自(0x40,2);
uint16_t a=Wire.read();
uint8_t b=Wire.read();
a=(a我认为python中的读取过程不正确。从端口40读取两次与从端口40读取两个字节不同
我建议使用read_byte_data(0x40,0,2)并使用struct.unpack(“>H”)
处理这些数据。您可以使用read_i2c_block_data(addr,offset,numobytes)
方法从i2c获取超过1个字节的数据。返回的数据是字节列表。因此很容易转换为整数
根据数据表和Arduino草图编辑
以下是与Arduino示例相匹配的Python完整代码:
from SMBus2 import SMBus
import time
offset = 32768
scale = 120
addr = 0x40
cmd = [0x10, 0x00]
with SMBus(1) as bus:
bus.write_i2c_block_data(addr, 0, cmd)
time.sleep(0.1)
block = bus.read_i2c_block_data(addr, 0, 3)
reading = block[0] * 256 + block[1]
crc = block[2] # should do some crc check for error
flow = (reading - offset)/scale
print(flow)
我找到了一个可行的解决方案。如果I2C专家能告诉我为什么下面的代码而不是上面的python代码可以工作,那就太好了
from fcntl import ioctl
from struct import unpack
from smbus import SMBus
address = 0x40
SMBus(1).write_byte_data(address,16,0)
i2c = open("/dev/i2c-1", "rb", buffering=0)
ioctl(i2c,0x0703,address)
i2c.read(3)
d0,d1,c = unpack('BBB', i2c.read(3))
d = d0 << 8 | d1
a = (float(d)-32768.)/120
print(a)
从fcntl导入ioctl
从结构导入解包
从smbus导入smbus
地址=0x40
SMBus(1).写入字节数据(地址,16,0)
i2c=打开(“/dev/i2c-1”,“rb”,缓冲=0)
ioctl(i2c,0x0703,地址)
i2c.读取(3)
d0,d1,c=拆包('BBB',i2c.读取(3))
d=d0预期的正确值是多少?我建议使用struct
unit,而不是需要丑陋的移位和/或方法的np。这可能是一个endianness问题。预期值应为0(无任何流)传感器应该对流量做出反应。但是在Raspbery上,我只能得到-273066666,有浮点数和没有浮点数。在这种情况下,我如何使用struct?请帮助我。先打印字节值,然后在计算之前查看结果。真的是101 ofprintf()
调试类型:)啊,是的,答案中的建议很好。顺便问一下,你读过数据表了吗?谢谢你的建议。你的代码对我有帮助,但我认为问题出在I2C总线上。你的代码我也得到了一个恒定的负值-273,…i2cset-y 1 0x40 0x10和i2cset-y 1 0x40 0x00,我试图开始测量SFM3300传感器。对于i2cget-y 1 0x40,我想读取一个字节,但我只得到0x00。我认为你的公式错了。你得到的是流量值,不需要减去32768再除以120。你得到-273的原因是因为值
=0,所以(0-32768)/120=-273.我已经编辑了我的代码。它来自官方数据表:根据数据表,你说Arduino代码可以工作,我编辑了我的答案以包含完整的python代码。同样,我不能测试它,因为我没有传感器和设置,你必须运行和调试它。我不知道为什么它不能在Raspberry Pi上工作。流程是仍然是-271,45(有流和无流)。块[0]的打印始终是0,块[1]194和块[2]37的打印。啊,i2cdev上linux上的i2c-dev.c
读取函数有一个关于为什么需要它的说明。什么ioctl()
所做的是让SDA浮动,如果存在从机,它将下拉SDA。这与运行linux命令i2cdetect-y1
检测i2caddr的效果相同。事实上,一旦在较新的Raspbian上运行i2cdetect-y1
一次(与早期版本相比),就不需要ioctl()
再编码,我提供的或您编写的普通SMBus代码可能会正常工作。
from SMBus2 import SMBus
import time
offset = 32768
scale = 120
addr = 0x40
cmd = [0x10, 0x00]
with SMBus(1) as bus:
bus.write_i2c_block_data(addr, 0, cmd)
time.sleep(0.1)
block = bus.read_i2c_block_data(addr, 0, 3)
reading = block[0] * 256 + block[1]
crc = block[2] # should do some crc check for error
flow = (reading - offset)/scale
print(flow)
from fcntl import ioctl
from struct import unpack
from smbus import SMBus
address = 0x40
SMBus(1).write_byte_data(address,16,0)
i2c = open("/dev/i2c-1", "rb", buffering=0)
ioctl(i2c,0x0703,address)
i2c.read(3)
d0,d1,c = unpack('BBB', i2c.read(3))
d = d0 << 8 | d1
a = (float(d)-32768.)/120
print(a)