tbs1-bo / ea_rpi_modul

Python Bibliothek für ein E/A-Modul für den RaspberryPi.
1 stars 0 forks source link

Wildes Flackern beim schnellen Dimmen #5

Closed elektroschule closed 8 years ago

elektroschule commented 8 years ago

Beim schnellen Dimmen kommt es hin und wieder zum Flackern. Folgender Code für eapi.hw funktioniert meistens ganz gut und flackert wenig bis gar nicht:

from eapi.hw import EAModul
import time
r = 100     # Anzahl der Dimmstufen
ea_modul = EAModul(29, 31, 33, 35, 37)
try:
    while(True):
    for i in range(r):
        x = pow(r,i/r)/r    # exponentielles Hochdimmen
        #x = i/r            # lineares Hochdimmen
        ea_modul.schalte_led(0, x)
        ea_modul.schalte_led(1, x)
        ea_modul.schalte_led(2, x)
        print(x)
        time.sleep(1/r)
    for i in range(r):
        x = pow(r,(r-1-i)/r)/r - 1/r    # exponentielles Runterdimmen
        #x = (r-i)/r                    # lineares Runterdimmen
        ea_modul.schalte_led(0, x)
        ea_modul.schalte_led(1, x)
        ea_modul.schalte_led(2, x)
        print(x)
        time.sleep(1/r)
except KeyboardInterrupt:
    ea_modul.cleanup()
finally:
    ea_modul.cleanup()

Folgender Code nutzt eapi.net und soll im Wesentlichen das selbe machen. Hier tritt eigentlich immer ein Flackern auf.

from eapi.hw import EAModul
from eapi.net import EAModulClient
import time

eam = EAModul()
eaclient = EAModulClient("localhost", 9999)

r = 100     # Anzahl der Dimmstufen
try:
    while(True):
    for i in range(r):
        x = pow(r,i/r)/r    # exp. Hochdimmen
        #x = i/r            # lin. Hochdimmen
        y = int(x*100)
        eaclient.sende(y, y, y)
        print(x)
        time.sleep(1/r)
    for i in range(r):
        x = pow(r,(r-1-i)/r)/r - 1/r
        x2 = (r-i)/r
        y = int(x*100)
        eaclient.sende(y, y, y)
        print(x)
        time.sleep(1/r)
except KeyboardInterrupt:
    eam.cleanup()

Es könnte z.B. daran liegen, dass im zweiten Beispiel eapi.hw und eapi.net gleichzeitig genutzt werden, was aber (außer in dem Beispiel) durchaus sinnvoll ist, wenn man über mehrere EAModule kommunizieren möchte.

Vielleicht findest du ja noch etwas beim Herumspielen heraus.

pintman commented 8 years ago

Im zweiten Beispiel wird ein EAModul eam initialisiert aber nicht verwendet. Lediglich ein cleanup() wird am Ende aufgerufen. Damit werden auch 3 PWMs auf den Standardpins gestartet. Das kann zu Problemen kommen, wenn am gleichen Rechner der Server läuft. Dieser nutzt auch ein EAModul auf den Standardpins.

Klappt es besser, wenn du die Zeilen eam = EAModul() und eam.cleanup() weglässt?

Gibt es eine Warnung, die sagt, dass Pins schon verwendet werden?

Vielleicht sollte ich bei der Erstellung des EAModuls testen, ob die angegebenen Pins schon konfiguriert sind.

elektroschule commented 8 years ago

Du hast Recht. Es kommt zu einer Warnung. Es funktioniert auch besser ohne die beiden Zeilen. Dafür flackert das erste Beispiel, wenn ich vorher das zweite Beispiel startete und der Server noch läuft. Das ergibt dann auch Sinn, wenn man bedenkt, dass wieder zwei EAModule initialisiert werden.

Ich weiß nicht, ob man das lösen kann, wenn man überprüft, ob die LED-Pins schon konfiguriert sind. Wenn ja, dann müsste man auf das schon bestehende PWM-Objekt zugreifen können um den duty cycle zu ändern.

