Autor Tema: duda sobre ADC en CCS  (Leído 3874 veces)

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

Desconectado distro

  • PIC10
  • *
  • Mensajes: 9
duda sobre ADC en CCS
« en: 17 de Septiembre de 2009, 02:56:48 »
Hola
Estoy trabajando en un programa para un pic 16f873a con el fin de autoregular el voltaje segun cambia la carga: La idea es que el microcontrolador genere cierto voltaje dado por medio de PWM y luego "lea" por medio de ADC cual es el resultado y ajuste los ciclos de trabajo segun sea necesario. Para esto hice un programa bien simple el cual basicamente decide por medio de un "if", si aumentar o disminuir el ciclo de trabajo en base lo que lee desde la conversion analogo/digital, el problema es que midiendo con un tester suceden cosas extrañas: Comienza con 5 volts y luego disminuye, pero al llegar al voltaje dado vuelve a saltar a 5 volts para disminuir lentamente de nuevo. Estoy seguro que esto ya lo han hecho y hay buenas soluciones por en google, pero me gustaria saber porque falla este metodo. Sera un problema con la velocidad de muestreo?.

este es el codigo:

Código: [Seleccionar]
#include <16f873A.h>

#fuses XT,NOWDT,NOPUT,NOPROTECT,NODEBUG,BROWNOUT,NOLVP,NOCPD,NOWRT
#device  ADC=8                   
#use     delay(CLOCK = 4000000)
#use RS232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)

void main (void)
{

float medicion;
float voltaje;
float duty;

SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(AN0);                     
SET_ADC_CHANNEL(0);

setup_timer_2(T2_DIV_BY_1, 49, 1);
 
setup_ccp1 (CCP_PWM);

setup_ccp2 (CCP_PWM);

while (true)
{

medicion=read_adc ();
voltaje=(medicion*5)/256;
printf("%g\r",voltaje);

if(voltaje>0.5){
duty=duty-1;

}
else{
duty=duty+1;
}
set_pwm1_duty(duty);

set_pwm2_duty(duty);

}
}

Gracias :shock:

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: duda sobre ADC en CCS
« Respuesta #1 en: 17 de Septiembre de 2009, 13:17:58 »
creo que acá puede faltar:

