Forum: Mikrocontroller und Digitale Elektronik Pico2 und WS2812 (mehr Kanäle?)


von Robert P. (robertoo)


Lesenswert?

Hallo

Versuche mich jetzt neu in den Pico 2 (RP2350) ein zu arbeiten.
Habe auch schon einen zweiten Pico zum Debugen und Programieren 
verdrahtet.
Habe vorher ein bisschen mit Mega8 und C gemacht.
Bin aber relativ ein Anfänger
Programieren möchte ich eher in C als in Python, da C doch 10mal 
schneller ist. (bin aber C-Anfänger)

Versuche jetzt eine Kette mit WS2812 an zu steuern.
Derzeit funktioniert eine Kette mit 250 Leds und den Code von hier:
https://github.com/raspberrypi/pico-examples/tree/master/pio/ws2812

Das läuft aber nur mit einem Pin (Kanal)
Ich möchte aber min 3 Led-Ketten anhängen  (also 3 Kanäle)

Kennt jemand einen Code, wo man mehr Kanäle für den WS2812 betreiben 
kann ?

Der Pico ist ja sehr viel anders als der Mega 8
Kennt jemand vielleicht gute Foren auf deutsch, wo das vielleicht gut 
behandelt wird, oder bin ich hier eher doch richtig ?

Ich war vor der Wahl zwischen Arduino und Pico
Habe mich für Pico entschieden weil es scheinabr vortschritlicher ist, 
aber scheinbar gibt es für Arduino doch viel mehr Beispiele und Anwender 
als für Pico?!

l.G. Roberto

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Robert P. schrieb:
> Kennt jemand einen Code, wo man mehr Kanäle für den WS2812 betreiben
> kann ?

Hast du doch schon. Selbst der Pico 1 hat 4 PIO Engines und ich schätze, 
das der Pico 2 dem nicht nachsteht. Du wirfst den PIO Engines den 
gleichen Code wie für PIO 1 hin, musst nur die Pins verändern.
Übrigens spielt es für die PIOs keine Rolle, ob sie aus Python oder C 
programmiert werden, das hat auf die Geschwindigkeit keinen Einfluss.

Tutorials sogar auf Deutsch findet man auf Youtube - meist für den PICO 
'1'.

: Bearbeitet durch User
von Norbert (der_norbert)


Lesenswert?

Robert P. schrieb:
> Das läuft aber nur mit einem Pin (Kanal)
> Ich möchte aber min 3 Led-Ketten anhängen  (also 3 Kanäle)
>
> Kennt jemand einen Code, wo man mehr Kanäle für den WS2812 betreiben
> kann ?

Der PICO2 hat drei PIOs, also zwölf StateMachines und kann somit zwölf 
'Ketten' allein darüber ansteuern. Wenn du dir die Mühe machst zu 
verstehen, wie die doch recht triviale Funktion implementiert ist, dann 
sollte keine allzu hohe mentale Transferleistung notwendig sein den 
zuvor kopierten Code zu erweitern.

von Norbert (der_norbert)


Lesenswert?

Matthias S. schrieb:
> Selbst der Pico 1 hat 4 PIO Engines

Ähm, nö!
Der 2040 hat zwei PIOs a vier StateMachines.

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Norbert schrieb:

> Der PICO2 hat drei PIOs, also zwölf StateMachines und kann somit zwölf
> 'Ketten' allein darüber ansteuern.

Viel mehr. Schließlich kann jede Statemachine bis zu 32 Pins 
gleichzeitig "bedienen".

von Norbert (der_norbert)


Lesenswert?

Ob S. schrieb:
> Viel mehr. Schließlich kann jede Statemachine bis zu 32 Pins
> gleichzeitig "bedienen".

Das stimmt. Allerdings muss man dann die zu übertragenden Daten vorher 
schön miteinander verweben. ;-)

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Norbert schrieb:

> Das stimmt. Allerdings muss man dann die zu übertragenden Daten vorher
> schön miteinander verweben. ;-)

Schon.

Das kann man aber auch sehr schön durch die PIO erledigen lassen. Mit 
Bits zu jonglieren ist ja gerade eine ihrer speziellen Fähigkeiten.

von Falk B. (falk)


Lesenswert?

