Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 不同I2C传感器读数Raspberry Pi和Arduino_Python_Arduino_Raspberry Pi_I2c_Smbus - Fatal编程技术网

Python 不同I2C传感器读数Raspberry Pi和Arduino

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

我使用的是Sensirion SFM3300流量传感器,可以使用Arduino读取正确的值,代码如下(I2C):

#包括
无效设置(){
//将安装代码放在此处,以便运行一次:
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 of
printf()
调试类型:)啊,是的,答案中的建议很好。顺便问一下,你读过数据表了吗?谢谢你的建议。你的代码对我有帮助,但我认为问题出在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)