while (true)
{
   SET_ADC_CHANNEL(0);
   delay_us(20);

   medicion=read_adc ();
   voltaje=(medicion*5)/256;
   ...

eso para fijar el canal a leer y el retardo del capacitor de muestreo

quizá ayude, saludos
.

Desconectado distro

  • PIC10
  • *
  • Mensajes: 9
Re: duda sobre ADC en CCS
« Respuesta #2 en: 17 de Septiembre de 2009, 13:27:00 »
gracias voy a probar, pero es necesario que  SET_ADC_CHANNEL(0); este dentro de la funcion while? en el codigo que puse esta en main.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: duda sobre ADC en CCS
« Respuesta #3 en: 17 de Septiembre de 2009, 13:36:51 »
Pienso que si, aunque parece redundante, pero si no se coloca sería innecesario colocar el retardo y por tanto ya no colocas nada y lo dejas como estaba, así que para asegurarse qeu se captura el canal 0 creo que hace falta colocarlo en el while, en realidad cada vez que se lea un canal.

saludos.
.

Desconectado _Maxi

  • PIC10
  • *
  • Mensajes: 34
Re: duda sobre ADC en CCS
« Respuesta #4 en: 18 de Septiembre de 2009, 02:17:05 »
Perdón que me meta, no se mucho de esto. Pero una señal pwm puede ser leída como una señal analógica? No son cosas distintas?

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: duda sobre ADC en CCS
« Respuesta #5 en: 18 de Septiembre de 2009, 11:10:57 »
Una señal PWM es una señal pulsante, solamente emite sus pulsos en el lado positivo (primer cuadrante) del sistema de coordenadas cartesianas, o mejor dicho solo varía entre 0 y +5V, en caso de una señal digital o TTL.

Si mides con un multímetro (tester, polímetro, o el nombre que le des) esa señal PWM que varía de 0 a 5V, no leerás 5V ni 0V, medirás el valor promedio de esa señal pulsante, y este valor dependiendo de la separación entre los pulsos (frecuencia, ancho de pulso) se aproximará a uno de los extremos a 0V o a 5V

por tanto puede ser considerado como una variación analógica, en cuanto al valor promedio se refiere

El valor promedio está dado, si no me equivoco como:

\frac{1}{T}\int_{0}^{T}\ f(t)dt

donde T es el periodo de la función f(t)  T=1/f
y f(t) es la señal PWM, en este caso.
.

Desconectado matocomasi

  • PIC10
  • *
  • Mensajes: 26
Re: duda sobre ADC en CCS
« Respuesta #6 en: 18 de Septiembre de 2009, 17:01:33 »
Hola distro,

Si no vas cambiar de canal analogico deja el set_adc_channel(0) fuera del while.

He visto un error en tu codigo, has definido la variable duty como float, pero la variable que sirve de entrada a la funcion set_pwm1_duty(duty) debe ser del tipo int8 o int16.

No se si esto sera el problema, pero seguro que esto esta mal.

Saludos

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: duda sobre ADC en CCS
« Respuesta #7 en: 18 de Septiembre de 2009, 17:26:51 »
Tienes razón matocomasi, no me fije esas variables float.

Si no me equivoco funciona no colocar el set channel, si solo usas ese canal, pero creo que lo correcto es colocarle el set y el delay, para eso del condensador o algo así

saludos.
.

Desconectado matocomasi

  • PIC10
  • *
  • Mensajes: 26
Re: duda sobre ADC en CCS
« Respuesta #8 en: 18 de Septiembre de 2009, 17:44:32 »
El set_adc_channel solo hay de ponerlo la primera vez, ya que no va a usar mas entradas analogicas.

El delay es necesario si los procesos a ejecutar son tan rapidos que no dan tiempo al condensador a tomar la carga correspondiente para la conversion, pero en este caso concreto hay una llamada a un printf y este consume muchos recursos y ciclos de reloj por lo que no es necesario. De todas formas yo lo pondría como norma para que no se olvide nunca.

Hay que dejar claro que una instruccion en ensamblador tarda como minimo un ciclo de instruccion, pero en C lo que para nosotros es una simple instruccion, convertida en ensamblador son muchas.

Saludos

Desconectado distro

  • PIC10
  • *
  • Mensajes: 9
Re: duda sobre ADC en CCS
« Respuesta #9 en: 19 de Septiembre de 2009, 11:08:45 »
Hola y gracias por sus respuestas.

Probe sus sugerencias, pero sigo con el mismo problema. De todos modos ya se donde donde esta: Si dejo el ciclo de trabajo fijo y como valor "1", el voltaje al que llego no es menor a los 1.4 volts, por lo tanto al sumar o restar el valor del ciclo de trabajo, el voltaje cambia dramaticamente considerando que pretendo obtener alrededor de 0.5 volts.
Alguna idea?
gracias

Desconectado matocomasi

  • PIC10
  • *
  • Mensajes: 26
Re: duda sobre ADC en CCS
« Respuesta #10 en: 19 de Septiembre de 2009, 15:09:21 »
Podrias pegar una imagen del circuito electrico, asi creo que te podra ayudar un poco mas.

Saludos

Desconectado distro

  • PIC10
  • *
  • Mensajes: 9
Re: duda sobre ADC en CCS
« Respuesta #11 en: 19 de Septiembre de 2009, 21:14:11 »
Aqui esta el diseño del circuito, el cable rojo es el que va al adc, lo demas no es muy importante.


Desconectado matocomasi

  • PIC10
  • *
  • Mensajes: 26
Re: duda sobre ADC en CCS
« Respuesta #12 en: 20 de Septiembre de 2009, 06:42:30 »
Hola distro,

Me he tomado la libertad de hacer pequeñas modificaciones a tu codigo para intentar simular lo que propones.

Tengo un par de dudas que espero me puedas resolver:

1.- Por que has definido unos parametros de timer 2 tan bajos? El timer 2 se desborda muy rapido.
2.- Porque haces una comparacion entre "voltaje" y 0.5

 Debes ajustar el timer 2 para que genere un periodo equivalente al tiempo de lectura del ADC, si no, no haces una lectura buena.
 Al mezclar variables de distinto tipo debes usar los castings para que no haya problemas de conversion, si no el valor de voltaje siempre es 0.00 y por eso no funciona.
Echale un vistazo a este codigo y simulalo en proteus, usa el osciloscopio y el virtual terminal y podras ver lo que te comento.
El ADC solo esta leyendo 0 ó 255, nunca valores intermedios y eso se puede deber a dos cosas, una es que no se pueda usar un PWM como señal analogica de entrada( cosa con la que no estoy de acuerdo) y otra que los tiempos de lectura del adc no se ajustan al periodo del PWM y hace lecturas erroneas.

Espero que te pueda servir el codigo aunque lo tengas que adaptar para tus necesidades concretas.

#include <16f873A.h>

#fuses XT,NOWDT,NOPUT,NOPROTECT,NODEBUG,BROWNOUT,NOLVP,NOCPD,NOWRT
#device  ADC=8                   
#use     delay(CLOCK = 4000000)
#use RS232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)

void main (void)
{

unsigned int8 medicion;
float voltaje;
unsigned int8 duty=127;

SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(AN0);                     
SET_ADC_CHANNEL(0);

setup_timer_2(T2_DIV_BY_4, 255, 1);
 
setup_ccp1 (CCP_PWM);

setup_ccp2 (CCP_PWM);

while (true)
{
delay_us(10);
medicion=read_adc ();

voltaje= ((float)(medicion)*5/256);

if(voltaje>0.5){
duty=duty-1;

}
else{
duty=duty+1;
}
printf("ADC= %u, V= %f, duty= %u\r\n",medicion,voltaje,duty);

set_pwm1_duty(duty);

set_pwm2_duty(duty);

}
}

Saludos