2015-07-08 20 views
5

Mam program Pythona Chcę uruchomić w tle (na Raspberry Pi), który czeka na wejście GPIO następnie wykonuje akcję i nadal czeka na dane wejściowe, aż proces jest zabity .Python jaki jest najbardziej efektywny sposób oczekiwania na dane wejściowe

Jaki jest najbardziej skuteczny sposób, aby to osiągnąć. Rozumiem, że używanie podczas prawdziwości nie jest tak skuteczne. Idealnie byłoby użyć przerwania - i mógłbym użyć GPIO.wait_for_edge - ale to musiałoby być w jakiejś pętli lub sposób kontynuowania operacji po zakończeniu obsługi.

Dzięki

+0

Proszę wyjaśnić nieco więcej dlaczego 'while True:' 'x = GPIO.wait_for_edge()' 'if hasSomeProperty (x): break' nie jest odpowiednim rozwiązaniem dla twojej sprawy. – Alfe

+0

@Alfe Jestem nowy dla Pythona - więc nie do końca pewny jak efektywny jest 'while True:'. Zakładam, że używało procesora - pętli wokół. Zastanawiam się, czy istnieje jakiś inny konstrukt, który by po prostu czekał (bez użycia cpu), podobnie jak 'GPIO.wait_for_edge()' ale nie specyficzny dla GPIO - wtedy pozwalając procedurom obsługi przerwań na ich przetwarzanie. Jest to zadanie serwisowe/działające w tle, które będzie po prostu działało nieprzerwanie - oczekiwanie na przerwanie. Po prostu nie żartuję na procesorze, jeśli nic nie robi. –

Odpowiedz

1

Zgodnie z tym: http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio GPIO.wait_for_edge (23, GPIO.FALLING) będzie czekać na przejście na pin 23 przy użyciu przerwań zamiast odpytywania. Będzie działał tylko po uruchomieniu. Możesz zamknąć to w próbie:/except KeyboardInterrupt aby złapać ctrl-c.

Jeśli chcesz kontynuować przetwarzanie, musisz zarejestrować funkcję oddzwaniania dla przerwania. Zobacz: http://sourceforge.net/p/raspberry-gpio-python/wiki/Inputs/

def callback(channel): 
    do something here 

GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback) 
continue your program here, likely in some sort of state machine 
+0

Dzięki @Mark - Widziałem ten artykuł .. ale chcę, aby kontynuować przetwarzanie. I zakładałem, że umieszczenie go w pętli 'while while' jest nieefektywne. Również wolałbym używać przerwań. –

+1

Gotcha - Edytowałem swoją odpowiedź, aby dołączyć funkcję zwrotną. Kod wykona tę funkcję w drugim wątku obok głównego komputera stanu po wykryciu wyzwalacza. – Mark

+0

Dzięki @Mark - tak, to linia myśli, na której byłem. Jaki jest najskuteczniejszy sposób wdrożenia części "kontynuuj ..."? Albo z automatem państwowym, albo bez niego. Jeśli korzystam z automatu stanów, zakładam, że wymagana jest jakaś pętla, która nieustannie sprawdza, czy nie nastąpiła zmiana stanu - co, jak zakładam, przeżułoby procesor nawet wtedy, gdy nie było żadnej zmiany (która byłaby przez większość czasu). –

1

Rozumiem, że kiedy mówisz „używając jednocześnie prawdziwe” znaczy wyborczych, który sprawdza stan GPIO w pewnym odstępie czasu, aby wykryć zmian w kosztem pewnego czasu przetwarzania.

Alternatywą dla uniknięcia odpytywania (od docs) jest wait_for_edge():

Funkcja wait_for_edge() jest zaprojektowany do blokowania wykonywanie programu aż zostanie wykryta krawędź.

Który wydaje się być tym, czego szukasz; program zawiesza wykonanie przy użyciu 01UCIIUC.

Teraz zakładając, że oznaczało to, że nie chcesz używać GPIO.wait_for_edge() bo nie chcesz stracić zmiany stanu GPIO podczas obsługi wydarzenia, trzeba użyć wątków. Jednym z możliwych rozwiązań jest wprowadzenie zdarzenia w Queue i konfiguracji:

  • jeden wątek się dzieje z while True: queue.put(GPIO.wait_for_edge(...)).
  • Kolejny wątek do wykonania Queue.get().
+0

Dzięki @jvdm Dobry pomysł (o używaniu kolejki). chociaż na moje oryginalne pytanie - pętla 'while while:' jest wydajna. Zaczynam odczuwać, że jest to jedyne podejście oparte na tym, co przeczytałem. Byłoby interesujące dowiedzieć się dokładnie, co 'GPIO_wait_for_edge()' robi pod maską (np. Robi także pętlę 'while'). Czy ktoś wie, jak aplikacja python GUI pozostaje uruchomiony podczas oczekiwania na wejście? –

+1

'' podczas gdy wydajność pętli True '' zależy od tego, co robi pętla, jeśli użyjesz '' wait_for_edge() '', zawiesi wątek oczekujący na zdarzenia I/O z deskryptora pliku używając '' epoll() '' (zgodnie z kodem źródłowym cytowanym w odpowiedzi). – jvdm

Powiązane problemy