Controlar brillo de LED con PWM en PIC16F628A

Buenas, recurro a este foro para pedir ayuda, si es que alguien sabe como hacer para encender un led pero de a poco , cambiando su brillo, intensidad, a través del tiempo y una vez encendido apagarlo lentamente de la misma manera. Sé como hacer encender y apagar led, solo que se hagan lentamente cambiando su brillo de menos a más a traves del tiempo no se como hacerlo en software Programo en C con CCS.
y tengo esto por ahora pero no me funciona:

Código:
 #include "C:\\librerias\\16F628A.h"
#use delay(clock = 20000000)
#fuses HS, NOWDT,PUT,BROWNOUT,NOMCLR,NOLVP,PROTECT,NOCPD
#use fast_io(A) // estandar de entrada y salidas de los puertos, necesario para que funcione
#use fast_io(B)
#zero_ram
int data=0,time=0;
void main(){ 
 
set_tris_b(0b00000000);
delay_ms(50); 
setup_timer_2(T2_DIV_BY_1,254,1); 
setup_ccp1(ccp_pwm); 
 
while(1){ 
   data=data+5; 
   if(data==255){data=0;} 
   delay_ms(10+time); 
   set_pwm1_duty(data); 
  } 
}
...
 
Última edición:
Eso se realiza utilizando PWM, verifica si el PIC contiene el módulo CCP (modo PWM) ya que será más fácil programarlo. Si no, tendrás que calcular los tiempos de encendido y apagado del Puerto, esto se realiza calculando los tiempos.
*****************************************************
Revisando el datasheet del PIC (páginas 58 y 59) si contiene el modulo.
Lo que necesitas es declarar los registros y calcular el periodo (1kHz, 2kHz,10kHz) que te funcione.
El datasheet contiene las fórmulas.

Si utilizas el CCS ahí un libro muy bueno, no me acuerdo muy bien del nombre pero en Google búscalo como "Libro CCS Proteus".
Espero haberte ayudado, Saludos.
 
Última edición:
Si lo tiene, si en el codigo lo estoy utilizando y nisiquiera prende RB3, no se si me falta agregar cosas al diseño de proteus... e hize todos los calculos que necesitaba 4kHZ y obtuve este codigo nuevo:

Código:
#include "C:\\librerias\\16F628A.h"
#use delay(clock = 20000000)
#fuses HS, NOWDT,PUT,BROWNOUT,NOMCLR,NOLVP,PROTECT,NOCPD
#use fast_io(A) // estandar de entrada y salidas de los puertos, necesario para que funcione
#use fast_io(B)
#zero_ram

int16 data=0;
void main(){ 
 
set_tris_b(0b00000000);
setup_timer_2(T2_DIV_BY_16,78,1); //78 por formula desbordamiento timer2
setup_ccp1(ccp_pwm); // habilita el pwm
 
while(1){    
	if (data==313){
	data=0;
	}
	data=data+2; 
	set_pwm1_duty(data);
	delay_ms(25); 

} 
   
}

y el proteus:
 

Adjuntos

  • 111.png
    111.png
    18.3 KB · Visitas: 87
Yo utilizo mikroC, así que no puedo decirte si está bien o mal en CCS, pero como te comenté del libro es bueno, viene bien explicado, te aseguro que resuelves tus dudas.

Yo utilizo los registros del PIC, pocas veces las librerías. Primero defino los registros: PR2, T2CON y CCPR1CON.
Ya después utilizo solo el registro CCPR1L para controlar el duty cycle de la señal y me funciona de maravilla.
 
si es que alguien sabe cómo hacer para encender un led pero de a poco, cambiando su brillo, intensidad, a través del tiempo y una vez encendido apagarlo lentamente de la misma manera.
Yo lo hago utilizando el Timer 0 para aumentar y disminuir el ciclo activo del PWM.
Es muy sencillo hacerlo de esa forma y el código no es complicado.

Adjunto el ejemplo con simulación. (Oscilograma)
Físicamente se nota un efecto de variación de luminosidad en el LED, lento y estable que sube y baja.
Esto viene siendo como las lámparas de obstrucción en sistemas de seguridad y señalamiento.
 

Adjuntos

  • 16F628A LED PWM.rar
    31.6 KB · Visitas: 384
