NeoPixeln mit Bascom         

 von Dirk Beilker                 

 Elektronik-Labor   Projekte   AVR 




Endlich ist es mir gelungen mit einer alten Bascom-Version (ohne die rainbow.lib) NeoPixel-Strings anzusteuern.

Wie geht das ohne Timer-, SPI-, oder PWM-Tricksereien und (fast) ohne Assembler-Code?

'*******************************************************************************
'Die Timing-Angaben aus dem NeoPixel WS2812 Datenblatt lassen sich mit viel
'Fantasie und einigen Tests zugunsten toleranter Timing-Anforderungen verbiegen:
'https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/

'Simplified Timing Constrains for NeoPixel strings (WS2812 Driver)
'Symbol Level Parameter Min Typ Max Unit
'T_0H Hi 0-Code 200 350 500 ns
'T_1H Hi 1-Code 550 700 5500 ns
'T_IBB Lo Inter-Bit-Break 450 600 5000 ns
'T_RST Lo RESET 6000 ns

'Dies ermöglicht eine Ansteuerung mit Bascom, falls die Bascom Rainbow.lib
'nicht vorhanden ist (z.B. Bascom Demo-Version). Das Programm benötigt ca. 2K
'und sollte z.B. auch auf einem ATtiny85 mit 16 MHz laufen ($regfile anpassen,
'Anzahl der LEDs (const N_LED) anpassen) Bei anderen Quarzen u.U. Impulslängen
'mit Oszi verifizieren und NOPs anpassen(s.u.)!
'******************************************************************************
Ich könnte mir sehr gut vorstellen, dass sich mein 2k Programm mit der Bascom-Demo-Version (evtl. Online?) compilieren lässt
und auf dem ATtiny85 läuft.

Hier der vollständige Bascom Quelltext für einen  Arduino Noano (siehe auch Tiny13: RGB-Led WS2812 und Bascom):


'*******************************************************************************
'* ArdunioNano ATmega328 mit NeoPixel-LED-Array
'*******************************************************************************

'Report : 170915 ATmega328 Neopixel
'Date : 09-14-2017
'Time : 13:43:09

'Compiler : BASCOM-AVR LIBRARY V 2.0.7.6
'Processor : M328P
'SRAM : 800 hex
'EEPROM : 400 hex
'ROMSIZE : 8000 hex

'ROMIMAGE : 822 hex
'ROMIMAGE : 2082 dec
'XTAL : 16000000 Hz

'-------------------------------------------------------------------------------
'* ARDUINO nano:
'* PinC.0 = GPIO ADC0 A0 -
'* PinC.1 = GPIO ADC1 A1 -
'* PinC.2 = GPIO ADC2 A2 -
'* PinC.3 = GPIO ADC3 A3 -
'* PinC.4 = GPIO ADC4 A4 -
'* PinC.5 = GPIO ADC5 A5 -
'* ADC6 A6 -
'* ADC7 A7 -
'* PinC.6 = RESET RESET Taster auf Arduinoboard
'* AREF Referenzspannung für ADC
'* PinD.0 = GPIO RXD D0 USB
'* PinD.1 = GPIO TXD D1 USB
'* PinD.2 = GPIO INT0 D2 NEOPIXEL: Data_in Verdrahten!
'* PinD.3 = GPIO INT1, OC2B D3 -
'* PinD.4 = GPIO D4 -
'* PinD.5 = GPIO OC0B D5 -
'* PinD.6 = GPIO OC0A D6 -
'* PinD.7 = GPIO D7 -
'* PinB.0 = GPIO D8 -
'* PinB.1 = GPIO OC1A D9 -
'* PinB.2 = GPIO OC1B D10 -
'* PinB.3 = GPIO MOSI OC2A D11 Flash-Stecker
'* PinB.4 = GPIO MISO D12 Flash-Stecker
'* PinB.5 = GPIO SCK D13 Flash-Stecker und Kontroll-LED
'* PinB.6 = GPIO XTAL1 Crystal 16M Hz
'* PinB.7 = GPIO XTAL2 Crystal 16M Hz
'* 3V3 3V3
'* 5V0 NEOPIXEL: 5V Verdrahten!
'* GND NEOPIXEL: GND Verdrahten!
'* GND GND
'-------------------------------------------------------------------------------
'*******************************************************************************
'Die Timing-Angaben aus dem NeoPixel WS2812 Datenblatt lassen sich mit viel
'Fantasie und einigen Tests zugunsten toleranter Timing-Anforderungen verbiegen:
'https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/

'Simplified Timing Constrains for NeoPixel strings (WS2812 Driver)
'Symbol Level Parameter Min Typ Max Unit
'T_0H Hi 0-Code 200 350 500 ns
'T_1H Hi 1-Code 550 700 5500 ns
'T_IBB Lo Inter-Bit-Break 450 600 5000 ns
'T_RST Lo RESET 6000 ns

