Python, Webiopi und Himbeer-Pi
-
20-12-2019 - |
Frage
Ich versuche, mein Himbeer-Pi-Auto über WLAN und Webiopi zu steuern.Die Grundfunktion funktioniert einwandfrei - haben Sie die Schnittstelle, wo ich auf fwd klicke und das Auto vorwärts fährt und wenn ich den Knopf loslasse, stoppt es.
Ich möchte jetzt den Ultraschall-Abstandssensor integrieren, damit das Auto beim Vorwärtsfahren anhalten soll, wenn etwas davor ist.Ich habe es dort, wo das Auto fährt und anhält, wenn ich auf die Vorwärtsfahrtaste klicke, wenn sich etwas in Reichweite befindet, aber es stoppt nur, wenn sich etwas in Reichweite befindet und nicht, wenn ich die Taste loslasse.Meine while-Schleife schleift sich irgendwie (steckt fest) und liest die Freigabetastenfunktion nicht von webiopi.
Kann mir bitte jemand helfen - ich bin jetzt schon seit Tagen dabei und weiß nicht, wo ich falsch liege :-(
Hier ist die Schleife aus meinem Python-Skript:
def go_forward(arg):
global motor_stop, motor_forward, motor_backward, get_range
print "Testing"
print mousefwd()
while (arg) == "fwd":
print (arg)
direction = (arg)
dist = get_range()
print "Distance %.1f " % get_range()
if direction == "fwd" and get_range() < 30:
motor_stop()
return
else:
motor_forward()
Und hier ist der Code aus meinem webiopi-Funktionsaufruf:
function go_forward() {
var args = "fwd"
webiopi().callMacro("go_forward", args);
}
function stop1() {
var args = "stop"
webiopi().callMacro("go_forward", args);
webiopi().callMacro("stop");
}
So habe ich es jetzt, aber es funktioniert immer noch nicht (ich bin ein totaler Neuling :-)) :
def go_forward(arg):
global motor_stop, motor_forward, motor_backward, get_range
print "Testing"
direction = arg
while direction == "fwd":
print arg
dist = get_range()
print "Distance %.1f " % get_range()
if get_range() < 30:
motor_stop()
elif direction == "fwd":
motor_forward()
else:
motor_stop()
Vielleicht ein kleiner Schritt nach vorne.Sehen Sie, dass Webipi eine eigene 'Schleife' verwendet und ich den Schleifencode hinzugefügt habe, um den Status der Motor-GPIOs und die Entfernung zu überprüfen und ob der Motor läuft und ob die Entfernung zu kurz ist, dann stoppen Sie.Das Auto bewegt sich jetzt, wenn ich den Vorwärtsknopf drücke und stoppt, wenn ich ihn loslasse und wenn es vorwärts fährt und die Entfernung weniger als 30 cm beträgt, stoppt es.Das einzige Problem ist, dass wenn die Entfernung zu kurz ist und ich die Vorwärts-Taste mehrmals zu schnell drücke, ich jetzt ein "GPIO" bekomme.ausgabe (Echo, 1) _webiopi.GPIO.InvalidDirectionException:Der GPIO-Kanal ist kein AUSGANGS-" Fehler :-( .
Der Code sieht jetzt so aus:
def go_forward(direction):
motor_forward()
def loop():
if get_range() < 30 and GPIO.digitalRead(M1) == GPIO.HIGH:
stop()
print "stop"
sleep(1)
Lösung
Ich werde Ihr Hauptproblem gleich beantworten, aber zuerst möchte ich etwas erwähnen, das Sie als Python-Anfänger tun, was Ihr Leben komplizierter macht, als es sein muss.
Es gibt keine Notwendigkeit für die global
aussage, die Sie zu Beginn Ihrer Funktion haben.In Python müssen Sie nur das verwenden global
erklärung, wenn Sie möchten schreiben zu einer globalen Variablen.Wenn alles, was Sie tun müssen, ist lesen die Variable, oder rufen Sie die Funktion, dann gibt es keine Notwendigkeit für die global
Anweisung.Alle in Ihrer Funktion verwendeten Namen, unabhängig davon, ob es sich um Namen von Variablen oder Namen von Funktionen handelt, werden in der folgenden Reihenfolge gesucht:lokal, umschließend, global, eingebaut."Lokal" bedeutet Namen, die in Ihrer Funktion definiert sind, wie Ihre direction
variabel."Einschließen" ist eine Regel, die verwendet wird, wenn Sie eine Funktion in einer anderen Funktion definieren.Dies ist in vielen Situationen nützlich, aber es ist ein etwas fortgeschrittenes Thema und Sie müssen sich vorerst keine Gedanken darüber machen."Global" bedeutet Namen (von Variablen, Funktionen oder Klassen), die auf der obersten Ebene Ihres Programms definiert sind - z. B. Ihre motor_stop
funktion unter anderem.Und schließlich bedeutet "eingebaut" Pythons eingebaute Namen, wie str
oder int
oder file
.
Also wenn du das ausgelassen hast global
anweisung, dann würde Python nach dem Namen suchen motor_stop
(und die anderen Funktionsnamen) wie folgt:
- Lokal: Gibt es eine
motor_stop
in dieser Funktion definiert?Nein.Mach weiter. - Einschließenden: Ist diese Funktion in einer anderen Funktion definiert?Nein, also gilt die Regel "Einschließen" nicht.Mach weiter.
- Global: Gibt es eine
motor_stop
auf der obersten Ebene des Programms definiert?Ja.Hab es gefunden. - (Vordefiniert):Diese Regel wird überhaupt nicht überprüft, da der Name von der "globalen" Regel gefunden wurde.
Alle Ihre Funktionen sind auf der obersten Ebene Ihres Programms definiert, sodass die "globale" Regel sie findet, ohne dass die global
Anweisung.Dies sollte Ihr Leben ein wenig einfacher machen.
Nun zu Ihrer Hauptfrage:warum Ihr Code für immer wiederholt wird.Das liegt daran, dass die Testbedingung Ihre while
schleife wird niemals falsch werden.Du bist aufgesprungen while direction == "fwd"
, und der Code in der while
schleife ändert nie die direction
variabel.Jedes Mal, wenn es das Ende der Schleife erreicht, kehrt es zurück, um den Zustand erneut zu testen.Der direction
variable enthält noch die Zeichenfolge "fwd"
, und so läuft die while-Schleife ein zweites Mal.Dann die direction
variable enthält noch die Zeichenfolge "fwd"
, und so läuft es ein drittes Mal.Und so weiter und so weiter.
Eine Möglichkeit, das zu verlassen while
schleife, wenn Sie möchten, dass es beendet wird, wäre das Setzen der direction
variabel zu etwas anderem, wie "stop"
, wenn du aufhören willst.(ZB nachdem Sie angerufen haben motor_stop()
).Eine andere Möglichkeit wäre die Verwendung des return
anweisung, um die Funktion an diesem Punkt zu beenden.Aber mein Vorschlag wäre, das zu verwenden break
anweisung stattdessen, was bedeutet "Verlasse an diesem Punkt sofort die Schleife, in der ich mich befinde." Es funktioniert auf beiden while
schleifen und for
schleifen, und ist eine sehr nützliche Aussage, über die man Bescheid wissen sollte.Es sieht so aus, als ob du deine willst while
schleife zum Beenden bei jedem Anruf motor_stop()
, also gibt es zwei Orte, an die Sie einen setzen würden break
Anweisung:
def go_forward(arg):
print "Testing"
direction = arg
while direction == "fwd":
print arg
dist = get_range()
print "Distance %.1f " % get_range()
if get_range() < 30:
motor_stop()
break
elif direction == "fwd":
motor_forward()
# No break statement here, so the while loop continues
else:
motor_stop()
break
Es gibt ein paar andere Änderungen, die ich vorschlagen würde.Zuerst rufst du an get_range()
dreimal in Ihrer Schleife, aber Sie müssen es wirklich nur einmal aufrufen.Sie haben das Ergebnis bereits einem zugewiesen dist
variable, warum also nicht diese Variable verwenden?
def go_forward(arg):
print "Testing"
direction = arg
while direction == "fwd":
print arg
dist = get_range()
print "Distance %.1f " % dist
if dist < 30:
motor_stop()
break
elif direction == "fwd":
motor_forward()
# No break statement here, so the while loop continues
else:
motor_stop()
break
Und zweitens gibt es keinen Weg in die while
schleife für direction
nicht "fwd" zu sein, also das Finale else
ist unnötig, und Ihre Funktion kann werden:
def go_forward(arg):
print "Testing"
direction = arg
while direction == "fwd":
print arg
dist = get_range()
print "Distance %.1f " % dist
if dist < 30:
motor_stop()
break
else:
motor_forward()
Schließlich haben Sie einen Funktionsparameter mit dem Namen arg
, was ein Name ist, der nichts darüber aussagt, wofür er verwendet wird.Sie weisen es sofort einer Variablen namens zu direction
, was ein viel besserer Name ist.Warum also nicht das an erster Stelle als Parameternamen verwenden?Es gibt keine Regel, die die Parameter einer Funktion angibt müssen werde "arg" genannt;sie können beliebig genannt werden (außer einem der reservierten Wörter von Python wie break
oder if
).Geben wir Ihrer Funktion also einen aussagekräftigeren Parameternamen, der sie noch weiter vereinfacht:
def go_forward(direction):
print "Testing"
while direction == "fwd":
print direction
dist = get_range()
print "Distance %.1f " % dist
if dist < 30:
motor_stop()
break
else:
motor_forward()
Dort.Das ist viel einfacher zu lesen und zu verstehen, und es sollte das Problem lösen, das Sie von Ihrem gesehen haben while
schleife wird nicht verlassen, wenn das Auto einem Objekt zu nahe kommt.
(Es gibt immer noch ein mögliches Problem, das ich sehen kann, nämlich dass die while-Schleife möglicherweise nicht beendet wird, während das Auto vorwärts fährt, obwohl Sie die "Vorwärts" -Taste losgelassen haben - aber ich müsste sehen Ihre motor_forward()
code, um zu wissen, wie man das löst.Es könnte so einfach sein wie das Setzen eines break
erklärung nach motor_forward()
, in welchem Fall es wirklich keine Notwendigkeit für eine geben würde while
schleife überhaupt - aber ich müsste wissen, wie deine motor_forward()
code interagiert mit webiopi und wie der Ereignisbehandlungscode von webiopi funktioniert.Nichts davon weiß ich im Moment, also werde ich beantworten, welche Probleme ich jetzt beantworten kann, auch wenn meine Antwort unvollständig ist, anstatt Sie ohne Antwort zu lassen.)
Bearbeiten von Mark: Hier ist der motor_forward-Code:
def motor_forward():
GPIO.output(M1, GPIO.HIGH)
GPIO.output(M2, GPIO.LOW)
string = "echo 0=130 > /dev/servoblaster"
os.system(string)
Andere Tipps
Versuchen Sie das - Sie stoppen immer auf dem Reichweite, möchten jedoch in Richtung Anhalten
generasacodicetagpre.btw Sie benötigen nicht nur das (ARG), wenn Sie es aufweisen
drucken Sie arg
Die PARENS in der Anrufsignatur gibt es, um ihr ein PARM in eine Funktion zu zeigen