Xmas Tree Led - Arbol de navidad a leds



Por los motivos obvios de la época navideña les propongo un simple árbol de navidad con leds y que a su vez es de bajo costo.

Tal vez la palabra simple sea un tanto camuflada ya que posee un microcontrolador para lograr los efectos, pero hoy en día no hay mucho problema con ellos, aunque si no tienen idea de cómo programar tal vez puedan rediseñar el circuito por ejemplo para implementar un 4017 y un 555 para el encendido de los leds, o bien transistores.

La idea del proyecto también es impulsar a realizar algún proyecto tradicional como lo suelen hacer en otras partes del globo.

Volviendo al proyecto, es un secuenciador de luces con un PIC16F628A (se elige este por el bajo costo y por la cantidad de pines suficiente para este tamaño de arbolito), se pueden usar MCU mas chicos por ejemplo cualquiera de la línea 12F pero hay que multiplexar los leds creando una matriz para aprovechar sus 6 pines de datos.

Podríamos decir que lo más divertido de esto es diseñar el PCB ya que sea la cara visible del árbol y luego programarle los efectos, si bien en este proyecto yo hice más de 10 efectos diferentes, solo mostrare 3 para que no sea muy extenso el programa de ejemplo.
Como se puede ver en el PCB pueden agregarle mensajes y demas.

El circuito:


El PCB:

El programa:


#include <16F628A.h>
#FUSES NOWDT
#FUSES INTRC_IO
#FUSES NOPUT
#FUSES NOPROTECT
#FUSES NOBROWNOUT
#FUSES NOMCLR
#FUSES NOLVP
#FUSES NOCPD
#use delay(int=4000000)
void main(){
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   int i;
   while(true){
      i=0;
      while(i<10){
         output_b(0b01010101);
         output_a(0b00000101);
         delay_ms(400);
         output_b(0b10101010);
         output_a(0b00001010);
         delay_ms(400);
         i++;
      }  
      i=0;
      while(i<10){
         output_b(0b00110011);
         output_a(0b00000011);
         delay_ms(200);
         output_b(0b11001100);
         output_a(0b00001100);
         delay_ms(200);
         i++;
      }     
      i=0;
      while(i<2){
         output_b(0b11111111);
         output_a(0b00001111);
         delay_ms(200);
         output_b(0b00000000);
         output_a(0b00000000);
         delay_ms(200);
         i++;
      }  
      i=0;
      while(i<20){
         output_b(0b00010000);
         output_a(0b00000000);
         delay_ms(10);
         output_b(0b00000000);
         output_a(0b00001000);
         delay_ms(10);
         output_b(0b01000000);
         output_a(0b00000000);
         delay_ms(10);
         output_b(0b00000100);
         output_a(0b00000000);
         delay_ms(10);
         output_b(0b00000000);
         output_a(0b00000010);
         delay_ms(10);
         output_b(0b00001000);
         output_a(0b00000000);
         delay_ms(10);
         output_b(0b00100000);
         output_a(0b00000000);
         delay_ms(10);     
         output_b(0b00000001);
         output_a(0b00000000);
         delay_ms(10);    
         output_b(0b00000000);
         output_a(0b00000001);
         delay_ms(10);    
         output_b(0b00000010);
         output_a(0b00000000);
         delay_ms(10);
         output_b(0b00000000);
         output_a(0b00001000);
         delay_ms(10); 
         output_b(0b10000000);
         output_a(0b00000000);
         i++;
      }
   }
}

Registro de Desplazamiento 74164 con CCS


En esta nota les mostrare la forma sencilla de utilizar los registros de desplazamiento 74164 con un microcontrolador PIC compilado con CCS.

La idea de este dispositivo es ingresar los bit de forma serial junto a un clock, de esta forma los bit ingresados serie se mostraran en la salida de cada flipflop de forma paralela.

Para comprender aun más esto podemos visualizar el diagrama lógico del integrado.


Como podemos ver es simplemente un array de flipflop tipo D, donde el dato ingresado va pasando secuencialmente de un FF al otro mediante un pulso de reloj por ciclo, es decir ingresamos el primer bit, enviamos un pulso de clock y ese bit pasa de un FF al otro, dejando libre el primero para ingresar el segundo bit, así sucesivamente hasta que se completen los 8bit a mostrar.

Ahora les mostrare dos posibles aplicaciones en un circuito electrónico con Displays de 7 segmentos y con Leds.


Claramente en el circuito con displays use solamente 3 a modo ejemplo pero podría decir que es infinita la cantidad de displays a utilizar ya que los 74164 se pueden concatenar uno tras otro, la limitación se encuentra en el microcontrolador que debe tener memoria suficiente para almacenar la cantidad de datos necesarios a representar.


El circuito con leds es el mismo que el de displays pero en lugar de mostrar los números en displays se muestra cada bit de salida de los registros de desplazamiento a modo de crear por ejemplo un juego de luces.
Nótese que el último bit del 74164 es el que alimenta la entrada del siguiente.


Ahora vamos con el programa, se utiliza un PIC de la línea 12F ya que no necesitamos una gran cantidad de pines ni de procesamiento para realizar esta práctica.

El programa hace lo mencionado al principio, Pone el bit en la entrada de dato del 74164 y luego envía el pulso de clock para que este de desplace al FF siguiente. 

Esta tarea se realiza 8 veces para completar los 8bit de cada 74164, luego a su vez esta tarea se realiza 3 veces ya que son 3 los 74164, y cada vez que se realiza se modifican los bit a mostrar en los registros ya que la idea es mostrar datos diferentes o bien en este ejemplo que se lea 1,2,3 en los displays.

La forma de manejar estos 3 datos es cargando la palabra de 8bit de cada display en un vector y luego al recorrer este vector se mueve a la variable valor, una vez esto se ingresa al bucle que se encarga de cargar los 8bit en el 74164, la forma de utilización de esta, es aplicando una máscara mediante la función lógica AND y comparando contra un vector que posee los bit que queremos mostrar de forma ponderada (2,4,8,...,128).

#include <12F675.h>
#FUSES NOWDT
#FUSES INTRC_IO
#FUSES NOCPD
#FUSES NOPROTECT
#FUSES NOMCLR
#FUSES NOPUT
#FUSES NOBROWNOUT
#use delay(int=4000000)
#define DATO PIN_A1
#define CLK  PIN_A0
void main(){
   int i,j;      
   byte valor;
//Variables para mascara  
   byte const bitMask[8]={1,2,4,8,16,32,64,128}; 
//Datos a mostrar en cada 74164    
   byte const ByteDatosSalida[3]={0b11110010,
                                  0b11011010,   
                                  0b01100000};
   while(true){

//Ciclo de recorrido de los tres 74164
      while(i<3){ 
//Intercambio de variables
         valor=ByteDatosSalida[i];  
//Rrecorrido de cada bit del 74164
         for(j=0;j<8;j++){ 
//Clock a nivel bajo 
            output_low(CLK);

//Salida de dato para 74164 con aplicación de mascara "&"
            output_bit(DATO,valor&bitMask[j]); 

//Demora de carga de datos
            delay_ms(30);  
//Clock a nivel alto
            output_high(CLK); 
//Incremento del contador del while
         }i++;  
      }
   }
}