Yo lo hago utilizando el Timer 0 para aumentar y disminuir el ciclo activo del PWM.
Es muy sencillo hacerlo de esa forma y el código no es complicado.

Adjunto el ejemplo con simulación. (Oscilograma)
Físicamente se nota un efecto de variación de luminosidad en el LED, lento y estable que sube y baja.


Hola muchas gracias por responderme :) , tengo algunas dudas, puedo probarlo colocando un led en el puerto del osciloscopio en la simulacion o no notaria los cambios de brillo?
Otra duda cuando copio tu codigo y lo intento compilar con MPLAB me tira el siguiente error sabes a que se debe? "Undefined Identifier T0_INTERNAL" intente googlearlo pero no encontre algo similar..

Desde ya muchas gracias por la ayuda :)

Reedit: cambie TO_INTERNAL por RTCC_INTERNAL y pudo compilar, afecta en algo o es cosa del compilador?
Otra cosa, cual es la formula para calcular el valor del set_timer0 dado que uso un reloj de 20Mhz y en el osciloscopio se ve rara la onda, gracias!
 
Última edición:
¿Puedo probarlo colocando un LED en el puerto del osciloscopio en la simulación o no notaría los cambios de brillo?
No se pueden ver los cambios de intensidad en el LED durante simulación con PWM.
Cuando copio tu código y lo intento compilar con MPLAB me tira el siguiente error. ¿Sabes a que se debe? "Undefined Identifier T0_INTERNAL"
Intenté googlearlo pero no encontré algo similar.
Eso se debe a que tu compilador ya es obsoleto y no contiene las nuevas constantes.
Reedit: cambie TO_INTERNAL por RTCC_INTERNAL y pudo compilar, afecta en algo o es cosa del compilador?
No afecta. Esa constante es de versiones anteriores y también está disponible en la versión actual.
¿Cuál es la fórmula para calcular el valor del set_timer0, dado que uso un reloj de 20 Mhz. y en el osciloscopio se ve rara la onda.
La fórmula viene en la hoja de datos al igual que toda la información que requieras sobre el PIC.
En el ejemplo usé un desborde cada 30 ms. teniendo 4 MHz con el oscilador interno.

Nota que si cambias la frecuencia de oscilación, también se debe cambiar la configuración del Timer 2.
Si no haces eso también se verá afectada la frecuencia del PWM.
También existe otro detalle importante cuando se aumenta la frecuencia de reloj.
Los tiempos de desborde para los Timers disminuyen, y por consecuencia se logran frecuencias más altas para el PWM.

Con 20 MHz. El desborde máximo para el Timer 0, será de 13.1072 ms. estando el prescaler a 1:256
Así que la variación en los cambios de intensidad sobre el LED serán más rápido.

Entonces es importante que tomes eso en cuenta para elegir la frecuencia de operación del microcontrolador.
 
Muchas gracias por la información amigo, me has aclarado un montón :D

sabes que he estado probando casi todo el día y he llegado a un codigo coherente con ccs en donde la onda debiese variar subiendo y bajando el brillo del led, pero por alguna razón el PIN no está recibiendo nada por lo que no oscila nada en ella, me podrías guiar en donde se encuentra posiblemente el error que no he logrado solucionarlo aún por favor, si Revisas la imagen te darás cuenta que por RB3 no sale nada, se encuentra en azul y no en rojo :c
:

Código:
#include "C:\librerias\16F628A.h"
#fuses intrc_io, nocpd, noprotect, nomclr
#use delay(clock = 4M)

int variable=0;

void main(){
set_tris_b(0b00000000); 
setup_timer_2(T2_DIV_BY_16,254,1);
setup_ccp1(ccp_pwm);

while(1){
	variable=variable+5;
	if(variable=255){
		for(variable=255;variable<0;variable=variable-5){
		set_pwm1_duty(variable);
		delay_ms(20);
		}
	}
	set_pwm1_duty(variable);
	delay_ms(20);
}

}
 

Adjuntos

  • Sin título.jpg
    Sin título.jpg
    66.7 KB · Visitas: 50
En lenguaje C debes igualar usando == y no un solo =
Esto es cuando comparas, cuando asignas si se usa un solo signo =

