erster µPython Versuch - Frage zu Definition von Variablen

OP #6121693
Lesenswert?

Hallo

Ich habe es getan!
Seit ein paar Stunden läuft auf meinem ESP8266 Micropyhon.
Kleiner Hinweis: die IDE Thonny hat mir dem Umstieg von der Arduino Welt 
recht einfach gemacht ;-)
Das Tollste: der Code muss nicht mehr compilieren
Damit ist eine Änderung nicht erst nach (gefühlten) 60 Sekunden,
sondern quasi sofort (gefühlt 3 Sekunden) auf dem Board sichtbar.
Großartig!

Nachteil 1: Python ist als Skriptsprache deutlich langsamer

Nachteil 2: Python ist recht neu für mich und (obwohl oft als 
Einsteigersprache genannt) einfach anders als das Arduino C++

Jetzt zu meinem aktuellen Problem:

Ich möchte gerne eine Funktion aufrufen, welche meine WS2812 LEDs einen 
Farbverlauf (HSV) durchgehen lässt.

Bei jedem Aufruf soll die erste Stelle um 0.1 erhöht werden.
1
from machine import I2C, Pin
2
import time
3
import utime 
4
import machine, neopixel
5

6
np = neopixel.NeoPixel(machine.Pin(13), 16)
7
i2c = I2C(scl=Pin(5), sda=Pin(4)) 
8

9
# HSV values in [0..1]  returns (r, g, b) values from 0 to 255
10
def hsv_to_rgb(h, s, v):
11
    h_i = int((h*6))
12
    f = h*6 - h_i
13
    p = v * (1 - s)
14
    q = v * (1 - f*s)
15
    t = v * (1 - (1 - f) * s)
16
    if h_i==0: r, g, b = v, t, p
17
    if h_i==1: r, g, b = q, v, p
18
    if h_i==2: r, g, b = p, v, t
19
    if h_i==3: r, g, b = p, q, v
20
    if h_i==4: r, g, b = t, p, v
21
    if h_i==5: r, g, b = v, p, q
22
    return (int(r*255), int(g*255), int(b*255))
23

24

25
def led_verlauf():
26
    for j in range(0, 2):
27
        np[j] = hsv_to_rgb(1, 0.9, 0.21) 
28
    np.write() 
29
    print(k)
30
    
31
    
32
after_now = utime.ticks_ms()
33
while True:
34
    now = utime.ticks_ms()
35
    if utime.ticks_diff(now, after_now) > 100:
36
        led_verlauf()        
37
        after_now = now
Leider bekomme ich eine Felhermeldung angezeigt, die ich nicht 
nachvollziehen kann:

NameError: local variable referenced before assignment

Bezogen auf die letzte Zeile der hsv_to_rgb() Funktion.

Auf sich alleine gestellt, also nur mit hsv_to_rgb(1,1,1) funktioniert 
es aber wie es soll.

Bitte seht mir nach, wenn ich gerade den allerdümmsten Anfängerfehler 
mache,
es ist mein allererste Fehler mit dieser Sprache.

Danke und Gruß

Kolja
OP #6121732
Lesenswert?

Karl schrieb:
> Du schaffst es tatsächlich einen Python-Code so unverständlich wie eine
> C-Code zu machen.

Das wundert jetzt hoffentlich keinen...

Karl schrieb:
> Abgesehen davon gibt es das schon eingebaut:
> https://docs.python.org/2/library/colorsys.html

Leider nicht für / in Micropython

Chris schrieb:
> Aber wenn das mal der einzige Fehler wäre..

Sag mir bitte welche, Danke

Daniel schrieb:
> r,b,g ist undefiniert

Wie und wo definiere ich die?
Gast #6121749
Lesenswert?

def hsv_to_rgb(h, s, v):
    h_i = int((h*6))
    f = h*6 - h_i
    p = v * (1 - s)
    q = v * (1 - f*s)
    t = v * (1 - (1 - f) * s)

    if h_i==0: r, g, b = v, t, p
    elif h_i==1: r, g, b = q, v, p
    elif h_i==2: r, g, b = p, v, t
    elif h_i==3: r, g, b = p, q, v
    elif h_i==4: r, g, b = t, p, v
    elif h_i==5: r, g, b = v, p, q
    else:
      r=0;g=0;b=0
    return (int(r*255), int(g*255), int(b*255))