pintman commented 8 years ago

An bestehende PWM-Objekte kann ich dran, wenn die z.B. in ganz anderen Prozessen laufen.

  1. Man könnte das PWM ganz rausnehmen und wieder nur ein- und ausschalten unterstützen. Dann muss man sich selbst um das Dimmen kümmen. Für eine LED nicht so schwierig, bei mehreren gibt es dann wieder mehrere Prozesse, die man verwalten muss -> komplizierter.
  2. Man könnte das Dimmen hardwareseitig realisieren über eine Art programmierbaren Wiederstand oder eine Hardware PWM.

Wie wichtig ist es, eine LED dimmen zu können? Bin mir da nicht sicher. :-/

Derzeit scheint das PWM-Zeug mehr Probleme zu verursachen als zu lösen. ;)

elektroschule commented 8 years ago

So wichtig ist das Dimmen der LEDs bestimmt nicht. Aus didaktischer Sicht finde ich eine Hardware-Lösung sowieso ganz gut. Ich überlasse dir die Entscheidung, ob und wie du das Dimmen softwaretechnisch realisierst. :)

pintman commented 8 years ago

Ich habe die Funktionalität Dimmen ausgelagert in eigene Klasse DimmbaresEAModul. Die kann verwendet werden, wenn wir es denn doch brauchen. Zunächst würde ich eher verzichten - aus den genannten Gründen.

Den Server habe ich wieder zurück geführt auf das 1-Byte Protokoll. Hier gibt es jetzt keine Unterstützung für Dimmen.

Kannst du mal testen, ob es wieder tut?

pintman commented 8 years ago

Die neue Version lautet 0.3.4.

elektroschule commented 8 years ago

Ich habe keine Fehler gefunden. Es funktioniert alles, wie es soll. Man könnte jetzt bei eapi.net wieder darüber nachdenken, ob man die ungenutzten Bit des Byte nicht nutzt, um die LEDs einzeln zu steuern und nicht immer alle drei gleichzeitig. ;)

pintman commented 8 years ago

Das Feature habe ich in Version 0.3.5 umgesetzt. Hier ist die entsprechende Doku dazu:

Nun wartet der Server auf dem Port 9999 auf UDP-Pakete. Ein an den Server
gesendeter Request besteht aus genau einem Byte - weitere gesendete Bytes
werden ignoriert. Die letzen sechs Bit (0 oder 1) des gesendeten Bytes, werden
als Werte für die rote, gelbe und grüne LED interpretiert:

  ? ? 0 0 1 1 1 0
      ^   ^   ^
      |   |   |
      |   |   grün
      |   gelb
      rot

Für jede Farbe werden zwei Bit verwendet. Das erste Bit besagt, ob die
entsprechende LED geschaltet werden soll (1) oder nicht (0). Wenn die LED
geschalet werden soll, so beschreibt das zweite Bit beschreibt den Zustand, in
den die LED geschaltet werden soll: an (1) oder aus (0) - wenn die
LED nicht geschaltet werden soll, ist der Wert beliebig.

Die Bitsequenz ?? 0? 11 10 (? bedeutet 'beliebig') belässt die rote LED in
ihrem bisherigen Zustandschaltet, schaltet die gelbe LED an und die grüne LED
aus.

Im Client ist dies entsprechend umgesetzt:

   def sende(self, rot, gelb, gruen):
        """Sende an den Server die Information, welche LEDs an- bzw. 
        ausgeschaltet werden sollen.

        Werte von 0 oder 1 für rot, gelb und grün schalten die LED aus bzw. an.
        Andere Werte werden ignoriert und belassen die LED in ihrem bisherigen
        Zustand.
        """
pintman commented 8 years ago

Die obige Doku findet man in der Modulbeschreibung

$ pydoc3 eapi.net

bzw. in der Beschreibung der sende-Methode des Clients:

$ pydoc3 eapi.net.EAModulClient.sende
elektroschule commented 8 years ago

Es ist perfekt! (Ich habe jedenfalls keine Fehler gefunden) :)