TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: adolfoadc en 06 de Febrero de 2004, 12:40:00
-
Buenas amig@s,
Necesito hacer lo siguiente con un pic12c508, debo dar en una de sus salidas una señal pwm de 500HZ y ir variando el duty cicle desde el 0% al 100% en un espacio de tiempo determinado (3 segundos desde 0% al 100%), os preguntareis para que?
Con esto pretendo encender y apagar un diodo led blanco de forma suave, es decir se va encendiendo poco a poco hasta llegar a tope, espero un par de segundos y comienza a apagarse poco a poco hasta que se apaga totalmente, y luego a encenderse y asi sucesivamente.
Hay por ahi algo para conseguir esa señal pwm en un micro sin pwm (12c508).
Gracias colegas,
-
Lo primero que se me ocurre, aunque por lo poco que sé
, es el uso de un 555 , y variar la resistencia (eso ya no se como). No se si te habre ayudado, tal vez te he comido la cabeza, pero bueno...
saludos
-
Creo que lo mejor es que hagas un PWM por programa... enciendes (duty cicle) y apagas con un período fijo... el que te dan los 500hz que dices... o sea 2ms... si fuera en una onda cuadrada normal serían 1ms por semiciclo... o sea encendido al 50%.
varías el duty cicle (dc) en tiempo desde 0.1ms a 1.9ms (0 a 100%), por lo tanto el ciclo bajo deberá ser 2ms - dc....
Eso lo repites y modificas a variable en el tiempo como para provocar el encendido y apagado gradual en forma secuencial.
Espero haberte ayudado.
Si quieres que te orientemos con el código.. deberás decirnos en que lenguaje programas.
Un abrazo...
marmatar
-
También puedes mirar esto y ver si puedes sacar algo en claro:
http://www.microchip.com/1010/suppdoc/appnote/all/an654/index.htm
Además, así por encima, si sólo va a hacer eso o mientras haga eso no hace otra cosa, pues yo lo haría en C. Un bucle con un par de delays cada uno con una variable. Incrementas una y la otra la decrementas. Esto hasta que llegue a cero la segunda variable. Luego un delay con el tiempo que quieres que esté encendido (2seg) y ahora el mismo bucle pero ahora el proceso inverso.
Lógicamente la suma de ambos delays es 2ms (500Hz).
Habría que ajustar esto un poco para que se note el encendido y el apagado. Vamos para que no vaya tan rápido que no se note. Pero para eso tenemos el proteus no...
saludos!!
-
Si lo que quieres es un simple regulador de luminosidad lo puedes hacer metiendo esa frecuencia como entrada de pulsos por RB0 y hacer un escalado con el TMR1, te saldrá un aumento y disminución de luminosidad muy fina.
Un saludo
-
Gracias por la prontitud en las respuestas.
Pretendo hacerlo con solo el pic y el led blanco enganchado a un transistor que es controlado por el pic.
No tengo mucha idea de C, ni de BAsic, asi que deberia hacerlo en ensamblador. Aunque si tengo los programas gracias al foro.
En C hay alguna intruccion para conseguir una salida PWM por cualquier pin digital. Cual es? Como se hace?
La idea es utilizar PWM, y un PIC para poder cambiar facilmente los ciclos de apagado y encendido en el programa.
Si me podeis echar una mano con el codigo, aunque sea en C, algo entiendo.
Gracias compañeros
-
¿Es fundamental que sea el 12c508? te lo digo porque en C sí que hay instrucciones que controlan directamente los módulos de captura-comparación-pwm, pero claro el PIC los tiene que tener, y ese no es el caso del 508.
Respecto a que si se puede generar pwm por otros pines que no sean RC1 ni RC2, con instrucciones directas en C, la respuesta es no.
Eso sí por software puedes generar con temporizaciones el pwm por el pin que quieras.
Si quieres adolfo te hago un programita sencillo para controlar tu led por pwm, con instrucciones C directas, usando un módulo CCP, eso sí tendría que ser para otro PIC.
Un saludo
PD. Con el TMR1 también se puede, metiendo la salida del detector de cruce por cero por RB0. Por cierto la onda ha de ser de 500Hz, no puede ser la de la red, 50Hz?
-
Os explico la razon, es que tengo que mirar por el precio y los 12C508 me salen por 0,57€. Y como el micro es lo unico que tiene que hacer tengo que hacerlo con este, da igual el tamaño del programa siempre que quepa dentro de los 512bytes que tengo de memoria, da igual la tecnica para hacerlo, aunque no tenga el programa quiero aunque sea la idea de como hacer una salida pwm en un pin cualquiera dentro de un micro que no tenga esa caracteristica.
El sacar una frecuencia de 500Hz por un pin no tiene problema ninguno, pero lo que no tengo claro es como variar el supuesto duty cycle de dicha señal pwm.
Gracias de antemano por vuestra ayuda.
-
Vale Adolfoadc.
Voy a ver si lo hago en C, me ha picado.
-
Hola Adolfo...
Si miras en el sitio de todopic... verás que hay un programita para un controlador de servos de modelismo, en asm... éste produce precisamente un PWM en un 16F84 (que no tiene ésa característica), variando el duty cicle...
Si mal no recuerdo, los servos tienen un rango entre 0.1ms y 1.9ms... o sea que el coclo completo es de 2ms... por lo tanto la frecuencia si mis cálculos mo fallan es de 500hz.
Quizá ésto te sirva para darte una idea de como se hace.
Un abrazo...
marmatar
Nota: sinó, mira en el apartado de robótica, en una oportunidad he puesto algo de control de servos... y era para PICs pequeños sin PWM.
-
Hola, aqui tienes un programita que escribi hace tiempo, y justamente controlaba el brillo de un display... te puede servir para sacar ideas

