Analog Input + PIC16F1827

Estoy haciendo un programa en el que dependiendo de un valor de una LDR se enviará por el puerto serial un comando específico

Para "supervisar" el comando que se ha de enviar, estoy utilizando una serie de cinco LEDs que se prenderán en diferentes rangos

Primero dejo el programa:

Código:
#include <16f1827.h>
#use     delay (internal = 32MHz)
#use RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B1, stream=com,errors)
 
#define NIVEL_0         PIN_B6
#define NIVEL_1         PIN_B7
#define NIVEL_2         PIN_B3
#define NIVEL_3         PIN_B5
#define NIVEL_4         PIN_B4

#BYTE TRISA = 0x85 

#define LDR       PIN_A0
 
void main(){
   int nivel_luz;
   int luz_ant;
   int porc;
   int checksum;
   int trama[23]={0x7E, 0x00, 0x13, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0x20, 0x83, 0x08, 0x00, 0x48};
   
   setup_adc_ports(LDR|VSS_VDD);         //Canal 0 analógico
   setup_adc(ADC_CLOCK_INTERNAL);
   
   nivel_luz = read_adc();
   luz_ant = nivel_luz;
   while(TRUE){
      set_adc_channel(0);        //Habilitación canal0
      delay_us(20);
      nivel_luz = read_adc();
      delay_us(20);
      // RANGOS:
      // VREF = 3 V
      // LUZ MÁXIMA: 0.60 V -> (0.60*255)/3 = 51
      // LUZ MÍNIMA: 1.23 V -> (1.23*255)/3 = 104
      if(nivel_luz < 50){        // V < 0.58V
         output_low (NIVEL_0);
         output_low (NIVEL_1);
         output_low (NIVEL_2);
         output_low (NIVEL_3);
         output_low (NIVEL_4);
         delay_ms(20);
         porc = 0x00;
         checksum = 0x48;
      }
      else if(nivel_luz > 51 && nivel_luz < 65){         // 0.6V < V < 0.76V 
         output_high (NIVEL_0);
         output_low (NIVEL_1);
         output_low (NIVEL_2);
         output_low (NIVEL_3);
         output_low (NIVEL_4);
         delay_ms(20);
         porc = 0x14;
         checksum = 0x34;
      }
      else if(nivel_luz > 64 && nivel_luz < 80){         // 0.75V < V < 0.94V 
         output_high (NIVEL_0);
         output_high (NIVEL_1);
         output_low (NIVEL_2);
         output_low (NIVEL_3);
         output_low (NIVEL_4);
         delay_ms(20);
         porc = 0x28;
         checksum = 0x20;
      }
      else if(nivel_luz > 79 && nivel_luz < 95){         // 0.92V < V < 1.11V 
         output_high (NIVEL_0);
         output_high (NIVEL_1);
         output_high (NIVEL_2);
         output_low (NIVEL_3);
         output_low (NIVEL_4);
         delay_ms(20);
         porc = 0x3C;
         checksum = 0x0C;
      }
      else if(nivel_luz > 94 && nivel_luz < 105){         // 1.10V < V < 1.23V 
         output_high (NIVEL_0);
         output_high (NIVEL_1);
         output_high (NIVEL_2);
         output_high (NIVEL_3);
         output_low (NIVEL_4);
         delay_ms(20);
         porc = 0x50;
         checksum = 0xF8;
      }
      else if(nivel_luz > 104){         // 1.22V < V
         output_high (NIVEL_0);
         output_high (NIVEL_1);
         output_high (NIVEL_2);
         output_high (NIVEL_3);
         output_high (NIVEL_4);
         delay_ms(20);
         porc = 0x64;
         checksum = 0xE4;
      }
      if(luz_ant-5 < nivel_luz < luz_ant+5){delay_ms(50);}
      else{
         trama[21] = porc;
         trama[22] = checksum;
         for(int pos=0;pos<=22;pos++){
            putc(trama[pos],com);
            delay_ms(500);
         }
      luz_ant = nivel_luz;
      }
   }
}

Y dejo también un esquema en Proteus

16bj214.jpg


No me interesa que en Proteus los valores correspondan a los del programa o que los LEDs no enciendan como deberían, porque esta parte está funcionando correctamente en la vida real, los cinco LEDs se pueden prender o apagar dependiendo si se tapa más o menos la LDR

La simulación la estoy utilizando para probar la comunicación serial, pero ni en la vida real ni en Proteus funciona correctamente y se generan los siguientes errores:

  • ADC conversion started before 'wait' time has expired followig previous conversion or channel charge
  • PORTA<0> is not configured as an analog input

Lo que no entiendo es por qué dice que no está configurado como una entrada análoga y sí varía la cantidad de LEDs que se encienden y apagan :confused::confused::confused:
 
Los errores sobre el ADC se deben a lo siguiente:
1.- Al inicio del bucle main no estás indicando que canal se debe usar.
2.- La configuración de setup_adc_ports() no es válida.
3.- El periodo de tiempo para la conversión es muy corto. Usa 50 us. (Es un tiempo base estándar)

Estás iniciando de esta forma:
Código:
   setup_adc_ports(LDR|VSS_VDD);         //Canal 0 analógico
   setup_adc(ADC_CLOCK_INTERNAL);
   
   nivel_luz = read_adc();
Y debe ser de esta forma:
Código:
   setup_adc_ports(sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);
   delay_us(50);
   
   nivel_luz = read_adc();
   delay_us(50);
La variable que asignas a LDR = PIN_A0, no es un valor que el compilador asuma para el canal 0.
PIN_A0 = 96 y sAN0 = 0x100

Tampoco es necesario que uses un Stream para la comunicación RS-232
Si vas a usar el módulo EUSART, con tan sólo declarar lo siguiente es suficiente.
#use RS232 (UART1)
Al usar esto el compilador realiza una configuración por defecto: 9600, N, 8, 1
9600 Bps. Sin paridad, 8 Bits y 1 Bit de parada.
Por lógica también asume que debe usar los pines correspondientes; Tx y Rx.

Si no transmite los datos, debe ser porque no se está cumpliendo la condición y debes entrar en modo de depuración para encontrar el por qué no se cumple el envío.

Algo que veo muy mal, es utilizar un retardo de 500 ms en cada envío, y si realizas 22 envíos consecutivos, la transmisión de datos tardará más de 11 segundos en completarse. :eek:
 
Última edición:
Atrás
Arriba