Linux/Python praat niet met Arduino

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • vanaalten
  • Registratie: September 2002
  • Nu online
(ik twijfelde tussen het NOS, programmeer of elektronica subforum - ik denk dat hier de meeste ervaring zit die het alledrie beheerst, dus...)

Ik ben aan het hobbyen geslagen. Lange termijn doel: een Arduino aan een DIN kWh-meter in de meterkast, verbonden met een Linux machine; Linux-machine vraagt vanuit een Python script om de vijf minuten aan de Arduino hoeveel kWh er sinds de laatste vraag geproduceerd is. En van daaruit pushen naar pvoutput.org. Maar, zo ver is het nog lang niet, want bij de eerste horde struikel ik al:

Als eerste wil ik kijken of ik via USB kan communiceren - daarvoor een simpel Arduino-programma:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int incomingByte = 0;

void setup() {
    // initialize the digital pin as an output.
    // Pin 13 has an LED connected on most Arduino boards:
    pinMode(13, OUTPUT);
    digitalWrite(13,HIGH);
    Serial.begin(9600);               // opens serial port, sets data rate to 9600 bps
}

void loop() {
    if (Serial.available() > 0) {        // read the incoming byte
        incomingByte = Serial.read();
        if (incomingByte == 0) {
            digitalWrite(13, LOW);
        } else {
            digitalWrite(13,HIGH);
        }
    }
}

...dat dus heel simpel moet wachten op een USB commando: een '0' zet de LED uit, elk ander getal zet 'm aan. En het bijbehorende python script:
code:
1
2
3
4
5
6
7
8
9
10
import serial, time

try:
    ser = serial.Serial('/dev/ttyACM0', 9600, timeout=0.1)
except SerialException:
    print ("port already open")
else:
    time.sleep(1)
    ser.write(bytes(0))
    print ("Printed 0 to /dev/ttyACM0")

... en een vergelijkbaar stukje code met '1' in de laatste twee regels om een 1 te sturen.
Resultaat: de LED blijft aan (door setup code), wat ik ook stuur. (uiteraard kan ik het standaard 'Blink' voorbeeld goed uitvoeren en wijzigingen aan 'Blink' komen goed aan, ofwel: de basis van compileren en uploaden werkt)

Daarna maar naar een standaard voorbeeld overgegaan: Arduino Python communication via USB. Die zou een 'hello from python!' string naar de Arduino moeten sturen, diezelfde string terug ontvangen en printen.

Het Python-stukje heb ik een klein beetje aangepast: COM1 vervangen door /dev/ttpACM0 (dezelfde poortnaam die ik ook opgeef in de Makefile als bestemming voor het uploaden).
Resultaat: python-code blijft hangen in de arduino.readline regel.

Gekeken of er een probleem is met het port openen:
code:
1
2
3
4
try:
    ser = serial.Serial('/dev/ttyACM0', 9600, timeout=0.1)
except SerialException:
    print ("port already open")

... en die geeft geen 'port already open'. Lijkt dus goed te gaan.

Gekeken of er een probleem is met communicatie NAAR de arduino of ook terug, door de code aan te passen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void setup() {
    Serial.begin(9600);
}
void loop() {
    if(Serial.available() > 0) {
        char data = Serial.read();
        char str[2];
        str[0] = data;
        str[1] = '\0';
        Serial.print(str);
    } else {
        char str[4];
        str[0] = 'M';
        str[1] = 'v';
        str[2] = 'A';
        str[3] = '\0';
        Serial.print(str);
    }
}

Dus OF hij echo-t wat hij binnen krijgt, of hij gooit constant "MvA" via USB terug. En ook dan blijft het python-programma in de readline hangen.

Verkeerde device gebruikt, misschien? Onder /dev zie ik wat ttyS0/1/2/3 devices, maar die gaven geen verbinding als ik die probeerde. "/dev/ttyACM0" lijkt toch de enige kanshebber te zijn, andere serieele devices zie ik zo snel niet. Plus, die ttyACM0 doet het als ik die in de makefile opgeef.

Ofwel, ik weet het even niet meer - het is nogal basis dit, maar ik loop er op vast en zie even geen andere ideeen meer om te debuggen. Doe ik iets fout aan de Arduino-kant voor USB communicatie? Of toch aan de Python kant?

Wat gegevens:
  • Arduino Uno
  • Linux: Debian 'Jessie' (maar, package arduino-mk uit testing voor commandline compile & upload)
  • Python: 2.7.9-2
  • Disclaimer: nieuweling op gebied 'Arduino' en 'python'

Beste antwoord (via vanaalten op 10-01-2016 19:47)


  • SA007
  • Registratie: Oktober 2002
  • Laatst online: 06-10 16:32

SA007

Moderator Tweaking
De uno heeft RX en TX ledjes, zie je die wat doen?

Zie ook dat de tekst die je naar serieel gooit als hij niks ontvangt geen newline '\n' bevat.
De Python code staat te wachten op een newline (met readline).

Alle reacties


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • SA007
  • Registratie: Oktober 2002
  • Laatst online: 06-10 16:32

SA007

Moderator Tweaking
De uno heeft RX en TX ledjes, zie je die wat doen?

Zie ook dat de tekst die je naar serieel gooit als hij niks ontvangt geen newline '\n' bevat.
De Python code staat te wachten op een newline (met readline).

Acties:
  • 0 Henk 'm!

  • vanaalten
  • Registratie: September 2002
  • Nu online
Ah, goede tip, dat helpt al iets: met een newline erbij in de Arduino-code gaat de Python-code oneinding lang "MvA" printen. Mooi, da's de helft opgelost!

Nu die "MvA" prints er uitgehaald, zodat ik kan zien of er ook de gewone 'hello from python!' teruggestuurd wordt, maar nee - ook niet als ik daar wat "\n" tussen zet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
void setup() {
    Serial.begin(9600);
}
void loop() {
    if(Serial.available() > 0) {
        char data = Serial.read();
        char str[3];
        str[0] = data;
        str[1] = '\n';
        str[2] = '\0';
        Serial.print(str);
    }
}

... dus die zou als het goed zou werken, "hello from python!" met elke letter op een nieuwe regel moeten terugsturen. Niet dus.
Wel zie ik, als ik het Python-programma start, op het Arduino-bord een LED knipperen - kan zo snel niet zien of dat een TX of RX is, maar ik gok dus een RX: de Arduino ontvangt dus wel degelijk iets vanaf de Linux machine.

... en ook dat probleem heb ik opgelost:
Deze code werkt NIET:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
import serial, time

arduino = serial.Serial('/dev/ttyACM0', 9600, timeout=.1)
time.sleep(1) #give the connection a second to settle

arduino.write("Hello from Python!")
print "send Hello"

while True:
    data = arduino.readline()
    if data:
        print data.rstrip('\n') #strip out the new lines for now
        # (better to do .read() in the long run for this reason

... maar als ik de delay op regel 4 verhoog naar 2 seconden, dan werkt het wel! :)

Mooi, communicatie beide kanten op werkt dus. Nu aan de echte applicatie beginnen. Dank voor je tip, precies wat er nodig was om mij weer aan het werk te zetten!