Robert P. schrieb:
> Kennt jemand einen Code, wo man mehr Kanäle für den WS2812 betreiben
> kann ?

Beitrag "Einfache Ansteuerung von 8x WS2812B"

von Robert P. (robertoo)


Lesenswert?

@Norbert
>>Wenn du dir die Mühe machst zu
verstehen, wie die doch recht triviale Funktion implementiert ist, dann
sollte keine allzu hohe mentale Transferleistung notwendig sein den
zuvor kopierten Code zu erweitern.

mmmhh..
Könnte man einen Kanal einfach mehr mal anlegen, für unterschiedliche 
pins?

Habe mal den Code durchgekaut, aber nicht so recht Plan.


Habe auch das hier gefunden:
https://mcuoneclipse.com/2023/04/02/rp2040-with-pio-and-dma-to-address-ws2812b-leds/
Da wird das ein bisschen beschrieben...

Aber so recht fehlt mir der Plan :-(

von Norbert (der_norbert)


Lesenswert?

Robert P. schrieb:
> Könnte man einen Kanal einfach mehr mal anlegen, für unterschiedliche
> pins?

Ganz bequem?
Wenn der PIO code vernünftig geschrieben ist, muss man den nur einmal 
anlegen sowie einmal pro PIO (also für je vier StateMachines) laden.
Jede Statemachine (0…11) steuert mit diesem Code nur jeweils einen GPIO 
Pin an. Danach kann man in die SM-FIFOs einfach die zu übertragenden 
Daten manuell einschreiben, oder – für die Bequemen unter uns – mittels 
DMA einschieben.

PS. Mit µPy wärst du schon gestern fertig. (Bei vollkommen identischer 
Geschwindigkeit)

von Robert P. (robertoo)


Lesenswert?

@Norbert
>PS. Mit µPy wärst du schon gestern fertig. (Bei vollkommen identischer
Geschwindigkeit)

Du machst mich echt neugirig. ;-)

Programierst du in Python ?
Was für eine Umgebung würdest du empfehlen ?
In VS-Code oder in Thonny Python ?

Kann ich da auch meinen zweiten Pico zum Programmieren/Debugen verwenden 
oder muss ich da den Pico immer neu anstecken und die .uf2 rüberladen?

l.G. Roberto

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Robert P. schrieb:
> oder muss ich da den Pico immer neu anstecken und die .uf2 rüberladen?

Du lädst nur einmal das .UF2 File für Micropython selbst auf den Pico. 
Die eigentlichen *.py Programme kommen per z.B. Thonny oder anderer 
Konsole auf den Pico. Nennst du ein Programm 'main.py', ist es ein 
Autostarter und wird nach dem Einschalten des Pico ausgeführt.
Du merkst, ich benutze Thonny, aber alles andere geht natürlich auch. 
Nur so als Beispiel, hier steuert ein Pico (1) mit MPy ein RC Car mit 
SBUS Dekoder, 2 MotorESC, Lichtsteuerung und einem RC Servo ohne 
irgendwelche Engpässe, und dabei benutze ich noch nicht mal die PIOs.
PIO Programmierung erfordert am Anfang eine neue Rangehensweise an 
Programmierung, macht aber Spass. Benutze ich z.B. als Ausgabe an ein 
LC-Display mit MM5453 Treiberchip, von dem du sicher noch nie gehört 
hast. Ich auch nicht, aber sein ulkiges Datenformat bot sich für PIO 
geradezu an.

von Norbert (der_norbert)


Lesenswert?

Robert P. schrieb:
> Programierst du in Python ?
Nebst vielen anderen Sprachen.

> Was für eine Umgebung würdest du empfehlen ?
> In VS-Code oder in Thonny Python ?
Empfehlungen sind so eine Sache. Ich nutze vi, manchmal gvim, manchmal 
geany. Von den beiden von dir genannten würde ich keine anfassen wollen. 
Vor allem weil Thonny gern die Gelegenheit ergreift, unangenehm 
aufzufallen. Genügend dokumentierte Fälle findet man.

> Kann ich da auch meinen zweiten Pico zum Programmieren/Debugen verwenden
> oder muss ich da den Pico immer neu anstecken und die .uf2 rüberladen?

