TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: glow_ing en 04 de Enero de 2013, 14:48:08
-
Hola amigos, hace poco posteé con algo relacionado a este proyecto, pero que no tiene nada que ver con esta consulta.
Como ya he comentado estoy trabajando en un dimmer de 3 canales controlado por Bluetooth (RS232).
Todo funciona bastante bien, el problema es que cuando ejerzo control sobre el PIC para aumentar/disminuir intensidad los LEDs parpadean mucho, incluso he notado que los canales influyen entre sí.
Las salidas del PWM del pic estan conectadas a 3 MOSFET IRF634, con una Rgate=22ohm, el surtidor a tierra y la tira de LEDS entre vcc(12v) y drenador.
El programa es el siguiente:
/*******************************************************************************
********************************************************************************
Programa para PIC18F4520 en placa de desarroyo SURE DB-DP113 que controla tres
ciclos PWM para ajustar la intensidad de tres LEDs conectados a las entradas
RB1, RB2 y RB3. Ademas muetra en pantalla la intensidad en % y la temperatura
obtenida por el sensor de temperatura LM75 incluido en la propia placa de
desarroyo.
El control de los ciclos PWM se controla mediante comunicacion serie RS-232
pines RC6 y RC7.Estos estan conectados a un modulo bluetooth HC-06, para poder
ser controlado inalambricamente atravez de un smatphone Android.
El sensor de temperatura LM75 se comunica con el PIC mediante comunicacion
I2C atravez de los pines RC3 y RC4.
********************************************************************************
*******************************************************************************/
#include "Dimmer_BT.h"
#Define led1 PIN_B1 //salida PWM1 (LED1)
#Define led2 PIN_B2 //salida PWM2 (LED2)
#Define led3 PIN_B3 //salida PWM3 (LED3)
#define L1ON 49 //dato de control,On/Off LED1. Corresponde al caracter '1' (ASCII=>49)
#define L2ON 50 //dato de control,On/Off LED2. Corresponde al caracter '2' (ASCII=>50)
#define L3ON 51 //dato de control,On/Off LED3. Corresponde al caracter '3' (ASCII=>51)
#define mas1 52 //dato de control,aumenta ciclo LED1. Corresponde al caracter '4' (ASCII=>52)
#define menos1 53 //dato de control,disminuye ciclo LED1. Corresponde al caracter '5' (ASCII=>53)
#define mas2 54 //dato de control,aumenta ciclo LED2. Corresponde al caracter '6' (ASCII=>54)
#define menos2 55 //dato de control,disminuye ciclo LED2. Corresponde al caracter '7' (ASCII=>55)
#define mas3 56 //dato de control,aumenta ciclo LED3. Corresponde al caracter '8' (ASCII=>56)
#define menos3 57 //dato de control,disminuye ciclo LED3. Corresponde al caracter '9' (ASCII=>57)
#include "lcd.c" //Libreria para la pantalla LCD
#include "LM75CIM3.c" //Libreria para el sensor de temperatura LM75
//que se comunica por I2C.
//Declaracion de funciones
void PWM(int ciclo1, int ciclo2, int ciclo3); //Crea tres PWM por sofware utilizando el TMR0
void entrada_de_datos(); //Recoge el dato recibido por comunicacion serie RS-232
void control(int BTin); //Ejerce el control sobre los LEDs y el duty de los PWM, segun el dato recibido.
void escribir_lcd(); //Escribe en pantalla el esado de cada LED y la temperatura
void enviando_estado(); //Envia el estado del sistema por RS232.
int BTin=0, ciclo1=0, ciclo2=0, ciclo3=0, BL1=1, BL2=1, BL3=1;
int ld1,ld2,ld3;
float temp=99.9, t=0;
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||| M A I N |||||||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void main(){
setup_adc_ports(NO_ANALOGS|VSS_VDD); //Desactiva entradas analogicas
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED); //desactiva PSP
setup_spi(SPI_SS_DISABLED); //Desactiva SPI
setup_wdt(WDT_OFF); //Desactiva el watchDog
setup_timer_0(RTCC_DIV_256|RTCC_8_BIT); //Activo TMR0, con divisor 128 y que trabaje solo con 8bits
setup_timer_1(T1_DISABLED); //Desactivo los demas temporizadores
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC); //desactivo el modulo CCP
setup_vref(FALSE); //desactivo tension de referencia
DISABLE_INTERRUPTS(GLOBAL);
escribir_lcd(); //Escribir LCD por primera Vez
while(true){ //bucle infinito
if(kbhit()){ //si recivo algun dato
BTin=GETC();
entrada_de_datos(); //lo guardo en BTin
control(BTin); //y segun sea, ejerzo el control pertinente
}
PWM(ciclo1, ciclo2, ciclo3); //Si no, saco los 3 PWMs por RB1, RB2 y RB3.
}
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||| ENTRADA DE DATOS ||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void entrada_de_datos() {
delay_ms(10);
printf("\f");
printf("OK");
switch(BTin){
case L1ON:
BL1=!BL1;
break;
case L2ON:
BL2=!BL2;
break;
case L3ON:
BL3=!BL3;
break;
case mas1:
if(ciclo1<250)
ciclo1=ciclo1+25;
break;
case menos1:
if(ciclo1>5)
ciclo1=ciclo1-25;
break;
case mas2:
if(ciclo2<250)
ciclo2=ciclo2+25;
break;
case menos2:
if(ciclo2>5)
ciclo2=ciclo2-25;
break;
case mas3:
if(ciclo3<250)
ciclo3=ciclo3+25;
break;
case menos3:
if(ciclo3>5)
ciclo3=ciclo3-25;
break;
}
return;
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||| C O N T R O L |||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void control(BTin) {
if(BL1==1 && BTin==L1ON)
ciclo1=0;
else if(BL1==0 && BTin==L1ON)
ciclo1=255;
if(BL2==1 && BTin==L2ON)
ciclo2=0;
else if(BL2==0 && BTin==L2ON)
ciclo2=255;
if(BL3==1 && BTin==L3ON)
ciclo3=0;
else if(BL3==0 && BTin==L3ON)
ciclo3=255;
if(ciclo1==5) ciclo1=0;
if(ciclo1==255) ciclo1=250;
if(ciclo2==5) ciclo2=0;
if(ciclo2==255) ciclo2=250;
if(ciclo3==5) ciclo3=0;
if(ciclo3==255) ciclo3=250;
escribir_lcd();
return;
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||| P W M |||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void PWM(int ciclo1, int ciclo2, int ciclo3){
if (ciclo1>get_timer0()) output_high(led1);
else output_low(led1);
if (ciclo2>get_timer0()) output_high(led2);
else output_low(led2);
if (ciclo3>get_timer0()) output_high(led3);
else output_low(led3);
return;
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||| ESCRIBIR EN LCD ||||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void escribir_lcd(){
ld1=ciclo1*0.4;
ld2=ciclo2*0.4;
ld3=ciclo3*0.4;
//DESCOMENTAR SOLO SI ESTA CONECTADO EL SENSOR (LM75), SINO SE CUELGA EL PIC.
init_temp(); //Inicializar sensor LM75
t=0.1*read_full_temp(); //Leer temperatura en grados farenheit
temp=(t-32)/1.8; //convertir a grados centigrados
lcd_init();
lcd_gotoxy(1,1);
printf(lcd_putc,"LD1 LD2 LD3 TEMP");
lcd_gotoxy(1,2);
printf(lcd_putc,"%03u %03u %03u %0.2f",ld1,ld2,ld3,temp);
enviando_estado();
return;
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||| ENVIAR ESTADO POR RS232 |||||||||||||||||||||||||||||
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void enviando_estado(){
printf("\f");
printf("LED1 = %03i%% \r",ld1);
printf("LED2 = %03i%% \r",ld2);
printf("LED3 = %03i%% \r",ld3);
printf("TEMP = %0.1fºC \r",temp);
return;
}
Adjunto link del video del dimer en funcionamiento y el rar con el proyecto.
Link Video (http://youtu.be/3MnLcNCcArU)
Ayúdenme Por favor!!
Gracias!!
-
No se bien como funciona la función PWM(), pero juzgando por el video es como que cuando le cambias el duty a cualquiera de los tres ciclos se toma un tiempo para ajustarse, yo revisaría por ahí.
No creo que el problema esté en el hard.
Si tienes parpadeo cuando no cambias el duty quizás es porque usas una frecuencia muy baja, para no notarlo mínimo tiene que ser 35 hz.
-
Hola
Pues, veo un delay de 10mS cada vez que entra un dato por el serial ... eso debe desajustar el periodo del PWM ... prueba manejarlo por interrupcion ;)
Saludos
-
Buenas amigos!
Muchisimas gracias por vuestra ayuda!
No se bien como funciona la función PWM(), pero juzgando por el video es como que cuando le cambias el duty a cualquiera de los tres ciclos se toma un tiempo para ajustarse, yo revisaría por ahí.
No creo que el problema esté en el hard.
Si tienes parpadeo cuando no cambias el duty quizás es porque usas una frecuencia muy baja, para no notarlo mínimo tiene que ser 35 hz.
Si, yo sospechaba tambien del PWM, ademas de que como ya me han comentado en otro foro, la funcion PWM que es la que actua directamente sobre las salidas, queda desatendia mientras el micro atiende a la recepcion del puerto serie y a las funciones de control. Así que la solucion será hacer el PWM utilizando la inturrupcion del TMR, tal y como dice MLO__.
Sobre parpadeo cuando no cambio el duty, hay no hay problema, la frecuencia la tengo en unos 70Hz.
Hola
Pues, veo un delay de 10mS cada vez que entra un dato por el serial ... eso debe desajustar el periodo del PWM ... prueba manejarlo por interrupcion ;)
Saludos
El delay, la verdad que nii me acuerdo porque lo puse, pero he probado a quitarlo y sigue igual. La solucion esta en, como bien dices, hacer el PWM utilizando interrupcion de algun temporizador.
El problema es que no se bien como hacer el PWM utilizando interrupcion. ¿Podeis indicarme un poco?, porfavor.
Tambien se que el 18f4520 tienemodulo CCP y podria utilizarlo para sacar el PWM, pero tampoco se como hacerlo.
Bueno muchisimas gracias de nuevo.
Un slaudo!
-
El problema es que no se bien como hacer el PWM utilizando interrupcion. ¿Podeis indicarme un poco?, porfavor.
Yo hice un PWM para controlar 18 servos, por ahí te das una idea de como hacer el tuyo, esta en c18 pero es simple de seguirlo ;-)
http://www.todopic.com.ar/foros/index.php?topic=39181.msg331864#msg331864
-
Yo hace tiempo hice un control pwm por soft controlado por USB HID no tan bueno, pero se hace el esfuerzo :). Espero te sea de ayuda para ti.
(hecho en CCS).
Apoyado mucho en con este excelente proyecto de gu1llermo
http://www.todopic.com.ar/foros/index.php?topic=20918.msg303265#msg303265
Espero te ayude mucho
-
Muchísimas gracias a los dos.
Ya lo tengo planteado gracias a vuestros proyectos.
Un saludo y gracias de nuevo a todos!!!
-
Buenas Amigos, acudo a uds para ver quien me puede colaborar con la inserción de un PWM por software en un proyecto que estoy realizando.
Les cuento el proyecto q realizo es la integración de una tarjeta de adquisición y Matlab, a través de procesamiento de señales en matlab diseñe un sistema de control lumínico, por ahora el pic solo prende y apaga las luces del recinto controlado dependiendo del carácter que le envié matlab, ahora a través de unas señas que haré frente a una cámara matlab detectara un patrón y modificara la intensidad de las luces.
Estuve leyendo y la mejor solución es realizar un PWM por software, pero la verdad no entiendo mucho la programación de los pic solo básico, quisiera saber si alguien podría colaborarme en esto, es algo así como urgente!
Este es el Codigo en ccs que llevo hasta ahora
#include <18F4550.h> // Definición de registros internos.
#fuses HSPLL,MCLR,NOWDT,NOPROTECT,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOLVP
#use delay(clock=20000000) // Frecuencia máxima de trabajo 20 Mhz
#use fast_io(A)
#use standard_io(B)
#use standard_io(D)
#include "usb_cdc.h" // Descripción de funciones del USB, entre comillas es porque esta trabajando sobre la misma carpeta
#include "usb_desc_cdc.h" // Descriptores del dispositivo USB.
void main() {
int sal1, sal2;
unsigned char datoIN;
usb_cdc_init(); // Configuramos al puerto virtual.
usb_init(); // Inicializamos el stack USB.
set_tris_B(0x00); // Configuro el puerto b salida
while(!usb_cdc_connected())
{
OUTPUT_HIGH(PIN_E0);
OUTPUT_LOW(PIN_E1);
DELAY_MS(500);
OUTPUT_HIGH(PIN_E1);
OUTPUT_LOW(PIN_E0);
}
// espera a detectar una transmisión de la PC (Set_Line_Coding).
OUTPUT_HIGH(PIN_E0);
OUTPUT_LOW(PIN_E1);
sal1=0; //Inicializo Variables alternativas
sal2=0; //Inicializo Variables alternativas
do{
usb_task();
//////////////////////////////////////////////////////
if (usb_enumerated())
{ // Espera a que el dispositivo sea enumerado por el host.
OUTPUT_LOW(PIN_E0);
OUTPUT_HIGH(PIN_E1);
if(usb_cdc_kbhit())
{ // En espera de nuevos caracteres en el buffer de recepción.
datoIN = usb_cdc_getc();
if(datoIN == 'a')
{ //¿lo que llegó fué el caracter a = hay movimiento en el salon 1 y esta en el nivel mas alto?
OUTPUT_HIGH(PIN_B1);
sal1=1; //si, entonces se prenden las luces del salon 1
}
if(datoIN == 'b')
{ // ¿lo que llegó fué el caracter b = hay movimiento en el salon 1 y esta en el nivel 2?
}
if(datoIN == 'c')
{ // ¿lo que llegó fué el caracter c = hay movimiento en el salon 1 y esta en el nivel 3?
}
if(datoIN == 'd')
{ // ¿lo que llegó fué el caracter d = hay movimiento en el salon 1 y esta en el nivel 4?
}
if(datoIN == 'g')
{ //¿lo que llegó fué el caracter g = no hay movimiento en el salon 1?
OUTPUT_LOW(PIN_B1);
sal1=2;
//si, entonces se apagaran las luces del salon 1
}
if (sal1==1) // Pregunto por variable del salon
{
OUTPUT_HIGH(PIN_B2); // Prende Led Indicador
}
else
{
OUTPUT_LOW(PIN_B2); // Prende Led Indicador
}
}
}
}while (TRUE); // bucle infinito.
}
el caracter a prende las luces , el caracter g apaga las luces y los caracteres b,c,d son las señas para el control de intensidad.
Lo que necesito es implementar el pwm en estos caracteres sobre el pin B0, les agradesco su ayuda!!!
Adjunto el circuito