python-kód 30% processzorhasználattal

 ( bzs | 2016. december 31., szombat - 16:48 )

Sziasztok.

Mezei Raspberry Zero el van látva egy gombbal, meg egy leddel. No meg ezzel, ami meghajtja a kettőt. Figyeli, be lett-e nyomva a gomb és ha igen, bekapcsolja a ledet, majd elindít egy scriptet BASH-ban. A led addig világít, míg ki nem kapcsol az rpi.
Valamiért azonban szerintem htop-ban nézve irdatlanul eszi a kód processzort, nem értem, miért.

Íme a kód:

import RPi.GPIO as GPIO
import time, os
GPIO.setmode(GPIO.BCM)
#switch_pin = 21
#led_pin = 17
switch_pin = 21
led_pin = 27

GPIO.setup(switch_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(led_pin, GPIO.OUT)
led_state = False
old_input_state = True # pulled-up
while True:
 new_input_state = GPIO.input(switch_pin)
 if new_input_state == False and old_input_state == True:
  led_state = not led_state
  GPIO.output(27, True)      # led ON
  os.system("sudo fuss off")
  print("power OFF")
 old_input_state = new_input_state
 GPIO.output(led_pin, led_state)

Szerintetek ez így tényleg erőforrás-zabáló?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

jól látom, hogy egy végtelen ciklusban nem vársz szinte semmire (csak a gomb státuszára), meg pörgeted a CPU-t (utasításokat adsz neki)?
akkor ez végtelen ciklusban pörgeti a CPU-t, már, amikor nem vár semmire. szóval szerintem reális lehet.

Én a gombot nézném meg, tud-e jelezni valami callback (esetleg interrupt, ha errefelé ez értelmes fogalom) szerűséggel, hogy most nyomtak meg.
Vagy (bár ez gány) beleraknék egy kicsi várakozást, hogy ~10 milisecet várjunk két iteráció között - valszeg úgysem tudod ~10 milisec alatt lenyomni-elengedni a gombot, szóval mindenféleképpen megüti a változás-figyelődet.

szerk.: https://en.wikipedia.org/wiki/Busy_waiting
--
blogom

A wiki egy c-kódmegoldásra mutat, most nekem kígyónyelven kell minden sajnos.
ezt találtam ki:

time.sleep(0.5)

Egyből visszaesett a mélybe a forgalom.
A többszörös gomblenyomástól pedig a bashban meghívott "fuss" nevű scriptem véd, ami nem engedi, hogy egy parancsot 20 másodpercen belül kétszer indítsak.

---
--- A gond akkor van, ha látszólag minden működik. ---
---

nagyjából.

a többszörös gombnyomogatás alatt azt értettem, hogy: ha most valami ilyesmi történik:
(ha jól értem, a lenyomott gomb False, az elengedett True)


0.0 s | - # gomb elengedve, lefut a new_input_state = GPIO.input(switch_pin), s a new_input_state True
      |
0.1 s | - # megnyomod a gombot, a new_input_state ilyenkor lenne False
      |
0.2 s | - # gomb még mindig nyomva
      |
0.3 s | - # elengeded a gombot, a new_input_state megint True lenne
      |
0.4 s | - # gomb elengedve
      |
0.5 s | - # újra lefut a ciklusod egyszer, de nem vette észre a gombnyomást

De ennek fizikailag van kicsi esélye, hogy te itt ilyen rövid gombnyomásokat hajts végre.
(Bár a fél másodperc már lehet sok, de ezt neked kell mérlegelned)
--
blogom

A pollozás erőforrás-zabáló dolog, csak akkor éri meg, ha a számunkra érdekes események annyira sűrűn jönnek, hogy összemérhető a leolvasás sebességével. Másrészt ha egy oda-vissza jelváltás nagyon gyorsan történik, akkor a pollozás esetleg nem is veszi észre. Gombnyomásnál ez valószínűleg nem játszik, rpi2-n még python-ból is lehet kb 100kHz-en pollozni.

Szerintem neked inkább ez kell:
https://pythonhosted.org/RPIO/rpio_py.html#gpio-interrupts
Ez hardveresen figyeli a jelet és csak akkor küld triggert, ha változás van.
Mivel nyomógombról van szó, ami szokott prellezni, ezért a debounce_timeout_ms paramétert is ajánlom figyelmedbe.
---
Régóta vágyok én, az androidok mezonkincsére már!

Már az rpio telepítésénél elvéreztem, olaszországban vagyok rossz netkapcsolattal. Kézzel tudnám felrakni leWget-elve, de olyat még nem csináltam.
pip nem megy, a távoli szerver elküld a fenébe a lassú net miatt.

---
--- A gond akkor van, ha látszólag minden működik. ---
---

Nem kell hozzá RPIO, ugyanez a funkció benne van a RPI.GPIO-ban is, csak a gugli erre dobta ki előbb nekem a linket.

Itt egy példa hozzá:
http://raspi.tv/2014/rpi-gpio-update-and-detecting-both-rising-and-falling-edges

Egyébként meg python cli-ben dir(RPI.GPIO) illetve help(RPI.GPIO.add_event_detect) a barátod.
---
Régóta vágyok én, az androidok mezonkincsére már!

Programozás alapjai... azért eszi a processzort, mert nem áll meg sehol, tehát folyamatosan fut. Mikor állna meg? Tipikusan csak akkor, ha valami kernel API-val vársz valami eseményre. Ez lehet időzítő, I/O vagy ilyesmi.

--

Én is tervezek nyomógombot használni.