Autor Tema: Libreria CCS para controlar LEDs WS2811/WS2812  (Leído 50263 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Libreria CCS para controlar LEDs WS2811/WS2812
« en: 14 de Abril de 2014, 21:29:51 »
Hola!
Os presento al WS2812, un LED RGB con driver integrado. Y al WS2811 un driver para LEDs RGB.
Datasheet: http://www.mikrocontroller.net/attachment/180459/WS2812B_preliminary.pdf
He tenido el placer de probar una tira de LEDs y jugar un poco usando Arduino. Realmente sencillo, pero no puedo evitar quererlo tambien para PICs, por lo que basandome en una libreria de Arduino desarrollada por Adafruit he decidido portarla a CCS.
Libreria de Adafruit: https://learn.adafruit.com/adafruit-neopixel-uberguide

Me referire siempre como "LED" que es lo que utilizare para pruebas, pero en realidad son lo mismo, ya que el WS2812 es un encapsulado de LED 5050 con el chip WS2811 integrado dentro del propio LED. Y el WS2811 es solo el IC, pero sin el LED.

Los LEDs se controlan con una señal de pulsos y no necesita señal de reloj.
Cada LED tiene un pin de entrada de datos, y otro de salida de datos. Los leds se conectan en cascada, es decir, la salida de uno con la entrada del siguiente. El primer LED utiliza el primer dato de la trama de datos, lo quita de la trama y reenvia los restantes, el siguiente led hace lo mismo, pilla el primer dato, lo quita y reenvia el resto. Asi no hace falta "direccionar" cada led, ya que es el propio led el que toma el dato que le corresponde.
Un unico pin del PIC puede controlar unos 1000 LEDs a 30Hz.

La forma de enviar los datos es la siguiente:
-Cada LED utiliza 3 bytes, cada byte nos dara 255 niveles de brillo para cada color, que combinados nos ofrecen colores de 24bits, es decir casi 17 millones de colores diferentes.
-Cada byte tiene 8 bits, por supuesto.
-Cada bit se envia como una combinacion de nivel alto + nivel bajo del pin que en total dura 1.25uS:
 * CERO = 0.4uS High + 0.85uS Low
 * UNO = 0.8uS High + 0.45uS Low
-El tiempo para enviar cada byte es de (1.25uS * 8) 10uS
-El tiempo para enviar el valor RGB completo por cada led es (10uS * 3) 30uS
-Entre bit y bit, o entre byte y byte NO HAY DEMORA. Luego de enviar el valor del primero se envia inmediatamente el siguiente.
-Cuando se ha enviado los datos de todos los LEDs hay que hacer una pausa de al menos 50uS para volver a enviar.

Cada LED es capaz de mantener el color que se le asigne, por lo que no hace falta estar constantemente enviando datos.

Dado los tiempos tan apretados la velocidad minima para controlar estos leds es un PIC a 32Mhz e instrucciones optimizadas y medidas en assembler. Gracias a la ayuda de muchos compañeros en el foro de assembler he podido terminar una libreria basica para controlar estos leds.

la libreria es esta: (ANTIGUO, descargar codigo para ultima version)
Código: C
  1. // ---- COMPROBACIONES DE COMPATIBILIDAD ----
  2. #IF getenv("VERSION")<5.019
  3.         //test realizado con compilador CCS v5.019
  4.         //para versiones anteriores comprobar que el codigo
  5.         //generado se adecua a los tiempos requeridos
  6.    #ERROR Compilador antiguo
  7. #ENDIF
  8.  
  9. #IF getenv("CLOCK") != 32000000
  10.         //necesitamos que el PIC corra a 32MHZ al menos
  11.         #ERROR Velocidad del PIC muy baja
  12. #ENDIF
  13.  
  14. #IFNDEF NUM_LEDS
  15.         #ERROR "NUM_LEDS" no definido
  16. #ELSE
  17.         #IF NUM_LEDS > 85
  18.                 //solo podemos usar un maximo de 85 leds.
  19.                 //Cada led usa 3 bytes, y nuestro contador de envio es un int
  20.                 #ERROR "NUM_LEDS" tiene que ser menor a 85
  21.         #ELIF NUM_LEDS*3 > getenv("RAM")
  22.                 #ERROR Tu PIC no tiene suficiente RAM para tantos LEDs
  23.         #ENDIF
  24. #ENDIF
  25. // ------------------------------------------
  26.  
  27. #include <stdlibm.h>
  28.  
  29. #byte INDF0 = getenv("SFR:INDF0")
  30. #byte FSR0L = getenv("SFR:FSR0L")
  31. #byte FSR0H = getenv("SFR:FSR0H")
  32.  
  33. #bit GIE = getenv("BIT:GIE")
  34.  
  35. int *pixels;            //puntero al la primera direccion donde se guardan los valores
  36. int brightness = 0;     //permite ajustar el brillo sin modificar el color
  37. int numLEDs = 0;        //cantidad de leds en la tira
  38. int numBytes = 0;       //numero de bytes usados
  39.  
  40. void ConfigPixels(int n){
  41. //n = numero de leds en la tira
  42.        
  43.         numLeds = n;                    //establece la cantidad de leds a usar
  44.         numBytes = n * 3;               //cantidad de bytes necesarios para manejar a todos los leds
  45.        
  46.         pixels = malloc(numBytes);      //crea espacio en memoria para los leds que vamos a usar
  47.        
  48.         if(pixels){
  49.                 memset(pixels, 0, numBytes);
  50.         }
  51. }
  52.  
  53. int NumPixels(void){
  54.         return numLeds;
  55. }
  56.  
  57. void SetPixelColor(int n, int r, int g, int b){
  58. //Set pixel color from separate R,G,B components:
  59.         if(n < numLEDs) {
  60.                 if(brightness) { // See notes in setBrightness()
  61.                         r = (r * brightness) >> 8;
  62.                         g = (g * brightness) >> 8;
  63.                         b = (b * brightness) >> 8;
  64.                 }
  65.                
  66.                 int * p = &pixels[n * 3];
  67.                
  68.                 *p++ = r;
  69.                 *p++ = g;
  70.                 *p = b;
  71.         }
  72. }
  73.  
  74. void SetPixelColor(int n, int32 c){
  75. //Set pixel color from 'packed' 32-bit RGB color:
  76.         if(n < numLEDs) {
  77.                 int r = (int)(c >> 16);
  78.                 int g = (int)(c >>  8);
  79.                 int b = (int)c;
  80.                
  81.                 if(brightness) { // See notes in setBrightness()
  82.                         r = (r * brightness) >> 8;
  83.                         g = (g * brightness) >> 8;
  84.                         b = (b * brightness) >> 8;
  85.                 }
  86.                
  87.                 int * p = &pixels[n * 3];
  88.                
  89.                 *p++ = r;
  90.                 *p++ = g;
  91.                 *p = b;
  92.         }
  93. }
  94.  
  95. int32 Color32(int r, int g, int b){
  96. //Convierte los colores separados R,G,B en un paquete de 32 bits con el color
  97.         return ((int32)r << 16) | ((int32)g <<  8) | b;
  98. }
  99.  
  100. int32 GetPixelColor(int n){
  101. //devuelve el color de un pixel que hayamos "coloreado" antes
  102. //en formato de 32bits y en order RGB
  103.         if(n < numLEDs) {
  104.                 long ofs = n * 3;
  105.                 return (int32)((pixels[ofs] << 16) | (pixels[ofs + 1] <<  8) | pixels[ofs + 2]);
  106.         }
  107.  
  108.   return 0; // Pixel # is out of bounds
  109. }
  110.  
  111. void SetBrightness(int b) {
  112. // Adjust output brightness; 0=darkest (off), 255=brightest.  This does
  113. // NOT immediately affect what's currently displayed on the LEDs.  The
  114. // next call to show() will refresh the LEDs at this level.  However,
  115. // this process is potentially "lossy," especially when increasing
  116. // brightness.  The tight timing in the WS2811/WS2812 code means there
  117. // aren't enough free cycles to perform this scaling on the fly as data
  118. // is issued.  So we make a pass through the existing color data in RAM
  119. // and scale it (subsequent graphics commands also work at this
  120. // brightness level).  If there's a significant step up in brightness,
  121. // the limited number of steps (quantization) in the old data will be
  122. // quite visible in the re-scaled version.  For a non-destructive
  123. // change, you'll need to re-render the full strip data.  C'est la vie.
  124.  
  125. // Stored brightness value is different than what's passed.
  126. // This simplifies the actual scaling math later, allowing a fast
  127. // 8x8-bit multiply and taking the MSB.  'brightness' is a uint8_t,
  128. // adding 1 here may (intentionally) roll over...so 0 = max brightness
  129. // (color values are interpreted literally; no scaling), 1 = min
  130. // brightness (off), 255 = just below max brightness.
  131.  
  132.         int newBrightness = b + 1;
  133.        
  134.         if(newBrightness != brightness) { // Compare against prior value
  135.                 // Brightness has changed -- re-scale existing data in RAM
  136.                 int c;
  137.                 int *ptr = pixels;
  138.                 int oldBrightness = brightness - 1; // De-wrap old brightness value
  139.                 long scale;
  140.                
  141.                 if(oldBrightness == 0)
  142.                         scale = 0; // Avoid /0
  143.                 else if
  144.                         (b == 255) scale = 65535 / oldBrightness;
  145.                 else
  146.                         scale = (((long)newBrightness << 8) - 1) / oldBrightness;
  147.                
  148.                 for(int i=0; i<numBytes; i++) {
  149.                         c      = *ptr;
  150.                         *ptr++ = (c * scale) >> 8;
  151.                 }
  152.                
  153.                 brightness = newBrightness;
  154.         }
  155. }
  156.  
  157. void ShowPixels(void){
  158. short GIEval;
  159. int i;          //loop
  160.  
  161.         GIEVal = GIE;   //guardo valor de global interrupt enable
  162.         GIE = 0;                //deshabilito interrupciones
  163.        
  164.         i = numBytes;   //numero de bytes a enviar
  165.  
  166.         //apunto FSR0 al inicio de mis bytes
  167.         FSR0L = pixels;
  168.         FSR0H = pixels >> 8;
  169.  
  170. //10 instrucciones por cada bit: HHxxxxxLLL
  171. //OUT instructions:              ^ ^    ^   (T=0,2,7)
  172.  
  173. SendByte:                                       //Clk   Instr
  174.         //bit7 ---
  175.         DAT = TRUE;                             //0             1
  176.         if(!bit_test(INDF0, 7)) //1             1
  177.                 DAT = FALSE;            //2             1
  178.         delay_cycles(4);                //3-6   4
  179.         DAT = FALSE;                    //7             1
  180.         delay_cycles(2);                //8-9   2
  181.        
  182.         //bit6 ---
  183.         DAT = TRUE;                             //0             1
  184.         if(!bit_test(INDF0, 6)) //1             1
  185.                 DAT = FALSE;            //2             1
  186.         delay_cycles(4);                //3-6   4
  187.         DAT = FALSE;                    //7             1
  188.         delay_cycles(2);                //8-9   2
  189.        
  190.         //bit5 ---
  191.         DAT = TRUE;                             //0             1
  192.         if(!bit_test(INDF0, 5)) //1             1
  193.                 DAT = FALSE;            //2             1
  194.         delay_cycles(4);                //3-6   4
  195.         DAT = FALSE;                    //7             1
  196.         delay_cycles(2);                //8-9   2
  197.        
  198.         //bit4 ---
  199.         DAT = TRUE;                             //0             1
  200.         if(!bit_test(INDF0, 4)) //1             1
  201.                 DAT = FALSE;            //2             1
  202.         delay_cycles(4);                //3-6   4
  203.         DAT = FALSE;                    //7             1
  204.         delay_cycles(2);                //8-9   2
  205.        
  206.         //bit3 ---
  207.         DAT = TRUE;                             //0             1
  208.         if(!bit_test(INDF0, 3)) //1             1
  209.                 DAT = FALSE;            //2             1
  210.         delay_cycles(4);                //3-6   4
  211.         DAT = FALSE;                    //7             1
  212.         delay_cycles(2);                //8-9   2
  213.        
  214.         //bit2 ---
  215.         DAT = TRUE;                             //0             1
  216.         if(!bit_test(INDF0, 2)) //1             1
  217.                 DAT = FALSE;            //2             1
  218.         delay_cycles(4);                //3-6   4
  219.         DAT = FALSE;                    //7             1
  220.         delay_cycles(2);                //8-9   2
  221.        
  222.         //bit1 ---
  223.         DAT = TRUE;                             //0             1
  224.         if(!bit_test(INDF0, 1)) //1             1
  225.                 DAT = FALSE;            //2             1
  226.         delay_cycles(4);                //3-6   4
  227.         DAT = FALSE;                    //7             1
  228.         delay_cycles(2);                //8-9   2
  229.        
  230.         //bit0 ---
  231.         DAT = TRUE;                             //0             1
  232.         if(!bit_test(INDF0, 0)) //1             1
  233.                 DAT = FALSE;            //2             1
  234. #asm
  235.         DECFSZ  i, F                    //3             1       decrementar contador de bytes enviados, si es cero salta 1 -> listo.
  236.         GOTO    Salto                   //4             1       salta 1 instruccion (no me deja usar GOTO $+2 ni BRA 2 ¿?)
  237.         GOTO    Listo                   //5             1       todo enviado. Salir
  238. #endasm
  239. Salto:
  240.         FSR0L++;                                //6             1       incremento puntero
  241.         DAT = FALSE;                    //7             1       PIN = LOW
  242.         goto SendByte;                  //8             2       vuelve al principio
  243.  
  244. Listo: 
  245.         DAT = FALSE;
  246.         delay_cycles(2);
  247.         // fin de transmision
  248.        
  249.         delay_us(50);           //espero 50uS para volver a enviar
  250.         GIE = GIEval;           //restauro valor de GIE
  251. }

Y un codigo de ejemplo es este (Ejemplo.c):
Código: C
  1. //------------------------------------------------------------------------------
  2. //                    TITULO PROYECTO
  3. //
  4. // Descripcion:
  5. //
  6. // PIC: 12F1822
  7. //
  8. //------------------------------------------------------------------------------
  9.  
  10. #include <12F1822.h>
  11. #device adc=8
  12.  
  13. #FUSES NOFCMEN          //NO fail safe clock monitor
  14. #FUSES NOIESO           //NO internal external switchover
  15. #FUSES NOBROWNOUT       //NO brownout reset
  16. #FUSES NOCPD            //NO eeprom protegido de lecturas
  17. #FUSES NOPROTECT        //NO codigo protegido de lecturas
  18. #FUSES NOMCLR           //NO mclr
  19. #FUSES PUT                      //power up timer
  20. #FUSES NOWDT            //NO watch dog timer
  21. #FUSES INTRC_IO         //oscilador interno, pines CLK como I/O
  22. #FUSES CLKOUT
  23.  
  24. #use delay(clock=32000000)
  25. #use fast_io(a)               //se accede al puerto a como memoria
  26.  
  27. //--- Constantes ---
  28. #byte PORTA     = getenv("SFR:PORTA")
  29.  
  30. #define TRIS_A  0b00111011      //define cuales son entradas y cuales salidas
  31. #bit DAT        = PORTA.2
  32.  
  33. #define NUM_LEDS        10
  34. //------------------
  35.  
  36. //--- Variables ---
  37.  
  38. //-----------------
  39.  
  40. //#use rs232(baud=9600, xmit=TX,rcv=RX)
  41.  
  42. #include "LED_Pixels.c"
  43.  
  44. void Rainbow(int wait);
  45. int32 Wheel(int WheelPos);
  46. // ---------------
  47.  
  48. void main(void) {
  49.        
  50.         setup_wdt(WDT_OFF);                                             //configuracion wdt
  51.         setup_timer_0(T0_INTERNAL|RTCC_DIV_1);  //configuracion timer0
  52.         setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //configuracion timer1
  53.         setup_timer_2(T2_DISABLED,255,1);               //configuracion timer2
  54.         setup_dac(DAC_OFF);                                             //configura DAC
  55.         setup_adc(ADC_OFF);                                             //configura ADC
  56.         setup_ccp1(CCP_OFF);                                    //configura CCP
  57.         setup_spi(SPI_DISABLED);
  58.         //setup_uart(FALSE);                                    //configura UART
  59.         setup_comparator(NC_NC);                                //comparador apagado
  60.         setup_vref(VREF_OFF);                                   //no se usa voltaje de referencia
  61.        
  62.         setup_oscillator(OSC_8MHZ|OSC_PLL_ON);  //configura oscilador interno
  63.        
  64.         set_tris_a(TRIS_A);                                     //
  65.         ConfigPixels(NUM_LEDS);
  66.        
  67.         int i = 0;
  68.         int32 ColorTest = 0;
  69.        
  70.         do{
  71.           //Rainbow(50);
  72.  
  73.           for(i = 0; i<NUM_LEDS; i++){
  74.                   ColorTest = Wheel(i * (255 / NUM_LEDS));
  75.                   SetPixelColor(i, ColorTest);
  76.           }
  77.           ShowPixels();
  78.           delay_ms(50);
  79.         }while(true);
  80. }
  81. void Rainbow(int wait){
  82.         long i, j;
  83.  
  84.         for(j=0; j<256; j++){
  85.                 for(i=0; i<numPixels(); i++){
  86.                         SetPixelColor(i, Wheel((i+j) & 255));
  87.                 }
  88.                
  89.                 ShowPixels();
  90.                 delay_ms(wait);
  91.         }
  92. }
  93.  
  94. int32 Wheel(int WheelPos) {
  95. // Input a value 0 to 255 to get a color value.
  96. // The colours are a transition r - g - b - back to r.
  97.  
  98.         if(WheelPos < 85){
  99.                 return Color32(WheelPos * 3, 255 - WheelPos * 3, 0);
  100.         }else if(WheelPos < 170){
  101.         WheelPos -= 85;
  102.                 return Color32(255 - WheelPos * 3, 0, WheelPos * 3);
  103.         }else{
  104.         WheelPos -= 170;
  105.                 return Color32(0, WheelPos * 3, 255 - WheelPos * 3);
  106.         }
  107. }

Basicamente, lo que hay que hacer es cargar cada led con el color que queramos con la funcion SetPixelColor(NumLed, ColorFormato32bits).
Tambien podemos usar la funcion SetPixelColor(NumLed, Rojo, Verde, Azul).
Podemos cargar los colores con un bucle como se hace en el ejemplo.
Una vez cargados los colores hay que usar la funcion ShowPixels() para que se envien los datos. Mientras no se use esta funcion, solo estamos manipulando valores de memoria, pero no enviamos nada.
La libreria tiene mas funciones que copie de la libreria de Adafruit, pero que aun no he probado como SetBrightness(int Valor) que permite ajustar el brillo de todos nuestros leds, sin modificar el color.

El resultado es este:


Aun quedan bastantes cosas por mejorar:
-Si bien parece funcionar correctamente, el mayor problema es la cantidad de LEDs que podemos manejar. Necesitamos 3 bytes de ram por cada led, y el total de bytes necesarios para todos los leds deber estar alojados consecutivamente en nuestra ram para poder acceder a ellos.
Para ello usamos la funcion malloc() que busca un bloque consecutivo de memoria ram del tamaño que necesitamos. Pero la memoria debe estar muy fragmentada, porque no consigo hacer funcionar mas de 10 leds. Eso quiere decir que no hay mas de 30 bytes libres y consecutivos en mi ram.
-En caso de que nuestro PIC tenga suficiente memoria ram, no podremos manejar mas de 85 leds (255 bytes de ram) porque nuestro contador de envio de bytes es de tipo INT y solo podra enviar hasta 256 antes de desbordarse.
-Solo funciona con un oscilador de 32Mhz. Las instrucciones estan contadas solo para este velocidad.

Las mejoras que vaya consiguiendo las ire publicando. Si alguien quiere ayudar a completar la libreria se agradece.
Reitero mi agradecimiento a los amigos del subforo de assembler, que sin ellos no habria podido enviar los datos en los tiempos requeridos.

EDITO:
Actualizacion de libreria a v0.2: Mejor manejo de la memoria, posibilidad de enviar datos a 800 o 400Khz, comprobada y bien comentada.
« Última modificación: 21 de Abril de 2014, 05:14:22 por Marttyn »
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado stk500

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4923
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #1 en: 15 de Abril de 2014, 05:08:07 »
Bravo Mago!!  ((:-))
Marttyn te es posible poner un video funcionando?
si no es muchos pedirte.
Saludos

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #2 en: 15 de Abril de 2014, 06:00:14 »
No problem, intentare solucionar lo del malloc() para que se vea con mas leds.
A ver si esta tarde subo algo.
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7918
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #3 en: 15 de Abril de 2014, 08:17:51 »
Excelente trabajo, Martiin !!
Felicitaciones !! ((:-)) ((:-)) ((:-))
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #4 en: 15 de Abril de 2014, 12:05:59 »
Bravo Mago!!  ((:-))
Marttyn te es posible poner un video funcionando?
si no es muchos pedirte.
Saludos

++;
 :mrgreen:

Felicidades Martiin, una muy buena opción para controlar varios leds con un pic de gama media mejorada.


Gracias por el aporte
"Nada es imposible, no si puedes imaginarlo"

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #5 en: 15 de Abril de 2014, 20:24:03 »
Click en la imagen para ver un mini video:


Ya he solucionado el problema de la memoria. Ahora he conseguido controlar hasta 28 leds (84 bytes) con un PIC 12F1822, que solo dispone de 128 bytes de RAM.
Con un 12F1840 consigo controlar unos 72 LEDs (216 bytes) con una RAM de 256 bytes.

Al principio la libreria funcionaba con punteros, y creaba en tiempo de ejecucion el espacio de memoria para los LEDs con "malloc()". Pero al tener la RAM fragmentada nunca encontraba un hueco suficientemente grande.
Ahora pase la libreria para que funcione con arrays. Que realmente es lo mismo que un puntero, pero el espacio de memoria se crea al compilar, por lo que el compilador se preocupa de ordenar la RAM para que quepa nuestro array.
Ademas, me libro de la libreria stdlibm.h necesaria para el malloc(). Dejando mas ROM y RAM libre.

He hecho pruebas con el analizador logico y los tiempos van bien.
Mañana subo la v0.2 de la libreria para que quede a disposicion del que la necesite.

Un abrazo!
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #6 en: 16 de Abril de 2014, 10:12:41 »
creo que lo que mas me gustó de esos leds es que no tienes que direccionar a que led enviar la señal y así controlas todo con solo una linea de transmisión de datos además es muy bonito el efecto que se logra con estos leds.

una pregunta :oops:, en cuanto sale una tira de leds como esa o donde puedo pedir una?
"Nada es imposible, no si puedes imaginarlo"

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #7 en: 16 de Abril de 2014, 12:49:17 »
"Nada es imposible, no si puedes imaginarlo"


Desconectado AKENAFAB

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3227
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #9 en: 17 de Abril de 2014, 03:19:25 »
Te ha quedado muy bien MArttyn  ((:-)) ((:-))  :-/ :-/

Yo uso el ws2801 para LEDs mas grandes y va muy bien. Estan muy prácticos estos chips para encadenar n LEDs.

Saludos!

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #10 en: 18 de Abril de 2014, 06:45:22 »
Estoy de vacas de semana santa, como me vea mi novia escribiendo con el movil me casca!
Las tiras de leds WS2812 cuestan unos 12USD por Aliexpress. Seguramente tambien haya en eBay.
Los leds sueltos no cuestan mas de 0.10 o 0.20USD por lo que resulta muy economico incluirlos en cualquier diseño.
Hay que tener cuidado porque se funden facilmente. Yo ya revente unos 10. Cuando deja de funcionar hay que reemplazar el primer led, o incluso el segundo tambien. La manera mas facil de joder un les en metiendo el analizador logico u osciloscopio a la señal de datos. Lo mejor es analizar los datos directamente del pic, con la tira de leds desconectada.

El lunes subo la libreria mejorada.
Salu2!
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado stk500

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4923
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #11 en: 18 de Abril de 2014, 07:45:47 »
Sigue reventando mago  :D :D
broma aparte!!!!
pero me imagino que lo reventaste por culpa de mas Voltage permitido?
yo hace poco instale en casa de un amigo 500 Led blancos en Serie de grupos y sin resistencia limitadora, calcule´sus voltage claro ante y me hice una fuente Regulable de 50 Voltios 5Amp y hasta ahora va, eso si la fuente se calienta muchos y el consumos no llega a 4,8Amp . estamos pnsando de ponerle ventilador con resistencia termica para que no este el ventilador haciendo ruido todos el ratos.

Saludos y Felices Fiestas.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #12 en: 21 de Abril de 2014, 05:16:58 »
De vuelta por aqui.
Ya tengo la libreria "lista". Bien comentada y explicada para el que la necesite.
De momento SOLO funciona con micros a 32Mhz. Pero puede enviar datos a 800Khz o a 400Khz segun queramos.
En teoria podria funcionar para micros a 16Mhz y a 400Khz, pero hay que escribir el codigo. De ahi para arriba puede funcionar con cualquier micro. Pero hay que adaptar el codigo para ajustarse a los tiempos.

El codigo esta disponible para descargar en el primer post.
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #13 en: 11 de Septiembre de 2014, 12:59:08 »
Complemento el hilo con una librería para controlar estos leds con DMA y SPI

http://hackaday.com/2014/09/10/driving-ws2812b-pixels-with-dma-based-spi/

Desconectado jeremylf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1341
Re: Libreria CCS para controlar LEDs WS2811/WS2812
« Respuesta #14 en: 13 de Septiembre de 2014, 02:54:24 »
Genial! Ya había visto estos LEDs y estoy muy tentando de usarlos. Se agradece =)