Seite 2 von 4

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Montag 23. September 2019, 22:17
von __blackjack__
@Frank R.: Das sind kein zwei Fehler sondern ein Fehler und eine Warnung. Beides ist recht selbsterklärend und offensichtlich. Das erste solltest Du Dir selbst klar machen. Was soll denn in der Zeile passieren?

Die Warnung bezieht sich auf das `i` was nirgends verwendet wird, weil Variablen die definiert, aber für nichts verwendet werden, in der Regel auf ein Problem hinweisen. Hier nicht, weil es bei der Schleife ausschliesslich darum geht das der Schleifenkörper wiederholt ausgeführt wird. In solchen Fällen gibt es die Konvention das man Namen die man aus syntaktischen Gründen benötigt, aber deren Wert nicht verwendet wird, einfach mit einem einzelnen Unterstrich benannt werden. Also ``for _ in range(…):`` statt ``for i in range(…):``.

Das ``leds.off`` macht übrigens keinen Sinn, weil die LEDs an der Stelle ja sowieso alle aus sind.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Montag 23. September 2019, 22:29
von Frank R.
So, nochmal überarbeitet:

Code: Alles auswählen

import gpiozero
import time
import random


def main():
    leds = gpiozero.LEDBoard(17, 18, 27, 22, 23, 24, 25, 4, 12)
    button = gpiozero.Button(16)
    numled = len(leds)  # Anzahl aktiver LEDs
    repeat = 5  # Muster wird Repeat mal wiederholt
    ontime = 0.1  # Leuchtdauer der LED
    button.wait_for_press()

    for _ in range(repeat * numled):
        j = random.randint(0, numled - 1)
        leds[j].on()
        time.sleep(ontime)
        leds[j].off()
    

if __name__ == '__main__':
    main()
Wenn ich das Programm starte, und den Taster drücke, leuchten die LEDs alle zufällig auf und gehen danach alle aus. So weit, so gut. Allerdings passiert beim zweiten Druck auf den Taster dann nicht mehr. Wenn ich debugge, werden mir bis ans Ende keine Fehler angezeigt, aber auch keine Meldung vom Assistant. Steckt also doch noch ein Fehler drin?
Update: Es kam doch eine Meldung vom Assistant > "looks good".

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Montag 23. September 2019, 23:00
von __blackjack__
@Frank R.: Natürlich passiert beim zweiten Druck nichts mehr. Warum sollte es auch? Das Programm ist dann ja zuende und läuft nicht mehr. Wenn Du etwas wiederholen möchtest, brauchst Du eine Schleife in der das steht was Du wiederholen möchtest. Das hat Sirius3 bereits zu Deinem Punkteplan geschrieben, das man das für Punkt 6 braucht.

Ich würde ja mindestens `random.randrange()` statt `random.randint()` verwenden — dann kann man sich das abziehen der 1 sparen und auch die explizite 0. Aber besser ist wirklich das mit dem Index sein zu lassen und `random.choice()` zu verwenden.

Bei den Namen sollte man auch nichts abkürzen und zwischen Worte auch einen Unterstrich setzen. Also `led_count` statt `numled` und `on_time` statt `ontime`. Oder noch besser `led_on_duration`, dann kann man sich den Kommentar sparen. `repeat` klingt auch eher nach einer Tätigkeit, ist also ein Name für aktive Werte wie Funktionen oder Methoden. `repetitions` oder `repetition_count` wäre da passender.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Dienstag 24. September 2019, 09:12
von Frank R.
@__blackjack__

Guten Morgen,
danke für Deine Hinweise :-) Werde ich im Laufe des Tages mal austesten und dann Rückmeldung geben.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 28. September 2019, 14:21
von Frank R.
Hallo, leider etwas verspätet, aber hier ist der überarbeitete Code:

Code: Alles auswählen

import gpiozero
import time
import random

def main ():
    while True:
        prompt_user()

