-
Angesteuert wird bei mir mit einen Microchip PIC12F1840
Der PIC benötigt nur 3 Anschlüsse
PIN 1 = VCC
PIN 2 = Datenausgang ==> zu DIN der RGB Led/Kette
PIN 8 = MASSE
Das wars schon an Hardware.
Testleds waren:
SK6812 Side Led 4020 Eckstein Komponete Art.Nr.: LED0006-10
SK6812 Mini 3535 led-stübchen Art.Nr.: SK6812_144strip_x50cm
WS2812 2020 led-stübchen Art.Nr.: WS2812_2020_x10
WS2812 5050 RGB Stripe 5050 irgendwo mal bei ebay bestellt...
Segor LED8 RGB/WS2812B runde LED, wobei hier rot und grün vertauscht ist.
!! Bei Segor gibt es ein ein RGB-Stripe IP67 geschützt, die haben ein Problem:
Der Power On Reset funktioniert nicht, beim Einschalten gehen alle LEDs mit voller Helligkeit an. (2,7 Ampere)
Artikel: PixelLight 1m-144x/IP67w
Hier die "erprobte" Software mit den Grundfunktionen:
Code:
// Beispielcode für den Microchip PIC Controller PIC12F1840
// grundlegende Ansteuerung einer RGB Kette:
// Autor: SIRO 20.08.2019
//
// PIN 1 = VCC
// PIN 2 = Datenausgang ==> zu DIN der RGB Led/Kette
// PIN 8 = MASSE
//
// An Pin2 (Port RA5) vom Controller wird die Datenleitung der RGB Kette angeschlossen
//
// PIC12F1840 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = ON // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock /Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
/* !!!!!!!!!!!!! B O E S E F A L L E */
/* !!!!!!!!!!! LVP muss off sein, sonst kann MCLRE NICHT OFF sein ??????*/
/* Der PIC reagiert dann immer auf den MCLR Pin mit einem RESET */
/* wahelt selbst den richtigen Header aus pic12F1840.h */
/* xc.h includiert htc.h pic.h pic_chip_select.h pic12f1840.h */
#include <xc.h>
// wird für die von Microchip zur Verfügung gestellten delays benötigt
#define _XTAL_FREQ 32000000
/*----------------------------------------------------------------------*/
/* hier habe ich meine eigenen Datentypen definiert:
ein "U" bedeutet unsigned, also ohne Vorzeichen
ein "S" bedeutet signed, also mit Vorzeichen
ein U8 ist ein 8 Bit Wert ohne Vorzeichen Wertebereich 0..255
ein S8 ist ein 8 Bit Wert mit Vorzeichen Wertebereich -127..+128
*/
typedef unsigned char U8; /* 8 Bit ohne Vorzeichen */
typedef signed char S8; /* 8 Bit mit Vorzeichen */
/*----------------------------------------------------------------------*/
/* im INTCON Register gibt es ein globales Interrupt Einschaltbit GIE */
/* wird dieses Bit auf High (1) gesetzt, sind Interrupts erlaubt */
/* wird dieses Bit auf Low (0) gesetzt, sind ALLE Interrupt gesperrt */
#define ENABLE (GIE=1) /* global interrupt enable */
#define DISABLE (GIE=0) /* global interrupt disable */
/*----------------------------------------------------------------------*/
// so viele LEDs sollen in der Kette angesteuert werden
#define LED_COUNT 16
/* Jede LED hat 3 Bytes, also 24 Bits fuer die Daten */
typedef struct // __pack ? weil wir keinen Speicher verschwenden wollen
{
U8 green; /* 8 Bit fuer die Helligkeit */
U8 red; /* 8 Bit fuer die Helligkeit */
U8 blue; /* 8 Bit fuer die Helligkeit */
} TLed; /* Type Bezeichner ist TLed */
TLed LedArray[LED_COUNT]; // Das komplette LED Array (Datenstrom)
/*----------------------------------------------------------------------------*/
// schiebt die gesamte Ledkette aus
// Das Timing wurde mit NOPs angepasst
void LedShiftOut(void)
{ U8* leds = (U8*)LedArray;
U8 count = LED_COUNT;
U8 one_byte;
S8 bit_count;
// damit keine Multiplikation verwendet wird:
count = (count << 1) + count; // 3 Bytes pro Led RGB
DISABLE; // alle Interrupts sperren
while (count) {
CLRWDT(); // den Watchdog bedienen, falls erforderlich
one_byte = *leds++; // aktuelles Datenbyte laden
// 8 Bits durchlaufen:
for (bit_count = 0; bit_count < 8; bit_count++) {
if (one_byte & 0x80) // wenn das oberste Bit 7 gesetzt ist dann
{
LATA5 = 1; // lange High Phase einleiten
NOP(); // Signal verlängern
NOP();
NOP();
LATA5 = 0; // High Phase beenden
} else // Kurze High Phase weil das Datenbit Low ist
{
LATA5 = 1; // kurze High Phase einleiten
NOP(); // Signal verlängern
LATA5 = 0; // High Phase beenden
}
one_byte <<= 1; // Das Datenbyte 1 mal links verschieben
}
count--; // Anzahl auszugebener Datenbytes -1
}
ENABLE; // Interrupt wieder einschaalten
// Das Ende des Datenstroms wird mit einem "längerem" Low signalisiert
// Die Länge ist unterschiedlich bei verschiedenen LEDs. Siehe Datenblatt
__delay_us(280); // Das Ende der Datenübertragung erreicht wenn die Leitung länger als xxx Low bleibt.
}
/*----------------------------------------------------------------------------*/
// fuellt die gesamte Ledkette mit den übergebenen Werten
void FillLeds(U8 r,U8 g,U8 b)
{ U8 i;
for (i=0; i < LED_COUNT; i++)
{
LedArray[i].red = r;
LedArray[i].green = g;
LedArray[i].blue = b;
}
LedShiftOut();
}
/*----------------------------------------------------------------------------*/
void init_system(void)
{
/* internal oszillator block 32 MHz / 4 stage pipeline = 8 MHz ==> 125ns Instruction cycle */
SCS0 = 0; /* OSCON register */
SCS1 = 0;
SPLLEN = 1; /* is ignored if config enables the PLL */
/* MF 500 KHz default on reset */
/* set to 8MHz value ==> 32Mhz clock with PLL */
IRCF0 = 0; /* OSCON register */
IRCF1 = 1;
IRCF2 = 1;
IRCF3 = 1;
/* !!!! alle ports stehen auf ADU input nach einem reset */
/* wir stellen sie um auf normale input/output funktion */
ANSELA = 0; /* 0 ==> normal Digital IO */
/* Pin Direction */
TRISA5 = 0; /* Datenausgang fuer die RGB LED 0=output */
}
/*---------------------------------------------------------------*/
// wird nicht unbedingt benötigt
// alle LEDs ausschalten
void LedInit(void)
{ U8 i;
for (i = 0; i < LED_COUNT; i++)
{
LedArray[i].green = 0x00;
LedArray[i].red = 0x00;
LedArray[i].blue = 0x00;
}
}
/*----------------------------------------------------------------------------*/
void main(void)
{
init_system();
while (1)
{
// die gesamte LED Kette mit einer Farbe füllen
FillLeds(0x00,0x00,0xFF);
__delay_ms(1000);
FillLeds(0x00,0xFF,0x00);
__delay_ms(1000);
FillLeds(0xFF,0x00,0x00);
__delay_ms(1000);
FillLeds(0x00,0xFF,0xFF);
__delay_ms(1000);
FillLeds(0xFF,0xFF,0x00);
__delay_ms(1000);
FillLeds(0xFF,0x00,0xFF);
__delay_ms(1000);
FillLeds(0xFF,0xFF,0xFF);
__delay_ms(1000);
// so kann man auf jede einzelne LED und der entsprechenden Farbe zugreifen:
// wir stellen hier die RGB Werte für erste LED in der Kette ein:
// Zählung der LEDs von 0..x
LedArray[0].red = 127; // halbe Helligkeit für rot
LedArray[0].green = 64; // viertel Helligkeit fuer grün
LedArray[0].blue = 0xFF; // volle Helligkeit für blau
LedShiftOut(); // es werden immer ALLE LED Daten ausgeschoben
__delay_ms(5000); // warte 5 Sekunden
}
}
Die Software lief mit allen Optimierungsstufen 0,1,2 und 3 des Compilers: XC8 V2.05
Siro
-
Danke Dir!
Ich habe mich über die 3V und weniger gewundert. Ich habe mal versucht, 2.7 oder 3V-LEDs zu bekommen, das ist irgendwie nicht so einfach. Ich habe da noch keine Alternative, kann bisher LEDs nur mit mehr als 3V zu voller Leuchtkraft bewegen.
Ich habe noch mal ins Datenblatt (WS2812-2020_V1.1_EN.pdf) geschaut. Dort steht Versorgungsspannung >3.7V. Ich dachte mal an eine Versorgung mit 3 bis 3.3V. Muss ich mal schauen....
MfG
-
Zwischen 3 und 5 Volt kann ich keine Helligkeitsunterschiede erkennen, zumindest nicht bei dieser kleinen LED.
Sind ja auch intern "Konstantströme"
Das Datenblatt sagt >3,7V das ist richtig. Funktionieren tuts aber auch noch bei 2,7 bei mir. Da kann man sich natürlich nicht unbedingt drauf verlassen,
aber da sie auch bei 2,6 Volt noch funktioniert sehe ich da eher kein Problem.
Bei der Side Led erkennt man aber schon bei Blau einen erheblichen Helligkeitsunterschied zwischen 3 und 4 Volt.
Bei den WS2812B 5050 LEDs auch bei blau.
Also sagen wir mal:
Funktional aber nicht Optimal bei kleineren Spannungen ;)