http://www.todopic.com.ar/asm/PWM/pwm.txt
Suerte!
Norberto
-
Ya está.
El uso de delay_us() en temporizaciones que necesitan ser precisas, no es muy recomendable. Aunque si lo único que se pretende es encender un LED suavemente y que a los dos segundos se apague suavemente, esté 2s parado y vuelta a empezar, pués este es el programa:
// Ejer30_5A.C
// El LED se enciende suavemente hasta el máximo y luego se apaga suavemente hasta cero
#include <16F84A.h>
#use delay(Clock=4000000)
main()
{
int16 b,c;
output_B(0x00);
set_tris_b(0x00);
setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
while(1)
{
delay_ms(2000);
while(b<255)
{
set_timer0(50);
while(get_timer0()<220)
{
output_high(pin_B0);
for(c=b;c!=0;c--)
delay_us(5);
output_low(pin_B0);
for(c=255-b;c!=0;c--)
delay_us(5);
}
b++;
}
output_bit(PIN_B0,1);
delay_ms(2000);
while(b>0)
{
set_timer0(50);
while(get_timer0()<220)
{
output_high(pin_B0);
for(c=b;c!=0;c--)
delay_us(5);
output_low(pin_B0);
for(c=255-b;c!=0;c--)
delay_us(5);
}
b--;
}
}
}
Si quieres más velocidad en el proceso cambia int16 por int8
Un saludo
PD. No tenía para probarlo físicamente, el 12C508 y lo hice con el 16F84. Cambia el #include <16F84A.h> por #include <12C508.h> y ya está (salida al LED por pin B0). Funcionamiento comprobado del circuito con el 12C508 en PROTEUS.
-
Gracias por vuestras respuestas, voy a digerir un poco la informacion que me habeis mandado, en cuanto tenga novedades os lo hago saber. ( a lo mejor mas que novedades tengo dudas pero bueno ya se resolveran
)
-
UNA PREGUNTA AMIGOS Y SI YO NECESITARA LO MISMO PERO CON DOS LED"S PERO A LA VEZ QUE UNO VAYA ENCENDIENDO EL OTRO VAYA APAGANDO MMMM... SE ENTIENDE
-
Hola, no se nada de C, pero se me ocurre que es muy simple, donde esta
output_high(pin_B0);
debajo escribes lo contrario para otro pin
output_low(pin_B1);
y viceversa....
Norberto
-
Así es Norberto.
Además añade encima del primer delay_ms(2000):
output_bit(PIN_B0,0);
output_bit(PIN_B1,1);
... y encima del segundo delay_ms(2000):
output_bit(PIN_B0,1);
output_bit(PIN_B1,0);
-
Ante todo daros las gracias a todos por vuestra ayuda,
mil gracias a POCHER por el programita ya estoy obligado a aprender C y lo mejor es que le he cogido el gustillo.
Os coloco el codigo ya depurado para un 12c508a, habia algunas cosillas que no me funcionaban, pero las consegui enmendar.
// Ejer30_5A.C
// El LED se enciende suavemente hasta el máximo y luego se apaga suavemente hasta cero
#include <12c508a.h>
//#fuses INTRC,NOWDT,NOMCLR,PROTECT
#use delay(Clock=4000000)
main()
{
int16 b;
int16 c;
int8 d;
int16 e;
setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
//setup_timer_1(T1_DISABLED);
//setup_comparator(NC_NC_NC_NC);
//setup_vref(FALSE);
output_B(0x00);
set_tris_b(0x00);
b=0;
c=0;
e=255;
while(TRUE)
{
output_bit(PIN_B0,0);
delay_ms(2000);
while(b<255)
{
d=0;
while(d<6)
// set_timer0(50);
// while(get_timer0()<220)
{
output_high(pin_B0);
for(c=b;c!=0;c--)
delay_us(2);
output_low(pin_B0);
for(c=e-b;c!=0;c--)
delay_us(28);
d++;
}
b++;
}
output_bit(PIN_B0,1);
delay_ms(3000);
while(b>0)
{
d=0;
while(d<6)
// set_timer0(50);
// while(get_timer0()<220)
{
output_high(pin_B0);
for(c=b;c!=0;c--)
delay_us(5);
output_low(pin_B0);
for(c=e-b;c!=0;c--)
delay_us(25);
d++;
}
b--;
}
}
}
Una de las cosas que me fallaron fue el timer0, lo sustitui por una variable que hace repetir el ciclo las veces que uno quiera para que vaya mas rapido o mas lento la subida y la bajada, otro problema fue la operacion de c=255-b, cuando realizaba esta operacion me daba un c de 16bits, mayor que 255 que es el valor maximo que toman ambas variables(sin embargo en el 12F629 no tuve problemas con dicho valor y lo unico que no iba era el tmr0), al final cambie algunos valores del delay para los anchos de pulsos para obtener un efecto mejor, todo fue cuestion de probar.
Todo va como la seda y he decidido de ahora en adelante programar en C, joder si hubiese tenido que hacer esto en asembler me da algo y para cambiar cosas esto es una maravilla.
-
je, je a mí también me pasó eso, es como si cambiaras de ir en bici a ir en coche.
Me alegro que hayas podido adaptar el programa al micro que querías.
Un saludo
-
Y como se dieron cuenta??

No entiendo porqué hace eso si está siempre dentro del rango para un byte.
-
Lo probe en el mplab en modo sim, y vi que tardaba un monton en ir de la instruccion de encendido a la de apagado, luego fui mirando el valor de las variables en C y vuala, que leches es esto si c=255-b y b siempre esta entre 0 y 255, como puede ser que c=64238. Prueba del millon, y si añado otra variable que sea del mismo tipo que c (int16)?, pues que funciona perfectamente, la razon no la se pero la solucion si
.
La verdad es que el simulador del mplab va bastante bien, casi se puede decir que es en tiempo real.