def prompt_user():
    leds = gpiozero.LEDBoard(17, 18, 27, 22, 23, 24, 25, 4, 12)
    button = gpiozero.Button(16)
    led_count = len(leds)  # Anzahl aktiver LEDs
    repetition_count = 5  # Muster wird repetition_count mal wiederholt
    on_time = 0.1  # Leuchtdauer der LED
    button.wait_for_press()

    for _ in range(repetition_count * led_count):
        j = random.randrange(led_count)
        leds[j].on()
        time.sleep(on_time)
        leds[j].off()


if __name__ == '__main__': main()
Ich habe den Code getestet, und so wie es aussieht funktioniert die Schleife auch so wie gedacht. Bitte trotzdem mal drüber gucken :-)

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 28. September 2019, 14:37
von Sirius3
Jetzt ist nur noch die Aufteilung, was alles in der Schleife passiert, etwas ungünstig.

Code: Alles auswählen

import gpiozero
import time
import random

def play_leds(leds):
    repetition_count = 5  # Muster wird repetition_count mal wiederholt
    on_time = 0.1  # Leuchtdauer der LED
    for _ in range(repetition_count * led(leds)):
        led = random.choice(leds)
        led.on()
        time.sleep(on_time)
        led.off()

def main ():
    leds = gpiozero.LEDBoard(17, 18, 27, 22, 23, 24, 25, 4, 12)
    button = gpiozero.Button(16)
    while True:
        button.wait_for_press()
        play_leds(leds)

if __name__ == '__main__':
    main()

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 28. September 2019, 14:48
von Frank R.
Hallo Sirius3,

danke für Deine Antwort, aber ist da nicht ein Fehler drin? Vor "if __name...." steht "prompt_user(leds)". Sollte das nicht eher "play_leds(leds)" heißen? Das Zeile bezieht sich ja auf "def play_leds(leds) :"

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 28. September 2019, 15:05
von Sirius3
ja, hab ich geändert.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 28. September 2019, 15:12
von Frank R.
Habe den Code eben mal gestartet, da kommt folgende Fehlermeldung in Zeile 8:

UnboundLocalError: local variable 'led' referenced before assignment

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 28. September 2019, 15:55
von Sirius3
muß ja auch ›len‹ heißen.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 28. September 2019, 16:01
von Frank R.
Sieht gut aus, habe "led" in "len" geändert. Besten Dank Sirius3.

Jetzt bleibt nur noch der Teil, dass die zuletzt aktivierte LED für einige Sekunden eingeschaltet bleibt. Ich schaue mal, ob ich dazu was finde.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 19. Oktober 2019, 21:10
von Frank R.
Hallo,

nach dem ich jetzt tagelang nach Antworten gesucht habe, bin ich leider immer noch nicht schlauer geworden. Ist es überhaupt möglich, die Zufallswiedergabe so zu ändern, dass die zuletzt aktivierte LED noch für einige Sekunden eingeschaltet bleibt? Mir ist zwar bekannt, dass es neben der sleep noch eine delay Funktion gibt, aber wie ich den Code schreiben muss... Also, geht das überhaupt, oder kann ich das Suchen auch aufgeben?

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 19. Oktober 2019, 21:28
von Sirius3
Wo willst Du denn nach Antworten suchen? Als Programmierer mußt Du die Antwort selbst entwickeln, und zwar aus Bausteinen, die Du schon kennst, also Zufalls-LED auswählen, für ein paar Sekunden warten, LED ausschalten.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 19. Oktober 2019, 21:58
von Frank R.
Ich habe nach Beispielen gesucht, bei https://py-tutorial-de.readthedocs.io/de/python-3.3/# z.B. Habe aber nichts gefunden, bzw. weiß nicht wie ich das realisieren soll. Ich habe zwar eine vage Vermutung, wie das funktionieren könnte, aber das war's dann auch.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Samstag 19. Oktober 2019, 22:11
von Sirius3
Dann mußt Du nur noch die vage Idee, die ich meiner Meinung nach recht konkret beschrieben habe, umsetzen.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Donnerstag 7. November 2019, 19:28
von Frank R.
Wieder mal später als geplant, aber mittlerweile weiß ich wirklich nicht mehr weiter. Das einzige Code Beispiel, was ungefähr mit meinem Problem zu tun hat, ist der elektronische Würfel mit 6 Zahlen. Der wird natürlich noch mittels Port Expander betrieben, und der Code ist entsprechend anders. Das Prinzip ist aber genau das, was ich brauche: Zufällige, SCHNELLE Wiedergabe der einzelnen LEDs zur Darstellung von "Zahlen", und die zuletzt angezeigte Zahl bleibt aktiviert. Analog zu meinem Projekt wäre das eben die zufällige LED Schaltung (z.B. mit einem time.sleep (on_time) von 0.02) und nach Erreichen des Wertes bei "repetition_count" bleibt die zuletzte aktivierte LED aktiv (entweder für eine festgelegte Zeit, oder bis der Taster erneut gedrückt wird.) Ich habe schon versucht, den Code anzupassen, aber ohne Erfolg.

