Problema con PWM y LCD en PIC C - CCS

Que tal como estan, el problema con el cual me gustaria me ayudaran es el siguiente:
Tengo un programa que hice en lenguaje C en PicC para el PIC16F877A, programa que tiene como funcion controlar el PWM por medio del ADC y a la ves mostrar el valor de velocidad en una LCD, bueno lo que hice fue el codigo que les adjunto, al parecer esta bien porque lo simule en Proteus y si cambia el valor mostrado en la LCD, aunque no estoy bien seguro si este trabajando bien el PWM pues lo grabe el Pic y no funciona el PWM, el valor en la LCD si aparece pero no cambia nada en el PWM, ¿afecta el uso de la LCD al mismo tiempo que el PWM?:unsure: o en que me estare equivocando de codigo?:eek:
El codigo que uso es:

Código:
#include "C:\proyecto\Version1.1\Control PWM\Controll_PWM.h"
#include <LCD.C>

void main()
{   unsigned int leido;    
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);   
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   lcd_init();
   // TODO: USER CODE!!
   while (true)
   {
      set_adc_channel(0);
      leido=read_adc();
      lcd_gotoxy(1,1);
      printf(lcd_putc,"%u   ",leido);
      setup_timer_2(T2_DIV_BY_1,61,16);
      setup_ccp1(CCP_PWM);
      setup_ccp2(CCP_PWM);
      set_pwm1_duty(leido);
      set_pwm2_duty(0);
   }
}
Ademas anexo la simulacion, les agradecere mucho su ayuda :D
 

Adjuntos

  • Control PWM.rar
    51.8 KB · Visitas: 427
  • control PWM y LCD.jpg
    control PWM y LCD.jpg
    80 KB · Visitas: 254
Última edición por un moderador:
//buenas tardes amigo aca te dejo la correcion del programa solo te faltaban agregar unas lineas de comando
Código:
#include <16F877A.h>
//#device adc=8


#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES PUT                      //Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#DEFINE  use_portc_lcd  true
#DEFINE  use_portb_kbd  true
#INCLUDE <kbd.c>
#USE  standard_io(a)
//#int_timer1
//int16 andar=0;

/****************************************************************/
#org 0x1f00,0x1fff {} // LINEAS PARA ACTIVAR EL BOOTLOADER
#build (reset=0x4)
/****************************************************************/
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

/********************************************************************/
//#define LCD_TYPE 2 //lcd 2x16
#include <lcd.c> // inicializa el LCD
/********************************************************************/



void main()
{   unsigned int leido;    
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);   
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   lcd_init();
   // TODO: USER CODE!!
   while (true)
   {
      set_adc_channel(0);
      leido=read_adc();
      lcd_gotoxy(1,1);
      printf(lcd_putc,"%u   ",leido);
      setup_timer_2(T2_DIV_BY_1,61,16);
      setup_ccp1(CCP_PWM);
      setup_ccp2(CCP_PWM);
      set_pwm1_duty(leido);
      set_pwm2_duty(0);
   }
}

// hecho por Alis Ernardo carvajal Rangel// // // //


 
Última edición por un moderador:
buenas... la verdad que no tengo aun mucha experiencia en pwm y si quisiera realizar la modulacion de ancho de pulso a traves de un teclado 4x4?... conectado al pto B?, quisiera ingresar la velocidad que deseo en funcion de su porcentaje, osea por el teclado ingresare 10, 20, 30, 40... para obtener una velocidad d 10%, 20%.. etc

Gracias
 
Última edición:
buenas... la verdad que no tengo aun mucha experiencia en pwm y si quisiera realizar la modulacion de ancho de pulso a traves de un teclado 4x4?... conectado al pto B?, quisiera ingresar la velocidad que deseo en funcion de su porcentaje, osea por el teclado ingresare 10, 20, 30, 40... para obtener una velocidad d 10%, 20%.. etc

Gracias

Claro que puedes, con set_duty(int) o set_pwm1_duty(int) puedes variar la anchura del pulso. Para que sea justamente un 10% o un 50% tendrias que hacer una conversion, porque si mal no recuedo en el duty puedes introducir valores entre 0 y 255 (8bits)
 
Claro que puedes, con set_duty(int) o set_pwm1_duty(int) puedes variar la anchura del pulso. Para que sea justamente un 10% o un 50% tendrias que hacer una conversion, porque si mal no recuedo en el duty puedes introducir valores entre 0 y 255 (8bits)

