Argumente an Script übergeben und über serielle Schnittstelle weiterleiten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
phischmi
User
Beiträge: 34
Registriert: Dienstag 12. Juli 2016, 06:08

Hallo zusammen,

da ich neu hier bin, zunächst zu mir :D
Ich heiße Philipp und bin bei Python gelandet, da ich mich aktuell näher mit dem Arduino auseinander setze.
Mein Ziel ist es, zwei Motoren - einen 12V Lüfter und einen Schrittmotor - vom Mac aus zu steuern.
Die Kommunikation zwischen Mac und Arduino soll per Python erfolgen, da mir dies die am weitesten verbreite Lösung zu sein scheint. Das Python-Script wiederum wird aus einem anderen Programm heraus aufgerufen und mit Argumenten gefüttert, welche angeben, welcher der beiden Motoren angesprochen werden soll und was dieser tun soll (Lüfter: Geschwindigkeit ändern / Schrittmotor: Anzahl der Schritte und Richtung).
Meine Erfahrungen in der Programmierung beschränken sich in erster Regel auf kleinere PHP-Skripte, welche ich vor einiger Zeit geschrieben habe (v.a. einfache Front-Ends für Datenbanken). OOP ist mir also zumindest nicht völlig unbekannt ;)

Da sowohl Python als auch der Arduino nun eben noch völlig neu für mich sind, taste ich mich nun langsam voran.
Der folgende Code macht grundsätzlich schon einmal, was er soll :)
Es wird ein fester Wert zwischen 0 und 255 (im Beispiel '100') über die serielle Schnittstelle an den Arduino gesendet, welcher die Geschwindigkeit des Lüfters entsprechend anpasst.

Code: Alles auswählen

#!/usr/bin/python

import sys
import serial
import struct
import time

port = '/dev/tty.usbmodemFA131'

arduino = serial.Serial(port, 9600)

arduino.open

time.sleep(2)

arduino.write(b'100')

print(arduino.readline())

arduino.close
Zur Kontrolle lasse ich mir den übergebenen Wert vom Arduino zurück geben.

Nun will ich im nächsten Schritt keine statischen Werte im Script definieren, sondern den Wert flexibel als Argument an das Script übergeben (z.B. "Arduino.py 100").
Soweit ich bisher verstanden habe, geht dies über das Array sys-argv[].
Das erste Argument bekomme ich also über sys.argv[1].

Nun würde ich das erste Argument in eine Variable einlesen und an die serielle Schnittstelle übergeben.
Mein Problem liegt nun jedoch darin, dass ich nicht weiß, wie ich den o.g. Code abwandeln muss, damit der Inhalt der Variable in gleicher Form übertragen wird wie durch

Code: Alles auswählen

arduino.write(b'100')
Das vorangestellte 'b' funktioniert ja nur mit Strings, nicht jedoch mit Variablen :K

Viele Dank für eure Unterstützung!

Philipp
Zuletzt geändert von Anonymous am Dienstag 12. Juli 2016, 10:04, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@phischmi: Da Du mit Python2 arbeitest, gibt es keinen Unterschied zwischen Byte-Strings und den Strings, die Du in sys.argv bekommst. Du kannst sie also ohne weiteres als Argument übergeben:

Code: Alles auswählen

#!/usr/bin/python
import sys
import serial
import time

PORT = '/dev/tty.usbmodemFA131'

arduino = serial.Serial(PORT, 9600)
time.sleep(2)
arduino.write(sys.argv[1])
print arduino.readline()
arduino.close()
Übrigens muß man Funktionen auch aufrufen, damit sie abgearbeitet werden und nicht nur referenzieren, also "close()".
phischmi
User
Beiträge: 34
Registriert: Dienstag 12. Juli 2016, 06:08

@Sirius3
Danke für die schnelle Antwort!

Ich habe leider vergessen zu erwähnen, dass ich mit Python 3 arbeite :?

Die Shebang-Zeile ist entsprechend natürlich falsch und muss heissen

Code: Alles auswählen

#!/usr/bin/env python3
Da ich ohnehin bei Null anfange, wollte ich auch mit der Version starten, die in ihrer Syntax fortgeführt wird.

Des Weiteren ist das arduino.open() nicht notwendig, wie ich aus deinem Code lese?


Grüße

Philipp
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@phischmi: Da Du anscheinend ohne "open" erfolgreich warst, ist das open überflüssig. Wenn Du mit Python 3 arbeitest, dann ist die erste Zeile irreführend.

Für Python3 mußt Du die Unicode-Strings, die Du in sys.argv erhältst, encodieren:

Code: Alles auswählen

#!/usr/bin/python3
import sys
import serial
import time

PORT = '/dev/tty.usbmodemFA131'

arduino = serial.Serial(PORT, 9600)
time.sleep(2)
arduino.write(sys.argv[1].encode("ASCII"))
print(arduino.readline())
arduino.close()
BlackJack

Den expliziten `close()`-Aufruf kann man sich auch noch sparen wenn man die ``with``-Anweisung verwendet:

Code: Alles auswählen

#!/usr/bin/env python3
import sys
import time

import serial
 
PORT = '/dev/tty.usbmodemFA131'
 
with serial.Serial(PORT, 9600) as arduino:
    time.sleep(2)
    arduino.write(sys.argv[1].encode('ASCII'))
    print(arduino.readline())
phischmi
User
Beiträge: 34
Registriert: Dienstag 12. Juli 2016, 06:08

Vielen Dank für eure Antworten! :D
Werde das Script heute Abend anpassen und ausprobieren!
phischmi
User
Beiträge: 34
Registriert: Dienstag 12. Juli 2016, 06:08

Der Code funktioniert so wie er soll. Nochmal Danke dafür :)

Eine Frage habe ich jedoch noch.

Die Rückgabe vom Arduino lautet...

Code: Alles auswählen

Last login: Tue Jul 12 19:57:12 on ttys000
Philipps-Air:~ philipp$ ./arduino.py 100
b'100\r\n'
Philipps-Air:~ philipp$ ./arduino.py 0
b'0\r\n'
Philipps-Air:~ philipp$ 
Ich hätte nun aber z.B. 100 statt b'100\r\n' erwartet. Woran liegt das?


Viele Grüße

Philipp
BlackJack

@phischmi: Woran das liegt das Du falsche Erwartungen hast? Keine Ahnung. ;-)

So sieht halt die Zeichenkettedarstellung eine `bytes`-Objektes aus das die Zeichen '1', '0', '0', und ein ”carriage return” und ein ”line feed” enthält.
phischmi
User
Beiträge: 34
Registriert: Dienstag 12. Juli 2016, 06:08

BlackJack hat geschrieben:@phischmi: Woran das liegt das Du falsche Erwartungen hast? Keine Ahnung. ;-)
Das frag ich mich auch so oft :mrgreen:

Danke für die kurze Aufklärung!
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@phischmi:
Damit wird das Zeilenende signalisiert. Anders weiß das angeschlossene Gerät nicht, ob noch Eingaben kommen.
Antworten