I2C байт получен из строя Raspberry Pi Python SMBus - PullRequest
0 голосов
/ 08 сентября 2018

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

Ссылка на таблицу данных интерфейса 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 байта, показанные выше.

Ответы [ 5 ]

0 голосов
/ 16 ноября 2018

Библиотека SMBUS неверна, поскольку SCD30 требует более длинных команд I2C, чем предоставляет библиотека linux i2c-dev.

Мы успешно используем pigpiod для общения через питон с сенсором. Наш код для SCD30 и инструкции по установке (а также решения для проблемы растяжения часов) можно найти здесь, на Github .

0 голосов
/ 24 сентября 2018

Может быть проблема с подтягивающим резистором.

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

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

Rp (мин) = (Vcc - объем (макс)) / Iol

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

0 голосов
/ 18 сентября 2018

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

0 голосов
/ 23 сентября 2018

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

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

Интерфейс устройства выглядит достаточно простым, чтобы вам не требовалась библиотека. Просто откройте i2c-dev , выполните ioctl I2C_SLAVE, чтобы установить адрес, затем запишите два байта и прочитайте три байта. В документе Ядро 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 находит по крайней мере некоторые инструкции .

0 голосов
/ 10 сентября 2018

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

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

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

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

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

Удачи

...