uhmm ya veo, pero me podrias explicar como calculo el duty cicle?... osea como saber la frecuencia maxima a la que debe trabajar mi motor, voy a utilizar un motor dc de 30V - 2A
 
Hola amigos. Tengo un código que estoy haciendo en lenguaje c para el pic16f887.
Se trata del pwm mostrado en lcd, pero no lo he logrado hacer que funcione en proteus.
Lo compilo con mplap y pic ccs compiler v5 y no me muestra errores, pero ya que lo cargo en el proteus no me muestra nada en el lcd.

Les comparto el código que llevo.

saludos.
Código:
#include <16f887.h>
#fuses intrc, nowdt, noprotect,nolvp,
#use delay(clock=4000000)
#include <lcd.c>
INT duty = 0;
int leido;

 void main()
{
 setup_ccp1(CCP_PWM);
 setup_timer_2(T2_DIV_BY_16, 124, 1);
 lcd_init();
while (true)

   {
 set_pwm1_duty(duty);
 if(input_state(PIN_A0)==1)
 {
 duty++;
 delay_ms(20);
 }
if (input_state(PIN_A1)==1)
{
duty--;
delay_ms(20);
}
{
 set_adc_channel(0);
      leido=read_adc();
      lcd_gotoxy(1,1);
      printf(lcd_putc,"%u",leido);
      setup_ccp1(CCP_PWM);
      set_pwm1_duty(leido);
     
}
}
}
¿Alguien me puede ayudar con el programa?
 
Última edición por un moderador:
Hola amigos. Tengo un código que estoy haciendo en lenguaje c para el pic16f887.
Se trata del pwm mostrado en lcd, pero no lo he logrado hacer que funcione en proteus.
Lo compilo con mplap y pic ccs compiler v5 y no me muestra errores, pero ya que lo cargo en el proteus no me muestra nada en el lcd.

¿Alguien me puede ayudar con el programa?
Te falta configurar los parámetros del ADC, por eso es que no puedes ver el resultado en la pantalla.
también debes decidir si controlarás el ciclo activo de forma análoga o digital, porque si lo haces de las dos formas simultáneamente, predominará una lectura y enseguida la otra, por lo tanto no tendrás un valor constante en la señal.

Si lo quieres hacer de forma digital, esta sería una forma modificando tu programa:
Código:
#include <16f887.h>
#fuses nobrownout,nofcmen
#use delay(internal = 4000000)
#include <lcd.c>

 void main()
{
int8 duty = 127;     // Iniciar a la mitad el ciclo activo del PWM

   setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 124, 1);
   setup_ccp1(CCP_PWM);
   setup_adc_ports(NO_ANALOGS);
   lcd_init();

while (true)
   {
   if(input_state(PIN_A1)==1)
   {
      duty ++;
         delay_ms(50);
            if (duty >=245){duty = 245;}  // No permitir que duty supere 245
         }
 
   if (input_state(PIN_A2)==1)
   {
      duty --;
         delay_ms(50);
            if (duty == 255){duty = 0;}   // No permitir el desborde del conteo
         } 

      lcd_gotoxy(1,1);
         printf(lcd_putc,"DIGITAL: %03u",duty);
            set_pwm1_duty(duty/2);
         }
}
Y si quieres controlar el ciclo activo del PWM de forma análoga lo podrías hacer así:
Código:
#include <16f887.h>
#device adc = 8            // 8 Bits de resolución para el ADC
#fuses nobrownout,nofcmen
#use delay(internal = 4000000)
#include <lcd.c>

 void main()
{
int8 duty;

   setup_ccp1(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 124, 1);
   setup_ccp1(CCP_PWM);
   setup_adc_ports(sAN0);           // Seleccionar el canal 0 del ADC
   setup_adc(ADC_CLOCK_INTERNAL);   // Usar el oscilador interno para el reloj del ADC
   set_adc_channel(0);              // Activar la lectura del canal 0
   lcd_init();

while (true)
   {
   duty = read_adc();
      lcd_gotoxy(1,1);
         printf(lcd_putc,"ANALOGO: %03u",duty);
            set_pwm1_duty(duty/2);
         }
}
Nota: en tu programa estás usando el pin RA0 para comprobar un estado lógico, pero al mismo tiempo es el pin del canal que seleccionaste para la lectura del ADC.