Der aktuelle Code (siehe unten) funktioniert, aber wenn ich einfach nur die on_time erhöhe, bleiben ja ALLE LEDs entsprechend lange angeschaltet, aber das sollen sie ja nicht. NUR die letzte LED soll z.B. für 10 Sekunden, oder bis per Tasterdruck der Ablauf neu gestartet wird aktiviert sein. Und da hakt's.

Code: Alles auswählen

import gpiozero
import time
import random

def play_leds(leds):
    repetition_count = 20  # Muster wird repetition_count mal wiederholt
    on_time = 0.02  # Leuchtdauer der LED
    for _ in range(repetition_count * len(leds)):
        led = random.choice(leds)
        led.on()
        time.sleep(on_time)
        led.off()

def main():
    leds = gpiozero.LEDBoard(17, 18, 27, 22, 23, 24, 25, 4, 12)
    button = gpiozero.Button(16)
    while True:
        button.wait_for_press()
        play_leds(leds)

if __name__ == '__main__':
    main()

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Donnerstag 7. November 2019, 19:37
von Sirius3
Dafür mußt Du Code schreiben, der mit der zuletzt gewählten LED etwas macht.

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Donnerstag 7. November 2019, 20:34
von Frank R.
So, nachdem ich mich mit jemandem kurzgeschlossen habe der "etwas" mehr Ahnung hat als ich, ist derzeit folgender Code aktuell. Aber immer noch fehlerhaft:

Code: Alles auswählen

import gpiozero
import time
import random

def play_leds(leds):
    repetition_count = 20  # Muster wird repetition_count mal wiederholt
    on_time = 0.02  # Leuchtdauer der LED
    
    for i in range(repetition_count):
        led = random.choice(leds)
        led.on()
        time.sleep(on_time)
        if i < repetition_count-1:
            led.off()

def main():
    leds = gpiozero.LEDBoard(17, 18, 27, 22, 23, 24, 25, 4, 12)
    button = gpiozero.Button(16)
    while True:
        button.wait_for_press()
        play_leds(leds)

if __name__ == '__main__':
    main()
Wenn ich jetzt den Taster drücke, läuft die Zufallswiedergabe und die zuletzt aktivierte LED bleibt an, bis ich den Taster wieder drücke. ABER: Manchmal bleiben ZWEI LED an, nicht nur ein. Also irgendwo stimmt noch was nicht :?:

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Donnerstag 7. November 2019, 21:05
von Sirius3
Wo schaltest Du denn die letzte LED wieder aus?

Re: Abfrage der Laufzeit entfernen und weiteres

Verfasst: Donnerstag 7. November 2019, 21:14
von Frank R.
nochmal überarbeitet, und ja, wo schalte ich die aus? Fehlt offensichtlich

Code: Alles auswählen

import gpiozero
import time
import random

def play_leds(leds):
    repetition_count = 20 * len(leds)  # Muster wird repetition_count mal wiederholt
    on_time = 0.1  # Leuchtdauer der LED
    
    for i in range(repetition_count):
        led = random.choice(leds)
        led.on()
        time.sleep(on_time)
        if i < repetition_count-1:
            led.off()

def main():
    leds = gpiozero.LEDBoard(17, 18, 27, 22, 23, 24, 25, 4, 12)
    button = gpiozero.Button(16)
    while True:
        button.wait_for_press()
        play_leds(leds)

if __name__ == '__main__':
    main()