Kompletter Python-Neuling ... Ich arbeite mit dem Arduino-Pyfirmata-Paket und versuche, etwas ganz Einfaches zu tun.

Abhängig von einer Benutzereingabe in Python möchte ich, dass eine LED blinkt oder nicht.

Mein Problem ist, dass das Python-Programm nur einmal nach der Benutzereingabe fragt, aber ich möchte, dass es immer nach der Eingabe fragt, damit der Benutzer die Funktion jederzeit ändern kann.

Ich habe versucht, das Threading-Paket zu verwenden, aber keinen Erfolg ... Vielleicht gibt es einen einfacheren Weg, aber ich bin völlig neu in der Codierung, so dass ich keinen anderen kenne. Offen für Vorschläge !!

Hier ist mein Code,

import pyfirmata
import threading
import time

board = pyfirmata.Arduino('/dev/cu.usbmodem14101')

def flash():
    for i in range(1000):
        board.digital[13].write(1)
        time.sleep(1)
        board.digital[13].write(0)
        time.sleep(1)

def stop():
    board.digital[13].write(0)


while True:
    runMode = input("Run or Stop? ")

    if runMode == "Run":
        x = threading.Thread(target=flash(), args=(1,))
        x.start()
        # x.join()

    elif runMode == "Stop":
        x = threading.Thread(target=stop(), args=(1,))
        x.start()
        #x.join()
2
pythonosaurusrex 22 Feb. 2020 im 23:11

3 Antworten

Beste Antwort

Sie können dies objektorientiert tun, indem Sie eine eigene Thread -Unterklasse wie die folgende Flasher -Klasse erstellen.

Einer der Vorteile dieses Ansatzes besteht darin, dass es relativ einfach wäre, die Klasse Flasher zu erweitern und LEDs zu steuern, die an verschiedene Ausgänge angeschlossen sind, oder die Verzögerung zwischen den Blitzen zum Zeitpunkt der Erstellung anzugeben. Wenn Sie erstere ausführen, können mehrere Instanzen gleichzeitig ausgeführt werden.

import pyfirmata
import threading
import time

OFF, ON = False, True

class Flasher(threading.Thread):
    DELAY = 1

    def __init__(self):
        super().__init__()
        self.daemon = True
        self.board = pyfirmata.Arduino('/dev/cu.usbmodem14101')
        self.flashing = False
        self.LED_state = OFF

    def turn_LED_on(self):
        self.board.digital[13].write(1)
        self.LED_state = ON

    def turn_LED_off(self):
        self.board.digital[13].write(0)
        self.LED_state = OFF

    def run(self):
        while True:
            if self.flashing:
                if self.LED_state == ON:
                    self.turn_LED_off()
                else:
                    self.turn_LED_on()
            time.sleep(self.DELAY)

    def start_flashing(self):
        if self.LED_state == OFF:
            self.turn_LED_on()
        self.flashing = True

    def stop_flashing(self):
        if self.LED_state == ON:
            self.turn_LED_off()
        self.flashing = False


flasher = Flasher()
flasher.start()

while True:
    runMode = input("Run or Stop? ").strip().lower()

    if runMode == "run":
        flasher.start_flashing()
    elif runMode == "stop":
        flasher.stop_flashing()
    else:
        print('Unknown response ignored')
0
martineau 22 Feb. 2020 im 21:34

Sie haben einen Fehler im Code.

Sie sollten den Thread erstellen über:

x = threading.Thread(target=flash)

Hinweis: Sie haben das eingegebene 'flash ()' angegeben und damit die Methode im Hauptthread ausgeführt. Und auch Ihre Methode hat keine Argumente, daher können Sie die args-Werte entfernen

0
Stefan xyz 22 Feb. 2020 im 21:20

Wenn Sie nur den Thread beenden möchten, können Sie eine Mehrfachverarbeitung verwenden, die eine Mehrfachverarbeitung verarbeiten kann.

p = Process(target=flash, args=(,))
while True:
    runMode = input("Run or Stop? ")
    if runMode == "Run":
        p.start()
    elif runMode == "Stop":
        p.terminate()

Es wird jedoch nicht empfohlen, nur Threads zu beenden, da dies zu Fehlern führen kann, wenn der Prozess kritische Ressourcen verarbeitet oder von anderen Threads abhängig ist. Eine bessere Erklärung finden Sie hier. Gibt es eine Möglichkeit, einen Thread zu beenden?

Eine bessere Option, wie hier beschrieben, ist die Verwendung von Flags, um das Flashen zu handhaben. Sie ermöglichen eine einfache Kommunikation zwischen Threads

from threading import Event

e = event()

def check_for_stop(e):
    while not e.isSet():
         flash()
    print("Flashing Ended")

while True:
    runMode = input("Run or Stop? ")

    if runMode == "Run":
        x = threading.Thread(target=check_for_stop, args=(e,))
        x.start()
        # x.join()

    elif runMode == "Stop":
        e.set() #set flag true
        e.clear() #reset flag

In der Dokumentation finden Sie weitere Informationen zu Ereignisobjekten https: //docs.python. org / 2.0 / lib / event-objects.html

Ich habe nicht getestet, dass dieser Code nur ein Beispiel ist. Ich entschuldige mich, wenn er nicht sofort funktioniert

Bearbeiten: Wenn Sie Ihre Funktion noch einmal betrachten, möchten Sie während des Blinkens nach der Flagge suchen. Dies ist mein Fehler, damit Ihre Blitzfunktion wie aussieht

def flash():
    while e.isSet():
        board.digital[13].write(1)
        time.sleep(1)
        board.digital[13].write(0)
        time.sleep(1)

Und Sie würden dies wie zuvor in den Thread übergeben

x = threading.Thread(target=flash(), args=(1,))
x.start()
0
Charlie 22 Feb. 2020 im 21:04