Suerte.
 
Última edición:
Que tal compañeros del foro, tengo problema con un teclado matricial, una lcd y la señal PWM para controlar un servomotor, es para controlar la apertura y cierre de una caja fuerte, y la parte del código que falla es la siguiente, estoy usando un 16f887 con oscilador interno,
Código:
 do{
   tecla=kbd_getc();
   if( tecla == '*' ){
      lcd_putc('\f');      // Se borra la cantalla
      lcd_putc("ABIERTO");
      delay_ms(300);
      for(i=0;i>=50;i++){
      output_high(pin_a1);
      delay_us(300);
      output_low(pin_a1);
      delay_us(21700);
      output_high(pin_a1);
      }
      delay_ms(300);
      i=0;
      claveOK=1;

   }
   
   if( tecla == '#' ){
      lcd_putc('\f');      // Se borra la cantalla
      lcd_putc("CERRADO");
      delay_ms(300);
      for(i=0;i>=50;i++){
      output_high(pin_a1);
      delay_us(2100);
      output_low(pin_a1);
      delay_us(19900);
      output_high(pin_a1);
      }
      delay_ms(300);
      i=0;
      claveOK=0;
      }
   }while(claveOK==1);

Lo que hago es abrir cuando presiono * y cierro cuando presiono # pero el problema es que no se genera la señal PWM. Adjunto el código del programa y la simulación. Desde ya muchas gracias
 

Adjuntos

  • Cerradura electrónica 16F887.rar
    169.2 KB · Visitas: 68
Última edición:
Buenas! Tengo un problema con este programa! Necesito controlar un motor mediante un puente H.
Estoy usando el siguiente programa:
Código:
void Configuracion(void)
{
   setup_oscillator(OSC_8MHZ);
   set_tris_a(Puerto_A);                              
   set_tris_b(Puerto_B);                              
   set_tris_c(Puerto_C);                             
   set_tris_d(Puerto_D);                              
   set_tris_e(Puerto_E);                                                         
   setup_adc_ports(AN0_TO_AN2);           //AN0 AN1 y AN2 activas como Analogas 
   setup_adc( ADC_CLOCK_DIV_8 );          // Declaramos que el reloj del adc sera interno
   set_timer1(0);                         // Inicializa el timer1
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);// Setup timer: Reloj interno, preescaler= 1 8mhz
   enable_interrupts(INT_TIMER1);         // Habilito interrupción particular del TIMER1
   enable_interrupts(int_rb);             //registro de int_rb
   enable_interrupts(GLOBAL);             // Activamos todas las interrupciones
   setup_timer_2(T2_DIV_BY_16, 125, 2);  // 500 Hz
   setup_ccp1(CCP_PWM);
   enable_interrupts(INT_TIMER2);
}

