# 16f877a. Defino ADC de 3 canales, solo funciona uno.



## RobertoIG (Oct 25, 2010)

Buenas, 

les cuento que estoy implementando 3 entradas analógicas en un pic 16f877a, las cuales convierten la información a digital en 8 bits.

El código me funciona bien al simularlo en proteus 7.5. El problema es que al implementarlo en la protoboard solo funciona la conversión del primer canal (RA0) y el resto es una salida (!!!) de 0 digital (0,1 volt aprox). 
Le he dado mil vueltas y no entiendo qué puede ser. ¿alguna idea?

Este es el código (omití las partes que funcionan bien, son solo "if" y "else").



> #include<16f877a.h>
> #device ADC=8
> #fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
> #use delay(clock=4000000)
> ...



He probado las declaraciones RA0_RA1_RA3_ANALOG, ALL_ANALOG (aunque no me sirve, pero para ver si cambiaba algo). También probé distintos delays, usualmente 10 o 20us y distintos clocks para el ADC, como ADC_CLOCK_DIV_8.
En todos los casos, el pic hace el mismo error.


Cualquier ayuda es bienvenida. Saludos.


----------



## El nombre (Oct 25, 2010)

prueba con 

setup_adc_ports( RA0_RA1_RA3_ANALOG );​


----------



## RobertoIG (Oct 25, 2010)

El nombre dijo:


> prueba con
> 
> setup_adc_ports( RA0_RA1_RA3_ANALOG );​



gracias por la respuesta. 
Eso es lo primero que intenté, de hecho, solo al final decidí probar los otros modos de setup_adc_ports.

Olvidé mencionar que esto se ha probado en 2 pics, ambos hacen lo mismo.


----------



## El nombre (Oct 25, 2010)

prueba dando mas tiempo a la conversion
Y digo yo? Aver si el error lo tienes en el circuito. Has medido la tensión que tienes en la patilla?


----------



## RobertoIG (Oct 25, 2010)

Intentaré darle más, pero si en general se usa 10-50us, ahora con 10ms debería andar más que bien, considerando que además la impedancia es muy baja.

El circuito está bien, porque antes programaba el pic con puertos digitales y todo andaba bien, ahora cambié a esos análogos, le conecto las entradas análogas (resistencia variable, sensor infrarrojo, etc) y no funciona.

Ya medí voltajes, como mencioné en el primer párrafo, los pines RA1 y RA3 tiene poco más de cero volts (~0,1V) y están fijos, independiente de lo que conecte ahí. Todo lo demás del pic funciona bien.


----------



## FBustos (Oct 25, 2010)

Los puertos analogos deben funcionar como entrada.

Prueba declarando las variables como tipo float.
--------

set_adc_channel(3); --->> dede ser set_adc_channel(2)
   delay_ms(20);
   giroiz = read_adc();


----------



## RobertoIG (Oct 25, 2010)

Gracias por sus sugerencias.


dj pipe dijo:


> Los puertos analogos deben funcionar como entrada.
> 
> Prueba declarando las variables como tipo float.
> --------
> ...


Sé que deben funcionar como entrada, pero ahora se comportan como salida. RA1 y RA3 están pegados en 0.

Creo que el _set_adc_channel(2)_ haría referencia a RA2 y ese no está definido como puerto análogo. 
¿acaso los puertos análogos se numeran como puerto 0 el primero, puerto 1 el segundo, puerto 2 el tercero..etc, independiente del número de pin?


----------



## FBustos (Oct 25, 2010)

Se enumeran justo como lo has dicho, independiente si es rbx o rcx, etc..


----------



## RobertoIG (Oct 25, 2010)

Gracias. Mañana lo probaré (debo hacerlo en el lab de la universidad) y les cuento.
Saludos.


----------



## RobertoIG (Oct 26, 2010)

No funciona, de hecho, al simular envía error. Al implementar en protoboard se comporta igual que antes.


----------



## FBustos (Oct 26, 2010)

Hola, te cuento que lo estoy simulando y anda bien.. Sube el esquema de tu simulacion...


----------



## El nombre (Oct 26, 2010)

RobertoIG dijo:


> Ya medí voltajes, como mencioné en el primer párrafo, los pines RA1 y RA3 tiene poco más de cero volts (~0,1V) y están fijos, independiente de lo que conecte ahí. Todo lo demás del pic funciona bien.


 Si tienes fijo esa tensión, con el tester, Tienes mal la placa. Revisa cortos.


----------



## RobertoIG (Oct 27, 2010)

El nombre dijo:


> Si tienes fijo esa tensión, con el tester, Tienes mal la placa. Revisa cortos.



Aún no hago la placa. Esto es en protoboard y no está malo, porque cuando tenía el puerto A solo como I/O digital todos los pines funcionaban bien.



dj pipe dijo:


> Hola, te cuento que lo estoy simulando y anda bien.. Sube el esquema de tu simulacion...



No me expliqué bien, lo siento. La simulación corre, pero proteus me indica que el pin RA2 no es A/D. Por lo tanto, el set_adc_channel(2) está llamando a RA2 y no a RA3.

La simulación es algo bien simple. adjunto imagen.

ya me estoy rindiendo con esto, ya he probado 3 pics 16f877a y todos hacen lo mismo.
estoy pensando usar el 16f628a e intentar hacer algo con los comparadores que trae


----------



## Herly (Nov 28, 2015)

A mi me paso igual, llevo poco en el tema de los microcontroladores.

Mi solución fue repetir el código, pues el PIC no puede leer ambos canales a la vez, pero por velocidad de trabajo pareciera que si.
Por lo tanto, aumenté la frecuencia del cristal y funcionó muy bien.

Aquí les dejo el código que usé.


```
void main ()
{  
  float  temp; //Variable con decimales llamada temp
  //delay_ms(2000);  // Al encender el PIC espero 2 segundos a que estabilice el voltaje
  output_low(pin_A1); // arranco el pin de salida en bajo
  
  Setup_adc_ports(sAN2 | sAN0);    //pongo como analogo el puerto solo el pin NA0 
  setup_adc(adc_clock_internal); //selecciono reloj interno para conversion
  

while (true)
{
set_ADC_Channel(0);

temp=read_adc()/2; //lee el conversor ADC se lo asigna a la variable temperatura
delay_us(20);
//************************si la temperatura es mayor que 35
if(temp>=38)  // (Si temp es mayor o igual a 38) /(if(temperatura>=35&&temperatura<=40) :siesta entre 35 y 40)
{

output_high(pin_A1);  //enciende el ventilador
delay_ms(3000); //Espero 1 minuto para evitar variaciones al encender y apagar el ventilador

}
//*********si la temperaturaes correcta o menor de 35
else
{
output_low(pin_A1);  //Apaga el ventilador
}

//******************************************************************************
set_ADC_Channel(2);

temp=read_adc()/2; //lee el conversor ADC se lo asigna a la variable temperatura
delay_us(20);
//************************si la temperatura es mayor que 35
if(temp>=38)  // (Si temp es mayor o igual a 38) /(if(temperatura>=35&&temperatura<=40) :siesta entre 35 y 40)
{

output_high(pin_A1);  //enciende el ventilador
delay_ms(3000); //Espero 1 minuto para evitar variaciones al encender y apagar el ventilador

}
//*********si la temperaturaes correcta o menor de 35
else
{
output_low(pin_A1);  //Apaga el ventilador
}
}
```
Este proyecto consiste en leer dos sensores de temperatura LM35 con un PIC12F675, y si la temperatura es igual o mayor a 38°C, enciende un ventilador.


----------

