2016-03-23 4 views
1

Ich habe ein Python-Skript, das mit einem Arduino über serielle kommuniziert. Es funktioniert wie erwartet auf meinem Computer, aber wenn ich das Skript auf meinem Raspberry Pi ausführe, funktioniert es nicht. Es bleibt nach dem Ausdruck "Gesendet: 1" hängen. Ich denke, es ist fest, warten auf ein Byte aus dem Arduino (erste Zeile von sendValue). Ich weiß jedoch nicht, warum das passiert, da es gut funktioniert, wenn ich es von meinem Computer oder dem seriellen Monitor des Pi aus starte.Python-Code mit Arduino über serielle Schnittstelle funktioniert nicht auf Raspberry Pi

Python-Skript:

import serial 
ser = serial.Serial('/dev/ttyACM0', 9600) 

def sendValue(value): 
    ser.read(1) # Arduino will send one byte when it's ready for the value 
    ser.write(value) # Send value 
    print("Sent: {}".format(value)) 
    return; 

ser.write('1') # Select function '1' 
print("Sent: 1") 

sendValue('5000') # Send 1st parameter to function '1' 
sendValue('4000') # Send 2nd parameter to function '1' 

while True: 
    print(ser.readline()) 

Arduino Code:

int task = 0; 

int val = 0; 
int val2 = 0; 
int val3 = 0; 

void task1(int length){ 
    Serial.println(length); 
    digitalWrite(13, HIGH); 
    delay(length); 
    digitalWrite(13, LOW); 
} 

void task2(int length1, int length2){ 
    Serial.print("Running task2 with parameters "); 
    Serial.print(length1); 
    Serial.print(" and "); 
    Serial.println(length2); 
    digitalWrite(13, HIGH); 
    delay(length1); 
    digitalWrite(13, LOW); 
    delay(500); 
    digitalWrite(13, HIGH); 
    delay(length2); 
    digitalWrite(13, LOW); 
} 

void waitForSerial(){ 
    while(Serial.available() == 0); 
} 

int getValue(){ 
    Serial.write(48); 
    waitForSerial(); 
    return Serial.parseInt(); 
} 

int getCommand(){ 
    if(Serial.available() == 0){ 
     return -1; 
    } 

    String in = ""; 

    in += (char)Serial.read(); 

    return in.toInt(); 
} 

void setup() { 
    Serial.begin(9600); 
    pinMode(13, OUTPUT); 
} 

void loop() { 
    task = getCommand(); 

    switch(task){ 
     case 0: 
      val = getValue(); 
      task1(val); 
      val = 0; 
      break; 
     case 1: 
      val = getValue(); 
      val2 = getValue(); 

      task2(val, val2); 
      val = val2 = 0; 
      break; 
    } 
} 

Ich habe versucht, anstelle des ser.read(1) eine Verzögerung setzen, wo ich denke, es ist stecken zu bleiben, aber das immer noch nicht funktioniert.

Ich konnte nicht entscheiden, ob dies auf die Himbeer-Pi-Community oder Arduino-Community gesetzt werden soll, also lege ich es hier.

Antwort

1

Sie können ein Problem mit dem Auto-Reset Arduino bezogen haben. Wenn das Arduino zurückgesetzt wird, dauert es einige Sekunden, bis es neu gestartet wird und das Hauptprogramm (loop()) gestartet wird. Wenn Sie eine Verbindung mit einem Arduino mit einem Unix-Betriebssystem (z. B. Raspberry Pi) herstellen, wird der automatische Reset ausgelöst. Wenn Ihr Python-Skript nach der Verbindung sofort Daten an das Arduino sendet, werden diese Daten möglicherweise vom Bootloader anstelle des Arduino-Prozessorcodes erfasst, da der Prozessor nicht bereit ist. Daher verhält sich das Arduino wie nichts. Dieses Verhalten tritt möglicherweise nicht auf, wenn Sie das Arduino unter Windows testen. Einige Windows-Konfigurationen lösen bei der ersten Verbindung kein automatisches Zurücksetzen aus, bei der seriellen Überwachung nicht.

Meine Lösung ist einfach eine Verzögerung von 5 Sekunden nach dem Erstellen der seriellen Verbindung in Ihrem Python-Skript hinzuzufügen, aber bevor Daten übertragen werden. Wenn dies das Problem löst, können Sie mehr über Lösungen erfahren, um dem Host mitzuteilen, wann das Arduino bereit ist. Beispielsweise können Sie eine Zeile zu dem Host an dem Ende des setup()-Abschnitts der Arduino-Skizze (Serial.println('READY');) drucken. Sie können auch ein paar Zeilen Code setzen, die die integrierten LED blinken am Ende der setup() Routine, als visueller Hinweis für die Fehlersuche macht:

pinMode(13, OUTPUT); 
digitalWrite(13, HIGH); 
delay(150); 
digitalWrite(13, LOW); 
delay(150); 
digitalWrite(13, HIGH); 
delay(150); 
digitalWrite(13, LOW); 

Wenn Sie die Doppel blinken sehen, wissen Sie, der Prozessor bereit, Kommunikation von Ihrem Host-Programm zu erhalten.

+0

Sie sagten, ich sollte 'Serial hinzufügen.println ('READY') 'zu' setup() '. Wird 'setup()' jedes Mal ausgeführt, wenn ich eine Verbindung über eine serielle Verbindung herstelle? – Marcel

+0

Die 'setup()' Routine wird jedes Mal ausgeführt, wenn der Prozessor startet, was ist: 1) Einschalten, 2) Drücken der Reset-Taste auf der Platine, oder 3) Öffnen einer seriellen Verbindung über den eingebauten USB-Port (" Automatisches Zurücksetzen"). Mit Auto-Reset können Sie die Karte über die USB-Verbindung programmieren. Siehe Details [hier] (http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection) oder Google "Arduino Autoreset". – mhopeng

+0

Beachten Sie, dass in einigen Fällen ein Windows-Host das automatische Zurücksetzen nicht auslöst, Linux oder OS X jedoch immer. – mhopeng

1

Ein besserer Weg, dies zu tun wäre, die Tatsache zu verwenden, dass ein ungültiges Zeichen so Serial.parseInt() gegeben wird, Parsing stoppt.

Anfangszeichen, die keine Ziffern oder ein Minuszeichen sind, werden übersprungen; Das Parsen wird beendet, wenn für einen konfigurierbaren Timeout-Wert keine Zeichen gelesen wurden oder eine Nicht-Ziffer gelesen wird. Wenn keine gültigen Ziffern gelesen wurden, als das Timeout (siehe Serial.setTimeout()) auftritt, wird 0 zurückgegeben;

https://www.arduino.cc/en/Reference/ParseInt

Dann könnten Sie so etwas tun:

var1 = Serial.read(); 
var2 = Serial.read(); 
var3 = Serial.read(); 

und in Python:

ser.write('<number1>a<number2>a<number3>a') 
Verwandte Themen