Байты I2C получены не в порядке. Малина Pi Python SMBus - программирование
Подтвердить что ты не робот

Байты I2C получены не в порядке. Малина Pi Python SMBus

Я настраиваю малину Pi для записи данных (CO2, влажность и температура) с сенсора Sensirion SCD30. Мой код находится в python3, используя библиотеку SMBus для связи с датчиком через контакты I2C в Pi GPIO. Существует команда, чтобы определить, готов ли датчик к отправке данных.

Ссылка на спецификацию интерфейса SCD30

Ссылка на библиотеку SCD30 для arduino от 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 вторым байтом, но я хотел бы найти основную проблему.

Я отправляю и получаю данные I2C, используя библиотеку smbus. Это мой код для отправки команд и чтения данных:

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 байтов, показанных выше.

4b9b3361

Ответ 1

Какие инструменты и навыки у вас есть?

(Моя первая реакция состояла в том, чтобы искать ошибки SCD30, но я не могу их найти, и быстрый поиск в Интернете не выявляет подобных проблем)

Если у вас есть осциллограф или логический анализатор, посмотрите на SCL и SDA и убедитесь, что проблема находится на RPi (может также быть на датчике).

Можете ли вы заменить какие-либо компоненты HW для установки - просто чтобы исключить нечетную вероятность того, что что-то будет неисправным.

Можете ли вы переписать код на C (используя /dev/i2c-x) и посмотреть, не исчезла ли эта проблема - это либо скажет вам, что проблема связана либо с драйвером ядра для ведущего устройства I2C, проводки, чипа SCD30, либо в lib smbus или другое программное обеспечение, которое находится между вашим куском кода и драйвером ядра.

Удачи

Ответ 2

Может случиться так, что буфер, проходящий для чтения, не пуст и дает вам неустойчивые данные. Попробуйте очистить буфер (установить значение 0) перед чтением данных.

Ответ 3

Использование SMBus для этого устройства i2c неверно.

Вы должны сравнить SMBus 6.5.7 Block Read (который является read_i2c_block_data, если я прав) в read_i2c_block_data данных вашего устройства. 1.3.4 Получить статус готовности. Они отличаются друг от друга, поскольку SMBus отправляет командный байт.

Интерфейс устройства выглядит достаточно просто, так как вам не нужна библиотека. Просто откройте i2c-dev, сделайте I2C_SLAVE ioctl для установки адреса, затем напишите два байта и прочитайте три байта. Документ интерфейса устройства i2c ядра сообщает подробности.

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 " мастер должен поддерживать растяжение часов ". Без растяжения часов вы должны быть готовы к ошибкам. Существуют способы растяжения часов на Pi с использованием i2c-gpio. Мне жаль, что у меня не было времени, чтобы просмотреть подробности здесь, но google находит хотя бы некоторые инструкции.

Ответ 4

Может возникнуть проблема резистора подтягивания.

См. Http://www.ti.com/lit/an/slva689/slva689.pdf

Вычисление резистора вытягивания. Сильное подтягивание (малый резистор) препятствует тому, чтобы штырь I2C на IC мог работать на низком уровне. Уровень VOL, который может быть прочитан как допустимый логический минимум входными буферами IC, определяет минимальное сопротивление подтягивания [RP (min)]. RP (min) является функцией VCC, VOL (max) и IOL

Rp (min) = (Vcc - Vol (max))/Iol

Максимальное сопротивление подтягивания ограничено емкостью шины (Cb) из-за стандартных значений времени нарастания I2C. Если значение резистора подтягивающего устройства слишком велико, линия I2C может не подняться до логического максимума до того, как будет выведена на низком уровне. Реакция RC-схемы на шаг напряжения амплитуды VCC, начиная с момента времени t = 0, характеризуется постоянной времени RC.