zum Beispiel. kein schöner code, aber er funktioniert. kann sein, dass 
du statt 0, 1 brauchst.
(Firma: @home) #6121864
Lesenswert?

Kolja L. schrieb:
> Ich habe es getan!

ich auch ..., start war vor 2 jahren und mein python code sah so ähnlich 
aus, sprich mein c code nur in python syntax, grausam!

Kolja L. schrieb:
> das Tollste: der Code muss nicht mehr compilieren

das wird nicht lange so bleiben, wer richtig mit mpy unterwegs ist kommt 
an froozen code nicht vorbei, spricht du musst dann die tool chain z.b. 
in vbox/linux aufsetzen ... und mpy immer übersetzen, was bei mir auf 
"knopfdruck" unter w8/10 alles startet einschließlich flashen.


für das if/else gedöns... kannst du mal probieren

colors = ([v,t,p], [q,v,p], ...)
r,g,b = c for i,c in enumerate(colors) if h_i == i
return bytes([round(r*255), ...])

ich "liebe" mpy!


mt
Gast #6121955
Lesenswert?

> if not sec % 2 if hour in (12, 23) else not sec % 3:

In dem sehr guten Buch "weniger schlecht Programmieren" legen einige der 
besten Programmierer dar, dass guter Code lesbar sein soll wie ein gutes 
Buch und zwar für den Menschen, nicht für den Computer:

https://www.oreilly.de/buecher/120174/9783897215672-weniger-schlecht-programmieren.html

Insofern sind komplexe Konstrukte einer Programmiersprache zu vermeiden, 
sondern nur diese zu verwenden, die für den Menschen eingängig sind.

Es ist keine Zeichen für einen guten Programmierstil den Code möglichst 
kurz zu halten, sondern den Code für den Menschen schön und lesbar zu 
gestalten.

Insofern war das Beispiel von Kolja am Anfang schon mal viel besser als 
alles nachher gezeigte.
OP #6121984
Lesenswert?

Daniel schrieb:
> else:
>       r=0;g=0;b=0

Danke, da ging mir ein Licht auf ?

chris schrieb:
> Insofern war das Beispiel von Kolja am Anfang schon mal viel besser als
> alles nachher gezeigte.

Insbesondere da es sich hier um die Frage eines blutigen Anfängers 
handelt.
Hab mal irgendwo aufgeschnappt: make it run, make it secure, make it 
fast.
Ich bin noch ganz am Anfang von "make it run".

Aber nur durch Fehler lernt man, also weiter gehts.
#6122010
Lesenswert?

Apollo M. schrieb:
> verstehst du sowas, was passiert hier?
>
> if not sec % 2 if hour in (12, 23) else not sec % 3:
>    ... # set led
> else:
>    ... # clear led

Das muss das hässlichste Stück Python-Code sein daß ich in meinem ganzen 
Leben jemals gesehen habe. Mit Abstand! Wo hast Du den gefunden?

Auch mit dem Wissen um die Ternäre-Operator-Syntax gelingt es mir auch 
nach 5 Minuten intensivem Nachdenkens und Klammern setzens im Kopf nicht 
zu ergründen warum dieser Code keinen Syntaxerror produziert, geschweige 
denn zu verstehen was er überhaupt tun soll. Ich gebe auf.
OP #6122028
Lesenswert?

Bernd K. schrieb:
> man kann auch else: r, g, b = 0, 0, 0 schreiben

Danke, jetzt sieht es auch noch einheitlich aus.
Funktioniert hat es natürlich schon vorher.

Gleich noch mal ne Frage:

Ich erhöhe beim Aufruf einer Funktion den Wert einer Variable immer um 
0.01:
1
## LEDs mit HSV aufrufen und anschliessend HSV erhoehen
2
hsv = 0
3
schritt = 0.01
4
def led_verlauf():
5
    global hsv
6
    for j in range(0, 2):
7
        np[j] = hsv_to_rgb(hsv, 0.9, 0.21) 
8
    np.write()
9
    print(hsv)
10
    hsv += schritt
11
    if hsv > 0.99: hsv = 0

In der Ausgabe finde ich aber sowas:

0.08
0.0899999
0.0999999
0.11

Ich will jetzt nich päptlicher sein als der Papst (egal welcher von 
denen),
denn 0.0899999 ist schon recht nah an 0.09 und den Unterschied in der 
Lichtfarbe wird niemand sehen, aber woher kommt diese Ungenauigkeit?
#6122081
Lesenswert?

