11

我正在设置一个 Raspberry Pi 来记录来自 Sensirion SCD30 传感器的数据(CO 2、湿度和温度)。我的代码在 Python 3 中,使用 SMBus 库通过 Raspberry Pi GPIO 中的 I²C 引脚与传感器进行通信。有一个命令可以确定传感器是否准备好发送数据。

链接到 SCD30 接口数据表

Sparkfun 链接到 Arduino 的 SCD30 库

该值0x0202通过 I²C 发送,并返回三个字节的数据:

0x00 0x00 0x81 for data not ready
0x00 0x01 0xB0 for data ready

前两个字节是数据就绪值的 MSB 和 LSB。结合得当,它们应该是0x00000x0001

第三个字节是前两个字节的 CRC8。这是用 的多项式0x31和 的初始化计算的0xFF

大约一半的时间,字节以错误的顺序发送。而不是MSB LSB CRC它被发送MSB CRC LSB。例如,如果数据准备就绪,它可能会发送0x00, 0xB0, 0x01而不是0x00, 0x01, 0xB0. 我无法弄清楚为什么会发生这种情况,并且我担心发送数据时存在一些损坏或问题。我可以更改代码以识别 CRC 是否是第二个字节,但我想找出根本问题。

我正在使用smbus库发送和接收 I²C 数据。这是我发送命令和读取数据的代码:

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)

它将返回上面演示的三个字节的列表。

4

4 回答 4

4

你有什么样的工具和技能?

(我的第一反应是搜索 SCD30 勘误表,但我找不到,快速的网络搜索也没有发现任何类似的问题。)

如果您有示波器或逻辑分析仪,请查看 SCL 和 SDA,并确认问题出在 Raspberry Pi 上(也可能出在传感器上)。

您能否更换设置的任何硬件组件 - 只是为了消除出现故障的奇怪机会。

您能否用 C 重写代码(使用 /dev/i2c-x),看看问题是否仍然存在 - 这会告诉您问题出在 I²C 主控器的内核驱动程序、布线、SCD30 芯片或库中smbus或位于您的代码和内核驱动程序之间的其他软件。

祝你好运

于 2018-09-10T09:33:01.947 回答
1

SMBus 库不正确,因为 SCD30 需要比 Linuxi2c-dev库提供的更长的 I²C 命令。

我们成功地使用pigpiod通过 Python 与传感器对话。我们的 SCD30 代码和安装说明(以及时钟延长问题的解决方案)可以在 GitHub 上找到

于 2018-11-16T09:27:48.507 回答
0

对这个 I²C 设备使用 SMBus 是不对的。

您应该将SMBus 6.5.7 块读取(read_i2c_block_data如果我是对的)与您的设备数据表 1.3.4 获取数据就绪状态进行比较。它们是不同的,因为 SMBus 发送命令字节。

设备界面看起来很简单,您不需要库。只需打开i2c-dev,执行I2C_SLAVEioctl 设置地址,然后写入两个字节并读取三个字节。内核 I²C 设备接口文档提供了详细信息。

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)

要获取 ioctlI2C_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 在 Raspberry Pi 上进行时钟延长。很抱歉我没有时间在这里详细介绍,但谷歌至少找到了一些说明

于 2018-09-23T20:02:38.237 回答
0

可能是上拉电阻问题。

请参阅I²C 总线上拉电阻器计算

上拉电阻计算

强上拉(小电阻)可防止 IC 上的 I²C 引脚驱动为低电平。可由 IC 的输入缓冲器读取为有效逻辑低电平的 V OL电平决定了最小上拉电阻 [RP (min)]。RP (min) 是V CC、V OL (max) 和I OL的函数。

R p(min) = (V CC - V OL(max) ) / I OL

由于 I²C 标准上升时间规范,最大上拉电阻受总线电容 (C b ) 的限制。如果上拉电阻值太高,I²C 线在被拉低之前可能不会上升到逻辑高电平。从时间 t = 0 开始,RC 电路对幅度为 V CC的电压阶跃的响应由时间常数 RC表征。

于 2018-09-23T22:00:03.097 回答