Binäruhr in Python / Umstieg auf Arduino / Umstieg auf Wemos D1

  • Tach zusammen,

    ich bastel (noch nur im Kopf und auf dem Papier) an einer Binäruhr.
    Ich habe mir die Zustände von 0-59 aufgezeichnet:
    Meine Frage ist jetzt, wie ich diese Zustände mit möglichst wenig Zeilen umgesetzt bekomme.
    Hier sind jetzt alle möglichen Zustände für zb Minuten aufgezeichnet. Ich will aber keine 60 definieren.
    Die Lampe1 soll also leuchten, wenn alle Minutenwerte ungerade sind (so würde ich die erste Zeile definieren). Wobei ich noch nicht weiß, wie man das in Python macht.
    Und dann? Würdet ihr mit größer/kleiner arbeiten? Lampe16 AN, wenn der Wert größer 15 und kleiner 32 ODER größer 48 und max 59 ist?
    Ich bin da ja absoluter Anfänger und spiele das ganze nur gedanklich durch.
    Am Ende soll es eine RGB-Variante werden, bei der man zusätzlich die additive Farbmischung berücksichtigen muss.
    Mehr oder weniger unlesbar. (Arbeitstitel "Der Unmoment")

    Das Prinzip sind also 3 Schaltungen (Sekunden, Minuten, Stunden) auf 6 Lampen(die jeweils 3-farbig angesteuert werden). Daher käme ich mit 6 RGB-LEDs aus.

  • Python kann denke ich schon decimal => bin: https://docs.python.org/3/library/functions.html#bin

    Den String könnte man dann wieder zurück in int parsen und entsprechend des Indexes im String die LED ansteuern.

    Nur so als Idee :)

    Könnte nach folgendem Schema klappen:
    Zeitstring wird in Elemente aufgeteilt: 11:45:01 =>
    hour = 11
    minute = 45
    second = 01

    Konvertierung in binary:
    hour_binary = bin(hour) = bin(11) = "00001011"
    minute_binary = bin(minute) = bin (45) = "00101101"
    minute_binary = bin(minute) = bin(01) = "00000001"

    LED state anhand des Wertes einer Stelle im String erkennen (wir beginnen von hinten nach vorne, i zählt von 0 bis 8):
    LED0_state = hour_binary[8-i] eq "0" ? 0 : 1;
    i++;
    LED1_state = hour_binary[8-i] eq "0" ? 0 : 1;
    ...

    Oder man switched direkt die LED states (sprich Ausgänge des Controllers) anhand des Vergleichs auf "0" oder "1".

    OpenELEC 5.0 Final (5.0.7 / 5.0.8 github) | SolidRun CuBox-i4Pro (CPU: ARM Cortex A9 | GPU: Vivante GC2000)
    Kein kodi.log => Kein Support! | Spendier' mir ein Bier!

    Einmal editiert, zuletzt von root2 (8. März 2017 um 11:53)

  • Moin, schöne Idee. Hab es aber noch nicht ganz verstanden :D
    Die Uhr besteht also aus 6LEDs und zeigt nur das Bitmuster an? Kannst du damit nicht nur Minuten oder Sekunden anzeigen? Machst du das ganze auch noch für Stunden mit 5LEDs?

    Wenn du das rein auf Bitebene realisieren möchtest, was ich dir auch empfehlen würde, hast du afaik 2 Möglichkeiten.
    Die eine hast du aufgezählt, 60 Zustände auflisten, ziemlich ätzend und langweilig.

    Interessanter wäre es aber, die Bits einzeln auszulesen.
    Das ganze kann man relativ einfach via Bitshifting und Maskierung machen.
    So würde sich das ganze nur auf die einzelnen Abfragen der Bits belaufen, theoretisch nur ein if pro Bit.

    Code
    endlosschleife {
    ...
    *bits auslesen und in (Variable) bitX speichern
    ...
    wenn bit0 == 1: Lampe0 an, sonst aus
    wenn bit1 == 1: Lampe1 an, sonst aus
    wenn bit2 == 1: Lampe2 an, sonst aus
    ...
    }

    Wenn du möchtest, kann auch gerne mal ein kleines Beispiel geben, wie man zb. Bit0 und Bit1 ausliest
    Hoffe ich habe keinen Denkfehler drinnen :)

  • Wenn ich da meinen Senf dazugeben darf,
    vom Prinzip her würe ich das so lösen.

    Gruß
    Claudia

  • 6 RGB LEDs. Also so gesehen 18 LEDs.Jede Einheit hat eine Farbe. Sekunden rot, minuten grün, stunden blau.
    Das ganze dann mit RGB-Streifen (WS2801). Dann wäre ein Ansprechen der RGB-LED Nr 4 (Wert 8) um 8:08 mit 0,255,255 erledigt.

    Da ist ja das Ablesen schon ne harte Aufgabe :D
    Ich habe auch noch WS2801 hier liegen, evtl baue ich mir auch so eine

    Wo du immer die Ideen her nimmst 8)

    edit: @ClaudiaF sehr pythonisch :D

  • Ah, jetzt wirds mir auch etwas klarer :)

    Sollte mit ein paar Variablen und Arrays ganz elegant funktionieren (PseudoCode angelehnt an Python aber eher C):

    OpenELEC 5.0 Final (5.0.7 / 5.0.8 github) | SolidRun CuBox-i4Pro (CPU: ARM Cortex A9 | GPU: Vivante GC2000)
    Kein kodi.log => Kein Support! | Spendier' mir ein Bier!

    2 Mal editiert, zuletzt von root2 (8. März 2017 um 13:00)

  • Ah, das ist ja mit Controller :)

    Dann fallen die ganzen Arrays für die Pins weg und vermutlich müsstest Du in (meinem Beispiel) das

    C
    set pin_LED_red[i](LED_red[i])     // PWM für Sekunden LED an Stelle[i] auf entsprechenden Wert setzen
    set pin_LED_green[i](LED_green[i]) // PWM für Minuten LED an Stelle[i] auf entsprechenden Wert setzen
    set pin_LED_blue[i](LED_blue[i])   // PWM für Stunden LED an Stelle[i] auf entsprechenden Wert setzen


    Ersetzen durch etwas wie:

    Python
    pixels.set_pixel(i, Adafruit_WS2801.RGB_to_color( LED_red[i], LED_green[i], LED_blue[i] ))

    Oder so :)

  • Also ich habe leider gar keine Erfahrung wenn es um die Ansteuerung des RPi geht, dass denke ich weißt Du aber um so mehr.
    Ich peröhnlich würde lieber display_binary so definieren, ist aber reine Geschmacksache.

    Python
    def display_binary(value, row, color):      
        binary_str = "{0:8b}".format(value)
        for x in range(0, 8):
            hat.set_pixel(x, row, color if binary_str[x] == '1' else off)

    Die Farben werden als Tuple gespeichert, (macht Sinn, oder)
    Der Format übernimmt die Aufgabe der Konvertierung in den Binärstring.
    Als Parameter bekommt er den Integer und mit :8b wird gesagt, dass
    der Integer in einen 8 stelligen String als b inär dargestellt werden soll.
    Die 0 vor dem : zeigt an, das der erste Werte nach format genommen werden soll.

    Z.B.

    Python
    '{0}:{1}:{2}'.format(Stunden, Minuten, Sekunden)

    würde {0} mit der Variable Stunden ersetzt, {1} mit Minuten und {2} mit Sekunden.

    Die Angabe ob 0 oder 1 oder 2 ist optional.

    Und da nur Sekunden angezeigt werden, macht der time.sleep(0.0001) wenig Sinn,
    besser dann time.sleep(1) oder time.sleep(0.5) um sicher zu gehen.


    Falls noch Frage sind, gerne ;)


    Gruß

    Claudia

  • O.K.
    Die Sekunden sollte man evtl deaktivieren können.
    Wenn ich mir die Zeichnung so anschaue, glaube ich nicht mal, dass ich es innerhalb einer Minute schaffe, die zu lesen.
    Wenn dann noch jede Sekunde eine Änderung stattfindet, ist es eher eine Lichtorgel.

    (1 ist oben, 32 ist unten)

    .

    Gedacht als Holzstück mit seitlichem Acryl (endlighten o.ä.) mit Zwischenstücken aus Alu. 120x120mm.

  • Auch hier habe ich mit den Tests angefangen.
    Den Code von der "build a binary clock"-Seite habe ich abgeändert, um irgendwie meinen WS2801 zu entsprechen.

    Läuft nicht. Habe ich ja auch nicht erwartet.
    Ich bin davon ausgegangen, dass ich in Zeile 18 von 0-5 zähle (bei 6LEDs).
    Und in den Zeilen 25-27 die Werte 3,4,5 gelöscht. Aber es bringt beides nichts.

    Ohne Änderungen ab Zeile 25:
    Traceback (most recent call last):
    File "/home/pi/fertige Scripte/binary.py", line 29, in <module>
    display_binary(t.hour, 3, hour_color)
    TypeError: display_binary() takes exactly 2 arguments (3 given)

    >>>
    KeyboardInterrupt
    >>> ================================ RESTART ================================
    >>>

    Mit Änderung ab Zeile 25:
    Traceback (most recent call last):
    File "/home/pi/fertige Scripte/binary.py", line 29, in <module>
    display_binary(t.hour, hour_color)
    File "/home/pi/fertige Scripte/binary.py", line 25, in display_binary
    pixels.set_pixel(x, off)
    File "/usr/local/lib/python2.7/dist-packages/Adafruit_WS2801/WS2801.py", line 83, in set_pixel
    r = color >> 16
    TypeError: unsupported operand type(s) for >>: 'tuple' and 'int'

    Vielleicht morgen noch mal ran. Mir fehlt es mal wieder an Basiswissen.

  • Die Adafruit library erwartet einen 24bit Farbenwert, nicht aber einen Tuple wie @freaksworth schon angemerkt hat.


    (Den ersen Parameter self, kannst Du ignorieren, das ist der standardverweis auf die Klasse in dem sich diese
    Funktion befindet)

    Ich würde an deiner Stelle aber ebenfals den Aufruf, welchen Du bei der Lichterkette benutzt hast benutzen

    pixels.set_pixel(i, Adafruit_WS2801.RGB_to_color( r, g, b ))

    und damit Du dein Tuple z.B. hour_color = (0, 255, 0) nicht wieder einzelnen Parametern zuordnen musst,

    r,g,b = hour_color kannst Du auf die derefernzierung zurückgreifen und wie folgt übergeben.

    pixels.set_pixel(i, Adafruit_WS2801.RGB_to_color( *hour_color ))

    Das Sternchen ist das wichtige dabei.

    Oder Du rufst gleich die Funktion set_pixel_rgb auf, welche ja intern auch von set_pixel aufgerufen wird, also

    pixels.set_pixel_rgb(i, *hour_color)

    Desweiteren mußt Du nach set_pixel, laut Library, ein pixels.show aufrufen.

    Und wenn Du bei Python etwas wie "von bis" definieren musst,
    musst Du bedenken, dass das "bis" nicht benutzt wird.
    Also for i in range(5) heisst es werden die Werte 0,1,2,3,4 übergeben,
    oder wenn Du einen String hast sagen wir 'Hello World' und Du definierst etwas wie
    'Hello World'[:3] dann bekommst Du 'Hel' zurück, H=0 e=1 l=2
    Also immer um eins weniger als Du denkst. 6 LEDs = range(7) (die 0 brauchst Du nicht, da die Standard ist)

  • Es gibt ein generelles Problem mit der Art der Umsetzung.
    Dein for x in range(0,5) passt nicht zum binär String da dieser immer 8 stellig ist,
    aber klar, wenn Du nur 6 LEDs hast, kannst Du nicht mehr setzen.

    Wie hast Du Dir das vorgestellt, dass Du mit 6 LEDs das darstellen kannst?
    Willst Du die einzelnen Farbwerte (r,g,b) pro LED für (h:m:s) setzen?

    Am Beispiel von 10:23:59

    Code
    Bits  HH:MM:SS
      1   0  1  1  LED1 = (0,255,255)
      2   1  1  1  LED2 = (255,255,255)
      4   0  1  0  LED3 = (0,255,0)
      8   1  0  1  LED4 = (255,0, 255)
     16   0  1  1  LED5 = (0,255,255)
     32   0  0  1  LED6 = (0,0,255)
          r  g  b

    Dann musst Du die Farben zur Laufzeit ermitteln und kannst diese nicht vorher definieren.
    Ausser Du definierst alle möglichen Werte, was nicht wirklich Sinn macht.

    Falls Du selber basteln willst, ok - ansonsten hätte ich ein kleines Script welches laufen sollte.

  • Willst Du die einzelnen Farbwerte (r,g,b) pro LED für (h:m:s) setzen?

    Ja genau so. Die Farbwerte definieren die Einheit.
    255, 0,0 für h
    0, 255, 0 für m
    0, 0, 255 für Sekunden
    So kann man jede Position (LED) 3-fach belegen.
    Wenn man die 3 Werte zuvor definiert (also r=255, g=255, b=255) könnte man diese auch "mal eben" abändern, um ein harmonischeres Farbspiel zu erzeugen.
    Und man könnte die Sekunden einfach durch 0, 0, 0 bei Bedarf auf AUS stellen.

    Dann musst Du die Farben zur Laufzeit ermitteln und kannst diese nicht vorher definieren.
    Ausser Du definierst alle möglichen Werte, was nicht wirklich Sinn macht.

    Das habe ich mir einfacher vorgestellt. Die Variante mit dem Unicorn-HAT unterscheidet sich doch zu meiner nur durch Reihen.
    Aber ich verstehe den Unterschied. Dort ist jede LED in jeder Reihe ein ansprechbarer Wert.
    Bei mir ist jede LED 3x verschieden anzusprechen.

    Wenn du schon ein Script im Kopf dazu hast, immer her damit. Ich bin schon mit dem reinen Verstehen der Scripte am Limit :)

  • Genereller Python Code:


    im Program wäre dies dann

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!