PIC18F25K22 & XC8: PWM por software - Controlando tiras de LEDs RGB


En este ejemplo, veremos un pequeño ejemplo para controlar un metro de tira LED RGB (para esta demostración he usado la tira que tengo instalado en mi mesa de trabajo, de cierta forma es un previo para el circuito de control del proyecto "Iluminación de escritorio con LEDs RGB"), para ello vamos a generar un PWM por software haciendo uso de un timer e interrupciones, si buscar información de como funciona el PWM, los timers, etc. te recomiendo leer los enlaces al final, o en su caso buscar en la red, ya que aquí no encontraras mucha teoría.

Circuito:
Para el circuito se ha utilizado un PIC18F25K22, los MOSFETS serán del tipo N y la matricula es IPD600N25N3G (al parecer ya están descontinuados), para controlador dichos MOSFETS utilizare el driver IR4427, el circuito propuesto esta hecho con los materiales que se tenían en casa, así que ustedes pueden utilizar otros que cumplan sus requisitos (lo que muestro aquí es solo una referencia mas de como hacerlo), esteremos alimentando el control a 3.3V y la parte de potencia a 12V, como se va a generar un PWM por software, podemos usar cualquier pin como salidas del MCU, en este caso están conectados en el puerto B.
Código:
Para realizar el código hemos usado una Fpwm = 100Hz, la resolución sera de 8bits, por lo tanto tendremos 256 pasos para un ciclo de trabajo completo, así que necesitamos desbordar el TMR0 a 39 microsegundos, el código queda de la siguiente manera.
/*******************************************************************************
*
* PWM por software - Controlando tiras de LEDs RGB
*
*******************************************************************************
* FileName: main.c
* Processor: PIC18F25K22
* Complier: XC8 v1.42 & MPLAB X IDE v5.00
* Author: Pedro Sánchez (MrChunckuee)
* Blog: http://mrchunckuee.blogspot.com/
* Email: mrchunckuee.psr@gmail.com
* Description: Gererar tres señales de PWM por medio de la interrupcion del
* timer 0, esto para controlar una tira de LEDs RGB
*******************************************************************************
* Rev. Date Comment
* v0.0.0 08/08/2018 - Creación del ejemplo
******************************************************************************/
#include <xc.h>
#include "hw_sw.h"
#include "FUSES_Config.h"
unsigned int Ticks = 0;
unsigned char DuttyPWM[4]; // Red, Green, Blue
unsigned char levelColor;
unsigned int ticksRGB = 0;
unsigned char color = 0;
unsigned char colors[NUMBER_OF_COLORS][3] = {
{255, 0, 0}, //Rojo
{139, 0, 0},
{255, 127, 0}, //Naranja
{255, 255, 0}, //Amarillo
{0, 255, 0}, //Verde
{0, 0, 255},//Azul
{0, 255, 255},//Cyan
{127, 255, 212},
{75, 0, 130},//Morado
{143, 0, 255},
{255, 255, 255}, //Blanco
};
void MCU_Init(void);
void PWM_Init(void);
void PWM_SetDutty(unsigned char Red, unsigned char Green, unsigned char Blue);
void demoRGBColor(void);
void interrupt high_priority ISR(void){
if(INTCONbits.TMR0IF){
if (Ticks == 256) Ticks = 0;
++Ticks;
if (Ticks < DuttyPWM[ticksRed]) redLedOutput = 1;
else redLedOutput = 0;
if (Ticks < DuttyPWM[ticksGreen]) greenLedOutput = 1;
else greenLedOutput = 0;
if (Ticks < DuttyPWM[ticksBlue]) blueLedOutput = 1;
else blueLedOutput = 0;
TMR0H = 0x00;
TMR0L = 0xB2;
INTCONbits.TMR0IF = 0;
}
}
void main(void) {
MCU_Init();
while(1){
demoRGBColor();
}
}
void MCU_Init(void){
//Puertos digitales
ANSELA = 0;
ANSELB = 0;
ANSELC = 0;
//Configura oscilador interno a 16MHz
OSCCONbits.IRCF=0b111; //El ciclo de instruccion es de 0.25 us
//Puertos como salida
TRISB = 0x00;
TRISC = 0x00;
//Limpiamos puertos
PORTB = 0x00;
PORTC = 0x00;
DuttyPWM[ticksRed] = 0;
DuttyPWM[ticksGreen] = 0;
DuttyPWM[ticksBlue] = 0;
PWM_Init();
}
void PWM_Init(void){
//Configuración del TMR0 = 39us
T0CONbits.TMR0ON = 1; //TMR0 On
T0CONbits.T08BIT = 1; //8 bits
T0CONbits.T0CS = 0;
T0CONbits.T0SE = 0;
T0CONbits.PSA = 0;
T0CONbits.T0PS = 0b000; // Prescaler = 2
TMR0H = 0x00;
TMR0L = 0xB2;
INTCONbits.TMR0IF = 0;
INTCONbits.TMR0IE = 1;
INTCON2bits.TMR0IP = 1;
RCONbits.IPEN = 1;
INTCONbits.GIEH = 1;
}
void PWM_SetDutty(unsigned char Red, unsigned char Green, unsigned char Blue){
//Set PWM dutty cycle
DuttyPWM[ticksRed] = Red;
DuttyPWM[ticksGreen] = Green;
DuttyPWM[ticksBlue] = Blue;
}
void demoRGBColor(void){
switch (color){
case 0: // Fade Red
++ticksRGB;
if (ticksRGB == 256) {
color = 1;
ticksRGB = 0;
}
PWM_SetDutty(ticksRGB,0,0);
break;
case 1: //Fade Green
++ticksRGB;
if (ticksRGB == 256) {
color = 2;
ticksRGB = 0;
}
PWM_SetDutty(0,ticksRGB,0);
break;
case 2: //Fade Blue
++ticksRGB;
if (ticksRGB == 256) {
color = 3;
ticksRGB = 0;
}
PWM_SetDutty(0,0,ticksRGB);
break;
case 3: //Show colors
for(levelColor=0; levelColor<NUMBER_OF_COLORS; levelColor++){
PWM_SetDutty(colors[levelColor][0], colors[levelColor][1], colors[levelColor][2]);
__delay_ms(1000);
}
color=0;
break;
default:
color = 0;
ticksRGB = 0;
break;
}
__delay_ms(30);
}
Vídeo:
Aquí un pequeño vídeo del circuito en funcionamiento:



Descargas:
Aquí el enlace directo para DESCARGAR los archivos disponibles, también puedes revisar o descargar la información desde mi repositorio en GitHub, si no sabes como descargarlo puedes checar aquí, bueno por el momento es todo si tienes dudas, comentarios, sugerencias, inquietudes, traumas, etc. dejarlas y tratare de responder lo mas pronto posible.


Donaciones:
Si te gusta el contenido o si los recursos te son de utilidad, comparte el enlace en tus redes sociales o sitios donde creas que puede ser de interés y la otra puedes ayudarme con una donación para seguir realizando publicaciones y mejorar el contenido del sitio. También puedes hacer donaciones en especie, ya sea con componentes, tarjetas de desarrollo o herramientas. Ponte en contacto para platicar, o puedes volverte uno de nuestros sponsors.


Pido una retroalimentación avisando cada que un enlace no sirva o tenga errores al momento de abrirlo, así también si una imagen no se ve o no carga, para corregirlo en el menor tiempo posible.

Bibliografía:

Publicar un comentario

0 Comentarios