Autor Tema: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad  (Leído 5215 veces)

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

Desconectado glow_ing

  • PIC10
  • *
  • Mensajes: 22
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:

Código: [Seleccionar]
/*******************************************************************************
********************************************************************************
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

Ayúdenme Por favor!!
Gracias!!

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad
« Respuesta #1 en: 04 de Enero de 2013, 20:13:56 »
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.
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad
« Respuesta #2 en: 05 de Enero de 2013, 01:03:58 »
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 papel lo aguanta todo

Desconectado glow_ing

  • PIC10
  • *
  • Mensajes: 22
Re: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad
« Respuesta #3 en: 06 de Enero de 2013, 09:33:26 »
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!

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad
« Respuesta #4 en: 06 de Enero de 2013, 12:14:12 »
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
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado sirias52

  • PIC10
  • *
  • Mensajes: 40
Re: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad
« Respuesta #5 en: 06 de Enero de 2013, 15:42:03 »
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
« Última modificación: 06 de Enero de 2013, 15:46:14 por sirias52 »

Desconectado glow_ing

  • PIC10
  • *
  • Mensajes: 22
Re: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad
« Respuesta #6 en: 08 de Enero de 2013, 08:22:58 »
Muchísimas gracias a los dos.
Ya lo tengo planteado gracias a vuestros proyectos.

Un saludo y gracias de nuevo a todos!!!

Desconectado Macko77

  • PIC10
  • *
  • Mensajes: 6
Re: Dimmer 18F4520 - PWM por Software - Leds parpadean al controlar intensidad
« Respuesta #7 en: 01 de Diciembre de 2013, 12:29:33 »
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


 

anything