void main(void) 
{
   Configuracion();                    // Configuramos el PIC
   //Apagar_Alarmas();                   // Apagamos todas las alarmas
   //lcd_init();                         // Inicializamos el LCD 16x4
   set_timer0(Valor_TMR1);             // Inicializa el timer0
   set_pwm1_duty(DUTY);            // PWM 
   //set_pwm2_duty((int16)0);            // PWM
   //Presentacion();
   do
   {
   
      if(BANDERA_GIRO_1 == TRUE)
      {
         Output_high(PIN_C4);
         Output_low(PIN_C5);
         delay_ms(500);
         DUTY = 15;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 30;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 45;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 30;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 15;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 0;
         set_pwm1_duty(DUTY);
         delay_ms(100);
      
      }
      if(BANDERA_GIRO_2 == TRUE)
      {
         Output_high(PIN_C5);
         Output_low(PIN_C5);
         delay_ms(500);
         DUTY = 15;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 30;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 45;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 30;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 15;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 0;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         
      }
      
   }while(TRUE);
}
Y no me funciona :( pero para nada! ¿Alguien podria ayudarme por favor?
 
Última edición por un moderador:
Buenas! Tengo un problema con este programa! Necesito controlar un motor mediante un puente H.
Estoy usando el siguiente programa:
Y no me funciona :( pero para nada! ¿Alguien podria ayudarme por favor?
¿Y el esquema y/o simulación?
Aparte ese código está incompleto, no mencionas el tipo de PIC que usas y tampoco se puede saber la configuración de los registros TRIS.
 
Bueno, disculpa ya lo resolví, no estoy seguro realmente de que era, pero lo volví a hacer y funcionó perfecto.

Uso el PIC16F877A.
Código:
[INDENT]#include <16F877a.h>    ///   libreria para el manejo del pic16f877a
#device ADC=10                  // Nº de bits que devolverá una conversion A/D
 
///////////////////////////////////////////////////////////////////////////////
//  DESCRIPTION:  Fuses                                                      //
///////////////////////////////////////////////////////////////////////////////
 
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT
#use delay(clock=4000000)      ///   declara  la frecuencia del cristal
 
#byte port_a = 0x05  // declaramos los puertos a usar
#byte port_b = 0x06
#byte port_c = 0x07
#byte port_d = 0x08
#byte port_e = 0x09
 
char DUTY, CONV; // Registros a usar
int1 BANDERA_GIRO_1 = FALSE;
INT1 BANDERA_GIRO_2 = FALSE;
int16 ADC;
 
 
#int_TIMER1                //////////////////////////////////////////////////////
void TIMER1_isr(void)      //Función de interrupción por desbordamiento TMR0   //
{ 
 
if(input(PIN_B7))
{
conv = 1;
}else if(input(PIN_B6))
{
conv = 2;
}
 
}
 
#INT_RB
void rb_isr()
{
   unsigned int8 valor=input_B();   //Traemos el valor del puerto B
   valor=valor & 0b11000000;        //Enmascaramos el estado de pines que no sean B0, B4, B5, B6, B7
   switch(valor)
   {
      case 0b10000000:             //En caso de estar pulsado Boton 1.-
 
 
      conv++;
 
      if(Conv == 1)
      {
      BANDERA_GIRO_1 = TRUE;
      BANDERA_GIRO_2 = FALSE;
      }else if(conv == 2)
      {
      BANDERA_GIRO_1 = FALSE;
      BANDERA_GIRO_2 = FALSE;
      }else if(conv == 3)
      {
      BANDERA_GIRO_1 = FALSE;
      BANDERA_GIRO_2 = TRUE ;
      }else if(conv == 4)
      {
      BANDERA_GIRO_1 = FALSE;
      BANDERA_GIRO_2 = FALSE;
      CONV = 0;
      }
      BREAK;
 
   }
}
 
void main (void)
{
 
 
 
set_tris_a(0b111111); 
set_tris_b(0xf0);
set_tris_c(0b00010000); 
set_tris_d(0x00);
set_tris_e(0b111);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
disable_interrupts(INT_TIMER1);
disable_interrupts(INT_TIMER2);
enable_interrupts(int_rb);
enable_interrupts(GLOBAL);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(0);
setup_timer_2(T2_DIV_BY_16, 127, 1);
setup_ccp1(CCP_PWM);
set_timer1(45553);
 
port_a=0x00;
port_b=0x00;
port_c=0x00;
port_d=0x00;
port_e=0x00;
 
while(true){
 
      if(BANDERA_GIRO_1 == TRUE)
      {
 
         Output_high(PIN_C4);
         Output_low(PIN_C5);
         delay_ms(500);
         DUTY = 25;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 50;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 75;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 50;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 25;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 0;
         set_pwm1_duty(DUTY);
         delay_ms(100);
      }
      if(BANDERA_GIRO_2 == TRUE)
      {
         Output_high(PIN_C5);
         Output_low(PIN_C4);
         delay_ms(500);
         DUTY = 15;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 30;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 45;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 30;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 15;
         set_pwm1_duty(DUTY);
         delay_ms(100);
         DUTY = 0;
         set_pwm1_duty(DUTY);
         delay_ms(100); 
      }
 
 
}
}[/INDENT]
 

Adjuntos

  • 123456.jpg
    123456.jpg
    145.9 KB · Visitas: 45
Última edición por un moderador:
Bueno, disculpa ya lo resolví, no estoy seguro realmente de que era, pero lo volví a hacer y funcionó perfecto.

Uso el PIC16F877A.
El PIC16F877A no usa esta instrucción que sería para los PIC con registro OSCCON
setup_oscillator(OSC_8MHZ);

En fin, bugs del compilador de CCS que a veces permite ingresar código que no corresponde con el PIC usado.

Que bien que resolviste el problema.

Suerte.
 
Atrás
Arriba