'Dies ermöglicht eine Ansteuerung mit Bascom, falls die Bascom Rainbow.lib
'nicht vorhanden ist (z.B. Bascom Demo-Version). Das Programm benötigt ca. 2K
'und sollte z.B. auch auf einem ATtiny85 mit 16 MHz laufen ($regfile anpassen,
'Anzahl der LEDs (const N_LED) anpassen) Bei anderen Quarzen u.U. Impulslängen
'mit Oszi verifizieren und NOPs anpassen(s.u.)!
'*******************************************************************************

'----------------------------------------------------------------------Compiler:
$regfile = "m328pdef.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 32
$framesize = 32

'-------------------------------------------------------------Dimensionierungen:
'LED-Anzahl
const N_LED = 23 'Anzahl der LEDs im Array (anpassen)
dim n as Byte 'Zähler

'Farben
dim g(N_LED) as byte 'Grün-Anteil
dim r(N_LED) as byte 'Rot-Anteil
dim b(N_LED) as byte 'Blau-Anteil

'-----------------------------------------------------------------Konfiguration:
Config PinB.2 = Output 'NEOPIXEL: Data_in

'------------------------------------------------------LED-Array RESET erzeugen:
reset portB.2 'T_RST = Lo = RESET = 10000 ns
waitus 10

'--------------------------------------------------------------------Startwerte:
'Startwerte der Farben sind u.U. entscheidend für den Effekt (beliebig änderbar)
for n = 1 to N_LED
g(n) = 2*n
b(n) = 255 - g(n)
r(n) = 3 * g(n)
next n

'-----------------------------------------------------------------Hauptschleife:
do

'############################################################################
'Hier ist der richtige Spielplatz, um mit irgendwelchen Algorithmen die
'Farbänderungen der LEDs und die Geschwindigkeit zu verändern:

waitms 30 'Geschwindigkeit verändern

for n = 1 to N_LED 'Farben aller LEDs verändern
g(n) = g(n)+ 1
r(n) = r(n)+ 3
b(n) = b(n)+ 5
next n

'############################################################################

'---------------------------------------------------LED-Array RESET erzeugen:
reset portB.2 'T_RST = Lo = RESET = 10000 ns
waitus 10
'-----------------------Das ganze LED-Array mit den neuen Farben beschreiben:
For n = 1 to N_LED
'Pro LED Grün-, Rot- und Blau-Byte in 24 Bit Datenstrom zerlegen und ausgeben:
'Oh mein Gott! Was ist das denn für ein unübersichtlicher Code? => s.u.
if g(n).7 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if g(n).6 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if g(n).5 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if g(n).4 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if g(n).3 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if g(n).2 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if g(n).1 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if g(n).0 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if

if r(n).7 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if r(n).6 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if r(n).5 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if r(n).4 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if r(n).3 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if r(n).2 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if r(n).1 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if r(n).0 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if

if b(n).7 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if b(n).6 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if b(n).5 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if b(n).4 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if b(n).3 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if b(n).2 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if b(n).1 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if
if b(n).0 = 0 then:set portB.2:nop:nop:nop:NOP:reset portB.2
else:set portB.2:nop:nop:nop:nop:nop:nop:NOP:NOP:NOP:reset portB.2:end if

next n
'----------------------------------------------------------------------------
Loop
End

'-------------------------------------------------------------------------------
'Code-Aufschlüsselung (Auszug)
'
' if g(n).7 = 0 then Wenn Bit 7 vom Grün-Anteil der n-ten LED nicht gesetzt:
' set PORTB.2 Kurzen Hi-Impuls ausgeben: T_0H = 0-Code = ca. 350 ns
' NOP:NOP:NOP:NOP (u.U. Impulslänge mit Oszi verifizieren, anpassen)
' reset PORTB.2
' else Wenn Bit 7 vom Grün-Anteil der n-ten LED gesetzt:
' set PORTB.2 Langen Hi-Impuls ausgeben: T_1H = 1-Code = ca. 700 ns
' NOP:NOP:NOP:NOP (u.U. Impulslänge mit Oszi verifizieren, anpassen)
' NOP:NOP:NOP:NOP:NOP
' reset PORTB.2
' end if End If und If-Abfrage Bit 6 vom Grün-Anteil
' if g(n).6 = 0 then dauern: T_IBB = Inter-Bit-Break = Lo = ca. 1100 ns
' u.s.w....
'
' Es wird davon abgeraten die 24 sehr ähnlichen If-Abfragen in eine
' For-Next-Schleife zu packen. Das Timing wird dadurch gestört. Einzelne Bits
' gehen verloren.
'-------------------------------------------------------------------------------





Elektronik-Labor   Projekte   AVR