Bernd K. schrieb:
> Das muss das hässlichste Stück Python-Code sein daß ich in meinem ganzen
> Leben jemals gesehen habe. Mit Abstand! Wo hast Du den gefunden?
>
> Auch mit dem Wissen um die Ternäre-Operator-Syntax gelingt es mir auch
> nach 5 Minuten intensivem Nachdenkens und Klammern setzens im Kopf nicht
> zu ergründen warum dieser Code keinen Syntaxerror produziert, geschweige
> denn zu verstehen was er überhaupt tun soll. Ich gebe auf.

Ich find's auch alles andere als schön. Aber erklären kann ich's, wenn 
Du möchtest:

Bernd K. schrieb:
> if not sec % 2 if hour in (12, 23) else not sec % 3:

"Klammernsuche" war der richtige Ansatz. Die gehören so:
1
if (not sec % 2 if hour in (12, 23) else not sec % 3):
2
...

Allgemein geht der ternäre Operator so:
1
x if C else y

Erst wird "die Mitte" (C) ausgewertet, wenn True, dann wird der gesamte 
Ausdruck x, sonst y:
1
not sec % 2 if hour in (12, 23) else not sec % 3

Das Ergebnis wird also um 12 und um 23 Uhr not sec % 2 und sonst not sec 
% 3
1
not sec % z
wird immer dann True, wenn es keinen Divisionsrest gibt, sonst False
#6122104
Lesenswert?

Kolja L. schrieb:
> Ich will jetzt nich päptlicher sein als der Papst (egal welcher von
> denen),
> denn 0.0899999 ist schon recht nah an 0.09 und den Unterschied in der
> Lichtfarbe wird niemand sehen, aber woher kommt diese Ungenauigkeit?

Willkommen in der Welt der Rundungsfehler!
Floatingpoint Darstellung von Zahlen funktioniert nicht exakt für Zahlen 
wie 0.1, während 0.5, 0,25, 0.125 exakt darstellbar sind.
Die Darstellung erfolgt auf der Basis von Zweierpotenzen, in 0.1 steckt 
aber 5 als Teiler, und das ist eben keine Zweierpotenz.
#6122108
Lesenswert?

Dies ist auch der Grund warum man bei Buchhaltungssoftware oder allem 
was mit Geldbeträgen zu tun hat (egal in welcher Programmiersprache) 
grundsätzlich in Integern rechnet (also in Beträgen von Cent oder 
kleiner) und niemals in Fließkomma und immer erst bei der Darstellung 
wieder das Komma an der richtigen Stelle setzt.
(Firma: @home) #6122183
Lesenswert?

Bernd K. schrieb:
> Das muss das hässlichste Stück Python-Code sein daß ich in meinem ganzen
> Leben jemals gesehen habe.

nö, du musst aber sicher noch viel lernen, https://realpython.com/
z.b. https://realpython.com/python-or-operator/

keyword: pythonic code - und nicht c/c++ code in python syntax!


Markus F. schrieb:
> Ich find's auch alles andere als schön. Aber erklären kann ich's, wenn
> Du möchtest:

if not sec % 2 if hour in range(12, 23) else not sec % 3:
   ... # set led
else:
   ... # clear led

der code dient in einer "24h uhr" (12 neopixel ring) und lässt die sec 
led von 0-12h im 2sec takt und von +12-24 alle 1sec blinken.

wichtig ist mir hier, dass das ternary "überall" stehen kann, also hier 
nicht als right value sondern als condition.


geklammert wird python nur wenns pflicht ist; siehe style guide, 
https://www.python.org/dev/peps/pep-0008/!


mt
#6122516
Lesenswert?

Apollo M. schrieb:
> nö

Doch. Das kann man lesbarer hinschreiben, da kann man noch ein oder zwei 
Variablen für Zwischenergebnisse spendieren mit aussagekräftigem Namen. 
Und das "not" bei dem man grübeln muss zu welcher Seite es nun gehört 
("if not" oder "not sec % 2") kann man sich auch schenken wenn man das 
if umdreht. "Pythonisch" bedeutet nicht absichtlich maximal unleserlich.


1
afternoon = hour in range(12, 23)
2
blinkphase = sec % 2 if afternoon else sec % 3
3

4
if blinkphase:
5
    ...
6
else:
7
    ...

/meinung

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren