Разница I2 C Датчик считывания Raspberry Pi и Arduino - PullRequest
0 голосов
/ 18 марта 2020

Я использую датчик потока Sensirion SFM3300 и могу прочитать правильные значения с помощью Arduino с помощью следующего кода (I2 C):

#include <Wire.h>

void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Serial.begin(115200);
  Wire.beginTransmission(byte(0x40));
  Wire.write(byte(0x10));
  Wire.write(byte(0x00));
  Wire.endTransmission();
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(100);
  Wire.requestFrom(0x40,2);
  uint16_t a = Wire.read();
  uint8_t  b = Wire.read();
  a = (a<<8) | b;
  float flow = ((float)a - 32768) / 120;
  Serial.println(flow);
}

Но используя Raspberry Pi, я написал почти тот же код, надеясь, что он также будет работать. Это код:

from smbus2 import SMBus
import time
import numpy as np

address=0x40
bus = SMBus(1)

def write(value):
    bus.write_byte(address,value)

write(0x10)
write(0x00)

while True:
    time.sleep(0.1)
    a = np.uint16(bus.read_byte(0x40))
    b = np.uint8(bus.read_byte(0x40))
    a = (a<<8) | b
    flow = (float(a)-32768)/120
    print(flow)

Код действительно выглядит так же, но я получаю только -273,06666666666 в качестве возвращаемого значения. Кто-нибудь знает, где есть различия между Raspberry Pi и Arduino I2 C и может помочь мне получить правильные значения на Pi?

Ответы [ 3 ]

1 голос
/ 19 марта 2020

Вы можете использовать метод read_i2c_block_data(addr, offset, numOfBytes), чтобы получить более 1 байта данных из i2 c. возвращаемые данные - это список байтов. Поэтому очень легко преобразовать в целое число.

Отредактировано на основе таблицы данных и эскиза Arduino

Вот полный код для Python, который должен соответствовать Arduino пример:

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)
0 голосов
/ 20 марта 2020

Я нашел рабочее решение. Было бы хорошо, если бы I2 C -эксперт мог бы сказать мне, почему следующий код работает вместо кода 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)
0 голосов
/ 18 марта 2020

Я не думаю, что ваш процесс чтения в python правильный. Чтение с порта 40 два раза отличается от чтения двух байтов с порта 40.

Я предлагаю использовать read_byte_data (0x40, 0, 2) и обработать это с помощью struct.unpack(">H").

...