Matthias hat's schon gut erklärt, nur einmal das passende uf2 drauf und 
danach werden Programme und Daten per /dev/ttyACM[0-9] (COMirgendwas:, 
oder wie auch immer das Zeug unter Windows heißt) übertragen.
Dafür eignet sich zB. pyboard.py prächtig (temporäres übertragen oder 
auch Änderungen am internen Dateisystem)

von Stephan S. (uxdx)


Lesenswert?

Micropython hat die Bibliothek neopixel, damit kann man ganz einfach 
beliebige WS281x-LEDs setzen.

z.B.
1
import machine, neopixel
2
pin = machine.Pin(48, machine.Pin.OUT)  # an Pin 48 ist WS2812 angeschlossen
3
np = neopixel.NeoPixel(pin, 60)         # 60x WS2812
4
# jetzt geht's los
5
np[7] = (255, 0, 0)                     # WS2812 Nr. 8 soll hell rot werden
6
np[11] = (0, 64, 64)                    # WS2812 Nr. 12 soll etwas cyan werden
7
np[27] = (128, 128, 128)                # WS2812 Nr. 28 soll mittelweiss werden
8
np.write()                              # jetzt werden die 3 WS2812 gesetzt

Hier ein "laufender Regenbogen":
1
import machine, neopixel, time
2
3
pin = machine.Pin(48, machine.Pin.OUT)
4
np = neopixel.NeoPixel(pin, 60)  # 60 LED
5
6
bri = 2                          # Divisor fuer Helligkeit
7
colinc = [0, 64, 128, 192, 255]  # Liste fuer aufst. Helligkeitsstufen, 0..255
8
coldec = colinc[::-1]            # umgekehrte Liste für abst. Helligkeit
9
tim = 0.1                        # Zeit fuer sleep
10
11
def setcol():
12
  global r, g, b, bri
13
  for pos in range(58, -1, -1):  # Pixel nach rechts durchschieben
14
    np[pos + 1] = np[pos]
15
  rr = int(r / bri)              # Helligkeit berechnen
16
  gg = int(g / bri)
17
  bb = int(b / bri)
18
  np[0] = (rr, gg, bb)
19
  np.write()
20
  time.sleep(tim)
21
22
def rainbow():
23
  global r, g, b, bri
24
  r = 255
25
  g = 0
26
  b = 0
27
# rot - gelb
28
  for g in colinc:
29
    setcol()
30
# gelb - gruen
31
  for r in coldec:
32
    setcol()
33
# gruen - cyan
34
  for b in colinc:
35
    setcol()
36
# cyan - blau
37
  for g in coldec:
38
    setcol()
39
# blau - magenta
40
  for r in colinc:
41
    setcol()
42
# magenta - rot
43
  for b in coldec:
44
    setcol()
45
46
while True:
47
  rainbow()

: Bearbeitet durch User
von Norbert (der_norbert)


Lesenswert?

Oder etwas lesbarer als die – meiner Meinung nach schreckliche – Neo 
Implementation…
1
#!python
2
# vim: fileencoding=utf-8: ts=4: sw=4: expandtab:
3
from machine import Pin
4
from machine import bitstream
5
from uctypes import struct,addressof,ARRAY,UINT8
6
gpio_pin = 23
7
numleds  = 1
8
timing   = (400, 850, 800, 450) # lowbit:hi,lo highbit:hi,lo (see datasheet)
9
10
pin = Pin(gpio_pin, Pin.OUT, 0)
11
ledarray = { 'led': (0 | ARRAY, numleds , { 'g': 0 | UINT8, 'r': 1 | UINT8, 'b': 2 | UINT8 } ) }
12
leds = struct(addressof(bytearray(numleds*3)), ledarray)
13
for i in range(numleds):
14
    leds.led[i].r = 0x01
15
    leds.led[i].g = 0x01
16
    leds.led[i].b = 0x05
17
bitstream(pin, 0, timing, leds)

Wobei das trotzdem noch timing-wackeliger, Arduino-ähnlicher, 
blockierender Code ist, von dem ich noch nie ein Freund war.
Aber für'n quick hack reicht's sicherlich.

von Robert P. (robertoo)


Lesenswert?

Danke für die Antworten !
Ich werde mich mal da reinarbeiten..

