problem serial write

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
nomads
User
Beiträge: 4
Registriert: Montag 4. April 2016, 15:05

hallo,
bin neuling in python.
habe seit einigen tagen probleme mit pyserial.
folgendes : moechte eine serielle verbindung zu einem microcontroller herstellen. also ein ser.write

Code: Alles auswählen

import time
import serial
import random

random.seed()



def random_esc():
	esc1 = str(random.randint(1000,2000))
	print(str(esc1))
	
# configure the serial connections (the parameters differs on the device you are connecting to)
ser = serial.Serial(
	port='/dev/ttyUSB0',
	baudrate=115200,
	parity=serial.PARITY_NONE,
	stopbits=serial.STOPBITS_ONE,
	bytesize=serial.EIGHTBITS
)

random_esc()

input = '3' # commando fuer den mc

ser.write(input + '\r\n')  # das ist ok
time.sleep(1)
# das problem: wenn ich das versuche , keine ansteuerung eines servos....
ser.write(esc1 + '\r\n')
# wenn ich hingegen 
ser.write('1567' + '\r\n') 
# ist das ok, und der servo wird angesteuert

print("ESC Done");
ser.close()
exit
	
koenntet ihr mir bei diesen problem bitte helfen.....
also ich moechte esc1 = integer in einen string convertieren und mit + '\r\n' senden.
vielen dank fuer eure hile
nomads
BlackJack

@nomads: Arbeite am besten mal ein Python-Grundlagentutorial durch, damit Du lernst wie Funktionen definiert werden und wie man da Werte hinein und vor allem in diesem Fall auch wieder heraus bekommt (Argumente und Rückgabewerte) und welche Namen in Python wo sichtbar sind.

Der `random.seed()`-Aufruf macht übrigens keinen Sinn. Weg damit. :-)
nomads
User
Beiträge: 4
Registriert: Montag 4. April 2016, 15:05

Hallo black-jack,
vielen dank fuer deine antwort.
ich habe auch schon die tutorials gelesen.... und im web mich fast zu tote gesucht um eine antwort zu finden
es waere hilfreich gewesen, wenn du mir wenigstens einen hinweis gegeben haettest.
da die variable esc1 aus meiner sicht global ist. sollte das kein problem sein.
ich kann ja auch die def funktion ganz weg lassen....
es geht eher darum,

- um die korrekte umwandlung eines integers to a string
- und warum ser.write(esc1 + '\r\n') nicht funktioniert aber
- ser.write('1234' + '\r\n') ok ist.

um hinweise und tips waere ich dankbar
nomads
ps. ich mach das schon seit ueber 10 jahre (entwicklung unter c und linux)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

nomads hat geschrieben:da die variable esc1 aus meiner sicht global ist.
Wie kommst Du darauf? Der Name `esc1` wird im Namensraum (Stichwort: scope) Deiner Funktion `random_esc()` definiert und gilt auch nur innerhalb dieses Namensraumes. Und den Namen an sich bekommst Du aus der Funktion auch nicht mehr heraus, nach Abarbeitung der Funktion wird deren Namensraum eh verworfen.

Was Du aber haben möchtest, nämlich den Wert, auf den `esc1` verweist, musst Du aus der Funktion zurückgeben (Stichwort: return), so wie es BlackJack ja schon gesagt hat.

Nochmal: Namen sind Namen und Werte sind Werte. Namen gelten innerhalb bestimmten Namensräumen. Werte nicht. Mit ein Grund, weshalb Du auf global gültige Namen verzichten solltest, da ein globaler Namensraum (das gesamte Modul) recht bald schwer zu überschauen ist und die Gefahr besteht, dass Werte an Stellen verändert werden, an denen man es nicht erwartet.
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

nomads hat geschrieben:ps. ich mach das schon seit ueber 10 jahre (entwicklung unter c und linux)
Ergänzend zu dem, was mutetella bereits schrieb: `esc1` wäre auch in C unter diesen Umständen nicht global verfügbar. Das Problem ist: Du führst den Bezeichner `esc1` innerhalb der Funktion `random_esc()` ein und erwartest dann, dass er in einem übergeordneten Namensraum verfügbar ist. Das funktioniert so nicht.

Eine Deklaration von Bezeichnern findet zwar nicht, wie in C üblich, explizit zu Beginn einer Funktion (bzw Namensraum) statt, aber es gelten trotzdem sehr ähnliche Regeln. Die erste Zuweisung an einen Bezeichner stellt auch gleichzeitig seine "Deklarierung" dar (wenn man die Bedeutung auf die Gegebenheiten von dynamisch typisierten Sprachen ausweitet). Er ist dann innerhalb dieses Namensraums und innerhalb aller tiefergelegenen Namensräume bekannt, nicht jedoch in einem übergeordneten Namensraum. Daher spuckt dir Python den Fehler aus.

