【问题标题】:How to read pot connected to arduino from Rpi using python and i2c如何使用 python 和 i2c 从 Rpi 读取连接到 arduino 的锅
【发布时间】:2017-06-22 00:19:42
【问题描述】:

我正在尝试从连接到 Arduino 的电位计写入模拟读数,并使用 RPi 上的 python 的 I2C 读取这些值。我已经让 Arduino 到 Arduino 使用下面的代码工作。我似乎无法正确做的是从 Arduino 写入两个字节并从 RPi 读取两个字节。

Arduino 主代码:

#include <Wire.h>
#define SLAVE_ADDRESS 0x2a

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  Wire.requestFrom(SLAVE_ADDRESS, 2);    // request 2 bytes from slave
  byte loByte;
  byte hiByte;
  if(Wire.available() >= 2)    // slave may send less than requested
    { 
    hiByte = Wire.read();
    loByte = Wire.read();
    }
  int val = (hiByte << 8) + loByte;
  Serial.print("read value:");   
  Serial.println(val);
  delay(500);
}

Arduino Slave 代码:

#include <Wire.h>
#include <stdlib.h>
#define SLAVE_ADDRESS 0x2a
//#define potPin 0  
int readVal;
byte hi;
byte lo;


void setup()
{
// Communication I2C
  Wire.begin(SLAVE_ADDRESS);                
  Wire.onRequest(requestEvent); // register event

  Serial.begin(9600);
}

void loop()
{

readVal = analogRead(A2);
Serial.println(readVal);
hi = highByte(readVal);
lo = lowByte(readVal);
}

void requestEvent()
{

byte buf [2];

  buf [0] = hi;
  buf [1] = lo;

  Wire.write(buf, sizeof buf);  // send 2-byte response

}

我从 RPi 中得到的最接近的读数是:

RPi 主代码:

import smbus
import time
bus = smbus.SMBus(1)
address = 0x2a

while True:
    bus.write_byte(address, 1)
    number = bus.read_byte(address)
    print(number)
    time.sleep(1)   

Arduino从机代码:

#include <Wire.h>
#define SLAVE_ADDRESS 0x2a
int number = 0;
void setup() {
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
  }
void loop() {
  }
void receiveData(int byteCount){
  while(Wire.available()) { 
    number = Wire.read();
    number = analogRead(A2);
  }
}
void sendData(){
  Wire.write(number);
  }

我似乎能够得到 0-255,但在 255 之后该值又开始了。毫无疑问,有一种更精确的方式可以说我只得到一个字节的数据或类似的东西。最终,我希望将 2 个电位器连接到 Arduino,将读数输入 RPi。

【问题讨论】:

  • 请原谅这个愚蠢的问题,但是让从机将 int 拼接成两个字节有什么意义,只是通过 SPI?简单地发送 int 不就行了吗?

标签: python arduino raspberry-pi i2c


【解决方案1】:

感谢您的反馈。它帮助我更多地思考这个问题并进行更多挖掘。这就是我的工作。

Arduino 方面的写作:

#include <Wire.h>
#define SLAVE_ADDRESS 0x2a
#define pot1pin A2
#define pot2pin A3

byte pot1byte;
byte pot2byte;
void setup()
{
    Wire.begin(SLAVE_ADDRESS);
    Wire.onRequest(requestEvent);
}

void loop() {
    int pot1int = analogRead(pot1pin);
    int pot2int = analogRead(pot2pin);
    pot1byte = map(pot1int, 0, 1024, 0, 255);
    pot2byte = map(pot2int, 0, 1024, 0, 255);
}

void requestEvent()
{
    Wire.write(pot1byte);
    delay(30);
    Wire.write(pot2byte);
}

用于读取的 RPi 端:

import smbus
bus = smbus.SMBus(1)
address = 0x2a
while (1):
    block = bus.read_i2c_block_data(address, 0, 2) # Returned value is a list of 2 bytes
    print(block)

如您所见,我正在读取 2 个电位器,将输出转换为 0-255,写入 I2C 总线,然后读取 RPi 端的 2 个字节。我在测试期间确实必须更改 Arduino 延迟值,因为几分钟后我收到错误“IOError:[Errno 5] Input/output error”。现在也许我会回去,每个罐子写 2 个字节并读取 4 个字节,这样我就不会丢失和解析。

【讨论】:

    【解决方案2】:

    在 Arduino 上,analogRead 返回 0-1023 范围内的 int 值。在此硬件上,int 是两个字节。 但是,您在sendData 函数中使用的Wire.write 形式只写入一个单个 字节,丢弃部分整数。

    基本上有两种解决方案。

    最简单的方法是将analogRead 的返回值除以4 并将其转换为一个字节。使用Wire.write 将其发送出去。这确实会降低电位器值的分辨率,但它是一个非常简单的解决方案。

    另一个是通过网络发送一个整数值。由于您正在读取 RPi 上的字节,因此您无法知道您正在读取的是整数的第一个字节还是第二个字节。所以你可能不得不使用一个信号来指示一个两字节序列的开始。您还必须考虑两个平台的字节顺序。总而言之,这要复杂得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多