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 WS2812LEDs einen
Farbverlauf (HSV) durchgehen lässt.
Bei jedem Aufruf soll die erste Stelle um 0.1 erhöht werden.
1
frommachineimportI2C,Pin
2
importtime
3
importutime
4
importmachine,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
defhsv_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
ifh_i==0:r,g,b=v,t,p
17
ifh_i==1:r,g,b=q,v,p
18
ifh_i==2:r,g,b=p,v,t
19
ifh_i==3:r,g,b=p,q,v
20
ifh_i==4:r,g,b=t,p,v
21
ifh_i==5:r,g,b=v,p,q
22
return(int(r*255),int(g*255),int(b*255))
23
24
25
defled_verlauf():
26
forjinrange(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
whileTrue:
34
now=utime.ticks_ms()
35
ifutime.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
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?
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.
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
Chris schrieb:> Scope. r, g und b existieren nicht auf dieser Ebene.>
Python kennt keinen block scope.
Aber wenn einer Variable nichts zugewiesen wird, hat sie auch keinen
Wert.
> 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.
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.
Daniel schrieb:> elif h_i==5: r, g, b = v, p, q> else:> r=0;g=0;b=0
man kann auch else: r, g, b = 0, 0, 0 schreiben damit nicht jeder der
eine einzelne Zeile Code beisteuert wieder einen anderen Schreibstil
einführt sonst sieht es am Ende aus wie ein Flickenteppich.
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.
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
defled_verlauf():
5
globalhsv
6
forjinrange(0,2):
7
np[j]=hsv_to_rgb(hsv,0.9,0.21)
8
np.write()
9
print(hsv)
10
hsv+=schritt
11
ifhsv>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?
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(notsec%2ifhourin(12,23)elsenotsec%3):
2
...
Allgemein geht der ternäre Operator so:
1
xifCelsey
Erst wird "die Mitte" (C) ausgewertet, wenn True, dann wird der gesamte
Ausdruck x, sonst y:
1
notsec%2ifhourin(12,23)elsenotsec%3
Das Ergebnis wird also um 12 und um 23 Uhr not sec % 2 und sonst not sec
% 3
1
notsec%z
wird immer dann True, wenn es keinen Divisionsrest gibt, sonst False
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.
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.
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
Apollo M. schrieb:> if not sec % 2 if hour in range(12, 23) else not sec % 3:
jetzt wird's klar.
Das 'range' war aber heute morgen auch noch nicht da ;)
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.