Den Kommentar, warum jemand, der nach eigener Angabe seit 10 Jahren in C programmiert, an einem solchen Problem verzweifelt, verkneif ich mir mal...
nomads
User
Beiträge: 4
Registriert: Montag 4. April 2016, 15:05

hallo
geloest
ohne funktion klappts
hauptsache der test funktioniert.
@snafu:
vergess solche kommentare
gruss
nomads
BlackJack

@nomads: Tutorials lesen reicht nicht, man muss die durcharbeiten, also den Code auch selber ausprobieren, verändern, überlegen was passiert und vergleichen mit dem was tatsächlich passiert und verstehen warum das so ist.

`esc1` ist wie schon gesagt nicht global. Das wäre es in C auch nicht, und Du solltest überlegen warum Du das erwartet hast, und auch was passieren würde wenn Du ein Modul mit 50 Funktionen hast und alle Namen global wären. Würde das überhaupt Sinn machen?

Warum ``ser.write(esc1 + '\r\n')`` nicht funktioniert hat, sollte die Ausnahme die man bekommt, ziemlich deutlich sagen: Der Name `esc1` ist an der Stelle nicht definiert. Da hättest Du dann darauf kommen können, dass der Name durch eine Zuweisung in einer Funktion nicht global zur Verfügung steht.

Ohne Funktion mag es klappen, aber ohne Funktion sollte man es nicht schreiben. Wenn Du Funktionen vermeidest, lernst Du nicht wie Python funktioniert, und Programme ohne Funktionen können kaum über simple "Hallo, Welt!"-Schnippsel wachsen. Auf Modulebene sollten nur Definitionen von Konstanten, Funktionen, und Klassen stehen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst und die so aufgerufen wird, dass man das Modul auch importieren kann ohne dass das Hauptprogramm automatisch abläuft.

Die Einrückung sollte vier Leerzeichen pro Ebene betragen.

Um sicherzustellen, dass die Verbindung unter allen Umständen am Ende geschlossen wird, bietet sich die ``with``-Anweisung an. Oder man benutzt ``try``/``finally`` dafür.

Namen sollten nicht kryptisch abgekürzt werden. Steht `ser` für `serial` oder für `servo`? So etwas sollte man nicht raten müssen.

`input` ist der Name einer eingebauten Funktion. Den sollte man nicht an etwas anderes binden.

Das Semikolon dient in Python nicht wie in C als Abschluss einer Anweisung, sondern um Anweisungen in der gleichen Zeile voneinander zu trennen. Da man das in der Regel nicht macht, ist das Semikolon sehr selten in Python-Quelltexten zu finden.

Das ``exit`` am Ende hat keinen Effekt. Man muss Funktionen auch aufrufen wenn man sie denn aufrufen möchte. Aber selbst dann hätte es keinen sichtbaren Effekt, denn das Programm wird an der Stelle ja sowieso verlassen weil es zuende ist. Ausserdem ist der Name zwar einfach so verfügbar, sollte er laut Dokumentation aber nicht. Deshalb sollte man ihn besser explizit aus `sys` importieren wenn man das Programm tatsächlich mit `exit()` verlassen muss/will, beispielsweise weil man den Rückgabewert des Prozesses setzen möchte.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function
import random
import time

import serial


def random_esc():
    return str(random.randint(1000, 2000))


def main():
    # 
    # Configure the serial connections (the parameters differ on the
    # device you are connecting to).
    # 
    with serial.Serial(
        port='/dev/ttyUSB0',
        baudrate=115200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
    ) as connection:
        command = '3'
        connection.write(command + '\r\n')
        time.sleep(1)
        connection.write(random_esc() + '\r\n')
        print('ESC Done')


if __name__ == '__main__':
    main()
nomads
User
Beiträge: 4
Registriert: Montag 4. April 2016, 15:05

hallo black-jack
vielen dank fuer deine antwort und dem schnippsel. ;-)
werd es in zukunft beherzigen.
dieses python schnippsel sollte nur ein problem loesen.
meine linux-box (in c) weigert sich standhaft serialwrites zu einem mc auszufuehren.
desswegen diese loesung.. :-)
die abkuerzung "ser" hab ich aus dem netz.
ich wohn auf dem land, und da sind python-buecher eher selten, und googlen hilft auch nicht immer
gruss
nomads
Antworten