La variable "variable" no puede llegar a ser menor de 0 porque es una variable sin signo.

En C también es más fácil que escribas; variable += 5; y no: variable = variable + 5;
 
Última edición:
prueba con esto:
Código:
void main() {
TRISB = 0x00;
PORTB = 0x00;
    PR2 = 0xF9; //1kHz
  T2CON = 0x05;
CCP1CON = 0x0C;
while(1) {
CCPR1L = 0x7D; //50%
}
}
Ese programa únicamente genera una frecuencia de 1 KHz con ciclo activo fijo, y lo que se requiere es que aumente y disminuya el ciclo activo constantemente, así como lo expuse en el ejemplo que subí.

Aparte no tiene sentido incluir dentro del bucle el registro CCPR1L si siempre aplicas el mismo valor.
Y en PIC C Compiler no se usan esos registros porque tiene funciones predefinidas que lo hacen.
Por lo tanto ese código sin la declaración de registros, dará errores si se compila en PCWHD.
 
Última edición:
muchas gracias por la ayuda, les informo que modifique lo que me dijeron y aún así sigue sin salida por el pin RB3, adujunto imagen para que me crean :p no se a que se deberá :c

el código lo dejé así:
Código:
#include "C:\librerias\16F628A.h"
#fuses intrc_io, nocpd, noprotect, nomclr
#use delay(clock = 4000000)

int variable=0;

void main(){
set_tris_b(0b00000000); 
setup_timer_2(T2_DIV_BY_16,254,1);
setup_ccp1(ccp_pwm);

while(1){
	variable=variable+5;
	if(variable>=255){ //probé con == y >= y no funciona
		for(variable=255;variable<=5;variable=variable-5){
		set_pwm1_duty(variable);
		delay_ms(20);
		}
	}
	set_pwm1_duty(variable);
	delay_ms(20);
}

}
 

Adjuntos

  • 1.png
    1.png
    38.4 KB · Visitas: 29
¿Y por qué no implementas el programa del ejemplo que subí?
Hace lo que requieres. ¿No? Eso era lo que requerías en tu primer post.
 
es que con tu código se debía de presionar un boton para que cambiara el pulso y yo necesito que siempre haga lo mismo subir de 0 a 100 y bajar de 100 a 0 infinitamente , no logre modificar tu codigo para hacer esto, por eso no lo segui ocupando jeje
 
Creo que estás equivocado. El programa que subí hace los cambios automáticamente.
No se tiene que presionar ningún botón para que realice la variación del ciclo activo.
De hecho el único botón que tiene es el de reset, y es opcional.

Prueba el circuito físicamente y lo podrás comprobar. :cool:
 
entonces debo probarlo fisicamente?, por que con el osciloscopio no me muestra ninguna onda si no presiono el boton :p
mira adjuntare cuando no apreto nada(sin) y cuando presiono el boton(con):
 

Adjuntos

  • sin.png
    sin.png
    38.3 KB · Visitas: 28
  • conboton.jpg
    conboton.jpg
    84.4 KB · Visitas: 28
Algo debes estar haciendo mal. No realices modificaciones al programa ni al diseño.
El circuito empieza a correr el programa desde el inicio, tanto en simulación como físicamente.
Si puedes ver en la ventana "Watch Window" que la variable "ciclo" aumenta y disminuye, quiere decir que el programa está funcionando.

Subí dos simulaciones, una en proteus 7.10 y la otra en proteus 8.3
En ambas se muestra la forma de onda como empieza el ciclo activo desde 0 % a 100 % y luego inversamente.

Físicamente también funciona y ahí si se puede ver la actividad en el brillo del LED.

También se pueden tomar los oscilogramas físicos en tiempo real.

Ciclo activo al mínimo.
Min_Duty.png

Ciclo activo a la mitad. (50 %)
Mid_Duty.png

Y ciclo activo al máximo.
Max_Duty.png

Las capturas físicas son aproximadas al ciclo, porque es algo complicado atinarle. :D
 
D@rkbytes si solo quiero un "Duty Cycle" fijo, digamos 25%, entonces me podrías asesorar con el código en C CCS.

Otra cuestión la frecuencia del PWM se puede configurar digamos a 200 Hz.

Gracias de antemano D@rkbytes.
 
Atrás
Arriba