我正在设置Raspberry Pi,以记录来自Sensirion SCD30传感器的数据(CO2,湿度和温度)。我的代码在python3中,使用SMBus库通过Pi的GPIO中的I2C引脚与传感器通信。有一条命令可以确定传感器是否准备好发送数据。
Link to SCD30 interface datasheet
Link to SCD30 library for arduino by Sparkfun
值0x0202
通过I2C发送,并返回3个字节的数据:
0x00 0x00 0x81 for data not ready
0x00 0x01 0xB0 for data ready
前两个字节是数据就绪值的MSB和LSB。正确组合后,它们应分别为0x0000
和0x0001
。
第三个字节是前两个字节的CRC8。这是通过0x31
的多项式和0xFF
的初始化来计算的。
大约一半的时间,字节以错误的顺序发送。代替MSB LSB CRC
而是发送MSB CRC LSB
。例如,如果数据准备就绪,则可能发送0x00, 0xB0, 0x01
而不是0x00, 0x01, 0xB0
。我不知道为什么会这样,而且我担心在发送数据时会出现损坏或问题。我可以更改代码以识别CRC是否是第二个字节,但是我想找到潜在的问题。
我正在使用smbus库发送和接收I2C数据。这是我发送命令和读取数据的代码:
bus = smbus.SMBus(0)
I2C_ADDRESS = 0x61
def sendCommand(self, cmd): # sends a 2 byte command (cmd)
data = [0]*2
data[0] = cmd >> 8 # splits 2 byte command into MSB and LSB
data[1] = cmd & 0xFF
bus.write_i2c_block_data(I2C_ADDRESS, data[0], data[1:])
def readRegister(self, reg, length): # sends 2 byte command (reg) and receives (length) bytes
sendCommand(reg)
data = bus.read_i2c_block_data(I2C_ADDRESS, 0, length)
return data
对于上面给出的示例,我将运行以下代码:
ready = readRegister(0x0202, 3) # returns a list of 3 bytes
print(ready)
并返回上面演示的3个字节的列表。
答案 0 :(得分:4)
您拥有什么样的工具和技能?
(我的第一反应是搜索SCD30勘误,但我找不到任何内容,快速的网络搜索也没有发现任何类似的问题)
如果您有示波器或逻辑分析仪,请查看SCL和SDA并确认问题出在RPi上(也可能在传感器上)。
您可以更换设置的任何硬件组件吗?只是为了消除出现故障的几率。
您能否用C重写代码(使用/ dev / i2c-x),并查看问题是否仍然存在-这可以告诉您问题出在I2C主站的内核驱动程序,接线,SCD30芯片中还是在位于您的代码段和内核驱动程序之间的lib smbus或其他软件。
祝你好运
答案 1 :(得分:1)
SMBUS库不正确,因为SCD30需要的I2C命令比linux i2c-dev库提供的更长。
我们成功使用pigpiod通过python与传感器进行对话。我们的SCD30代码和安装说明(以及时钟延长问题的解决方案)可以在here on Github中找到。
答案 2 :(得分:0)
可能发生的情况是,传递用于读取的缓冲区不为空,并给您不稳定的数据。 读取数据之前,请尝试清除缓冲区(将值设置为0)。
答案 3 :(得分:0)
为此i2c设备使用SMBus是不正确的。
您应该将SMBus 6.5.7块读取(如果我正确的话,应该是read_i2c_block_data
)与设备数据表1.3.4的数据就绪状态进行比较。它们与SMBus发送命令字节不同。
设备界面看起来足够简单,您不需要库。只需打开 i2c-dev ,执行I2C_SLAVE
ioctl来设置地址,然后写入两个字节并读取三个字节。 kernel i2c device interface文档介绍了详细信息。
I2C_SLAVE=0x703
with open('/dev/i2c-1', 'r+b') as f:
fcntl.ioctl(f, I2C_SLAVE, 0x61)
f.write(b'\2\2')
data = f.read(3)
要获取ioctl I2C_SLAVE
值,请编译一个小的C程序以打印它。
#include <stdio.h>
#include <linux/i2c-dev.h>
int main() { printf("%#x\n", I2C_SLAVE); return 0; }
类似于cc file.c && ./a.out
的值。
数据表确实在1.1中说:“ 主机必须支持时钟延长”。没有时钟延长,您必须为错误做好准备。有几种方法可以使用i2c-gpio在Pi上进行时钟延长。抱歉,我没有时间在这里详细说明,但是Google至少找到了some instructions。
答案 4 :(得分:0)
可能是上拉电阻器问题。
请参见http://www.ti.com/lit/an/slva689/slva689.pdf
上拉电阻计算 强上拉电阻(小电阻器)会阻止IC上的I2C引脚驱动为低电平。 VOL水平 IC的输入缓冲器可以将其读取为有效逻辑低,从而确定最小上拉 阻力[RP (分钟)]。 RP (min)是VCC,VOL(max)和IOL的函数
Rp(min)=(Vcc-Vol(max))/ Iol
最大上拉电阻受总线电容(Cb )由于I2C标准的上升时间 规格。如果上拉电阻值太高,则I2C线可能在此之前未上升到逻辑高电平。 拉低。从时间t = 0开始,RC电路对幅度VCC的电压阶跃的响应为 以时间常数RC为特征。