我正在尝试使用python smbus模块从Arduino UNO读取数据到Raspberry Pi。我在smbus模块上找到的唯一文档是here。我不确定cmd在模块中的含义。我可以使用write将数据发送到Arduino。我写了两个简单的程序,一个用于读取,一个用于写入
写作的那个
import smbus
b = smbus.SMBus(0)
while (0==0):
var = input("Value to Write:")
b.write_byte_data(0x10,0x00,int(var))
读取的那个
import smbus
bus = smbus.SMBus(0)
var = bus.read_byte_data(0x10,0x00)
print(var)
Arduino代码是
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include <Wire.h>
LiquidCrystal lcd(8,9,4,5,6,7);
int a = 7;
void setup()
{
Serial.begin(9600);
lcd.begin(16,2);
// define slave address (0x2A = 42)
#define SLAVE_ADDRESS 0x10
// initialize i2c as slave
Wire.begin(SLAVE_ADDRESS);
// define callbacks for i2c communication
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}
void loop(){
}
// callback for received data
void receiveData(int byteCount)
{
Serial.println(byteCount);
for (int i=0;i <= byteCount;i++){
char c = Wire.read();
Serial.println(c);
}
}
// callback for sending data
void sendData()
{
Wire.write(67);
lcd.println("Send Data");
}
当我运行读取程序时,它每次都返回“33”。 Arduino返回调用sendData函数。
我使用的是Data Level Shifter,说明说它可能有点迟钝。
有没有人让这个工作?
答案 0 :(得分:11)
我设法启动了Arduino和Raspberry Pi之间的通信。两个使用两个5k上拉电阻连接(见page)。 arduino为每个请求在i2c总线上写一个字节。在Raspberry Pi上,每秒都会打印hello
。
Arduino代码:
#include <Wire.h>
#define SLAVE_ADDRESS 0x2A
void setup() {
// initialize i2c as slave
Wire.begin(SLAVE_ADDRESS);
Wire.onRequest(sendData);
}
void loop() {
}
char data[] = "hello";
int index = 0;
// callback for sending data
void sendData() {
Wire.write(data[index]);
++index;
if (index >= 5) {
index = 0;
}
}
Raspberry Pi上的Python代码:
#!/usr/bin/python
import smbus
import time
bus = smbus.SMBus(1)
address = 0x2a
while True:
data = ""
for i in range(0, 5):
data += chr(bus.read_byte(address));
print data
time.sleep(1);
在我的Raspberry Pi上,i2c总线为1.使用命令i2c-detect -y 0
或i2c-detect -y 1
验证您的Raspberry Pi是否检测到您的Arduino。
答案 1 :(得分:0)
我知道这是一篇过时的文章,但是我也取得了类似的成功,这似乎是我取得成功的血统。
很长时间以来,我一直在尝试将高RPM的计算工作转移到ATTiny85。我想将i2c请求上的RPM发送给Pi,而不是利用pi上的GPIO引脚中断和处理器时间。我今天终于做到了。这是我想出的。希望它可以帮助某人。如果有人想批评我的代码,那就来吧!
AtTiny 85 ino代码: 1 Mhz时钟速度
#include <TinyWire.h>
// _____
// RST -|o AT |- VDD (1.8-5.5v)
// A3/D3 -| Tiny|- D2
// A2/D4 -| 85 |- D1 (PWM) Can use analogWrite(pin_0_or_1, 255);
// GND -|_____|- D0 SDA (PWM) on pwm pins. (8 bit resolution=0-255)
#define own_address 0x26 // I2C address - change this in arduino code if changed
#define LED_pin 4
#define hallPin 3 //Melexis US5881 Hall Effect Sensor (Put a 50K Ohm pull up resistor
// between VDD and OUT pins
bool pulseState = false;
const int sample_rate_ms = 1000;
volatile uint32_t timeCheck = 0; //uint32_t is same as "unsigned long"
volatile uint32_t pulse1 = 0; //uint32_t is same as "unsigned long"
volatile uint32_t pulse2 = 0; //uint32_t is same as "unsigned long"
volatile uint8_t i2c_regs[2] = { 0, 0 };
volatile uint16_t RPM = 0;
volatile int counter = 0; //int is same as short
void setup() {
pinMode(LED_pin, OUTPUT); // If you want to enable an LED for status.
pinMode(hallPin, INPUT);
digitalWrite(LED_pin, HIGH); // Turn on the LED to indicate alive status
delay(2000); // Leave it on for 2 seconds
digitalWrite(LED_pin, LOW); // Turn it off
TinyWire.begin( own_address );
TinyWire.onRequest( onI2CRequest );
timeCheck = millis() + sample_rate_ms; // Set a time in the future to calculate
pulse1 = micros(); // Take an initial time hack
sei(); // Enable interrupts
}
void loop() {
if (digitalRead(hallPin)!=pulseState){ // Look at the hall state
pulseState = !pulseState; // If the pin isn't what it was before
if (!pulseState){ // Check if the pin was pulled low
pulse1 = pulse2; // Start time was previous pulse
pulse2 = micros(); // End time is this pulse
++counter; // Count pulses for determining 0 RPM
delay(0.0016); // Wait for 1/600th of a second (to
// prevent bounces) Should be good up
// to about 20,000rpm. This may not be
} // necessary but it works.
}
if(millis() > timeCheck){ // Every so often (once per second in my code)
// calculate RPM or lack thereof.
timeCheck = millis() + sample_rate_ms;
if (counter < 2){ // Less than 2 pulses, it's not rotating
RPM = 0;
}else{
RPM = 60000000 / (pulse2 - pulse1); // Revs per minute at 1000000 ticks per
// second using micros()
}
i2c_regs[0] = (RPM & 0xFF00) >>8; // Prepare the two bytes to send
i2c_regs[1] = (RPM & 0x00FF); // and place them into an array
counter = 0; // Reset the counter for the next loop
}
}
void onI2CRequest() {
TinyWire.send(i2c_regs, sizeof(i2c_regs)); // Send the two bytes over i2c
}
这是Raspberry Pi Python 3代码:
from smbus2 import SMBus, i2c_msg
# https://pypi.org/project/smbus2/
# To install on raspberry pi execute the following:
# pip install smbus2
# or
# sudo python3 -m pip install smbus2
# or
# sudo python3 -m pip3 install smbus2
import time
from datetime import datetime, timedelta
def bytes_to_int(bytes):
result = 0
for b in bytes:
result = result * 256 + int(b)
return result
def int_to_bytes(value, length):
# This routine is unused for now
result = []
for i in range(0, length):
result.append(value >> (i * 8) & 0xff)
result.reverse()
return result
last_good_data_at = datetime.utcnow()
with SMBus(1) as bus:
address=0x26
while True:
time.sleep(0.25)
try:
read = i2c_msg.read(address, 2)
bus.i2c_rdwr(read)
bytes = list(read)
except:
bytes = []
if bytes:
last_good_data_at = datetime.utcnow()
rpm = bytes_to_int(bytes)
print(f" " + "\r", end="")
print(f"RPM: {rpm} Bytes: {bytes}" + "\r", end="")
elif datetime.utcnow() > last_good_data_at + timedelta(seconds=10):
break
print("No data received for 10 seconds.")
print("Terminating program")