Aber was anderes, weil gerade so viel Fachleute hier sind:
Kann man eigetlich den programierten Code in einem Pico auch schützen ?
Beim Mega 8 gib es ja Flags, die man setzen kann, womit man das auslesen 
verhindern kann.
Gibt es sowas bei einem Pico auch ?
Bei Pyhton oder C?

l.G. Roberto

von Harald K. (kirnbichler)


Lesenswert?

Robert P. schrieb:
> Kann man eigetlich den programierten Code in einem Pico auch schützen ?

Nein, denn der Code steckt gar nicht im µC, sondern in dem seriellen 
Flashbaustein daneben.

Hältst Du es für wahrscheinlich, daß irgendjemand Deinen Code "klauen" 
will?


BTW: Vor Fragezeichen gehört kein Leerzeichen.

von Robert P. (robertoo)


Lesenswert?

>BTW: Vor Fragezeichen gehört kein Leerzeichen.
Das stört dich? ;-)
Dann wird dich meine Rechtschreibung total frustrieren ;-)

von Robert P. (robertoo)


Lesenswert?

Habe mich mal gespielt.. (mit Thonny)
@Stephan S
Deine Beispiele sind super!

Habe mal das probiert: (Lauflicht)

import machine, neopixel
pin = machine.Pin(2, machine.Pin.OUT)    # an Pin 2 ist WS2812 
angeschlossen
np = neopixel.NeoPixel(pin, 251)         # maximale Leds WS2812

for i in range(250):
    for i1 in range(250):                 #alle Leds vorher auf dunkel
        np[i1] = (0,0,0)
    np[i] = (255,0,0)
    np.write()

for i in range(250,0,-1):
    for i1 in range(250):                 #alle Leds vorher auf dunkel
        np[i1] = (0,0,0)
    np[i] = (255,0,0)
    np.write()

So in etwa hatte ich es in C
Da ist C schon ca. 10 mal schneller..

von Norbert (der_norbert)


Lesenswert?

Robert P. schrieb:
> Da ist C schon ca. 10 mal schneller..

Du allokierst ja auch wie ein Berserker zig zehntausende von Tupels. Da 
kommt dann flugs die Garbage Collection ins Spiel.
Daher meine Abneigung bezgl. der NeoPixel Implementation.
Zudem schreibst du zehntausende von unnötigen, redundanten 
Informationen.

von Ron-Hardy G. (ron-hardy)


Lesenswert?

Robert P. schrieb:
> Kann man eigetlich den programierten Code in einem Pico auch schützen ?

ich denke schon, via secure boot/encrypted boot:
https://github.com/raspberrypi/rp2350_hacking_challenge

von Robert P. (robertoo)


Lesenswert?

@Norbert
>Du allokierst ja auch wie ein Berserker zig zehntausende von Tupels. Da
kommt dann flugs die Garbage Collection ins Spiel.

Drei Fremdwörter in einem Satz, die ich noch nicht kannte?!
Ich sehe schon, ihr spielt ihn einer ganz anderen Liga..

von Robert P. (robertoo)


Lesenswert?

habe jetzt den Turbo hin bekommen ;-) freu..
1
import machine, neopixel
2
pin = machine.Pin(2, machine.Pin.OUT)    # an Pin 2 ist WS2812 angeschlossen
3
np = neopixel.NeoPixel(pin, 251)         # maximale Leds WS2812
4
5
for i in range(250):                     #alle Leds vorher auf dunkel
6
    np[i] = (0,0,0) 
7
8
for i in range(250):
9
    if (i > 0):
10
        np[i-1] = (0,0,0)
11
    np[i] = (255,0,0)  
12
    np.write()
13
     
14
for i in range(250,0,-1):
15
    if (i< 250):
16
        np[i+1] = (0,0,0)
17
    np[i] = (255,0,0)
18
    np.write()

: Bearbeitet durch Moderator
von Stephan S. (uxdx)


Lesenswert?

Robert P. schrieb:
> for i in range(250):
>     for i1 in range(250):                 #alle Leds vorher auf dunkel
> Da ist C schon ca. 10 mal schneller..

Kein Wunder, das sind 250 x 250 = 62500 Durchläufe

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.