2017-02-04 2 views
0

Ich versuche, analoge Messwerte von einem Potentiometer zu einem Arduino schreiben und lesen Sie diese Werte mit I2C von Python auf einem RPi. Ich habe Arduino nach Arduino gebracht, um mit dem folgenden Code zu arbeiten. Was ich nicht korrekt zu tun scheint, schreibe zwei Bytes vom Arduino und lese zwei Bytes vom RPi.So lesen Pot von Arduino von Rpi mit Python und i2c

Arduino Master-Code:

#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 Code:

#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 

} 

Die nächstgelegene Ich habe von einem RPi bekommen, ist:

RPi Mastercode:

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) 

Ard uino Slave-Code:

#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); 
    } 

Ich scheine in der Lage zu sein, 0-255 zu bekommen, aber nach 255 beginnt der Wert wieder. Zweifellos gibt es einen präziseren Weg zu sagen, dass ich nur ein Byte Daten oder etwas in dieser Richtung bekomme. Letztendlich möchte ich 2 Töpfe mit dem Arduino verbunden haben, die Messwerte in das RPi einspeist.

+0

verzeihen Sie die dumme Frage, aber was ist der Punkt, den Slave ein * int * in zwei Bytes spleißen, nur um beide durch die * SPI * zu senden? würde es nicht funktionieren, indem man einfach das * int * sendet? –

Antwort

1

Auf Arduino gibt analogRead einen int Wert im Bereich 0-1023 zurück. Auf dieser Hardware ist ein int zwei Bytes. Das Formular Wire.write, das Sie in der sendData Funktion verwenden, schreibt jedoch nur ein einzelnes Byte, einen Teil der Ganzzahl zu verwerfen.

Es gibt grundsätzlich zwei Lösungen.

Am einfachsten wäre es, den Rückgabewert analogRead zu übernehmen, ihn durch 4 zu teilen und in ein Byte umzuwandeln. Senden Sie das mit Wire.write. Dies reduziert zwar die Auflösung des Pot-Meters, ist aber eine sehr einfache Lösung.

Die andere war, einen ganzzahligen Wert über die Leitung zu senden. Da Sie Bytes auf dem RPi lesen, können Sie nicht wissen, ob Sie das erste oder das zweite Byte einer Ganzzahl lesen. Sie müssten also wahrscheinlich ein Signal verwenden, um den Beginn einer Zwei-Byte-Sequenz anzuzeigen. Sie müssten auch die Endian-Ness der beiden Plattformen berücksichtigen. Alles in allem ist das viel komplizierter.

0

Danke für die Rückmeldung. Es half mir, ein wenig mehr durchzudenken und mehr zu graben. Das ist, was ich arbeite.

Arduino Seite zum Schreiben:

#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 Seite zum Lesen:

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) 

Wie Sie sehen, ich 2 Töpfe lesen, um die Ausgabe zu 0-255 Umwandlung in dem I2C Schreiben Bus und dann Lesen der 2 Bytes auf der RPi-Seite. Ich musste den Arduino-Verzögerungswert während des Testens ändern, weil ich nach einigen Minuten den Fehler "IOError: [Errno 5] Input/output error" erhielt. Jetzt werde ich vielleicht zurückgehen und 2 Bytes pro Pot schreiben und 4 Bytes lesen, damit ich nicht verliere und auflöse.

Verwandte Themen