Mostrar lectura adc en un lcd pero en barras

Hola que tal comunidad electronica !!!!! queria consultar por que hace muy poco que estoy con la programacion de microcontroladores y estoy tratando de hacer un medidor de nivel con un pic 16f877a y mostrarlo en un lcd 2 x 16 pero en forma de barras el tema es que busco en internet y todo lo que me sale es el ejemplo de neoteo (medidor de nivel-vumetro) que es perfecto el efecto que logra pero esta hecho en lenguaje basic y no entiendo nada yo uso el CCS . Si alguien me puede dar una mano con esto se lo agradeceria estoy encerrado en un bucle infinito y no puedo salir ja ja !!! . Un pequeño ejemplo , un link que no sea el de neoteo , algo para orientarme .Desde ya muchas gracias el foro esta buenisimo !!! saludos a todos !!! ...
 
Puedes crear un caracter especial que sea todos los puntos del "cuadradito" encendidos, y definir intervalos. Si tu ADC mide 1024, dividir para que salga en 14 o 16 trozos, e ir encendiendo un número determinado de veces el caracter especial según la lectura.

Exactamente algo así:

LCDPP12.jpg


Sólo tienes que averiguar cómo crear el caracter especial (yo solo sé en arduino...) y listo.
 
Última edición:
Hola que tal!
Yo estoy de acuerdo con jmthm, deberias usar el modulo ADC del PIC y representar el nivel de voltaje por medio de una barra o barras; por lo general estas barras no vienen el libreria de lcd.c, tienes que trabajar directamente sobre la GRAM de la lcd. Yo encontre alguna vez una aplicacion gratuita para generar caracteres especiales, creo que lo encontre en la pagina de todopic (adjunto una imagen). Seguro te puede servir para lo que quieres.
 

Adjuntos

  • Captura.PNG
    Captura.PNG
    25.9 KB · Visitas: 57
  • cgram_picture.rar
    32.8 KB · Visitas: 70
Hola amigos como estan !!! les cuento que al fin pude hacer el programa aunque soy muy novato en esto lo hice con las pocas herramientas que tengo en la cabeza por lo que lei y pude retener ja ja !!! pero en principio funciona, tal vez antes no me supe expresar bien con lo que queria hacer pero jmth me encendio la lamparita con lo que me dijo y queria mostrarles mi programa para ver que opinan ya que creo que debe haber otra forma de hacerlo mas facil pero bueno este es de nivel principiante , al grano lo que hice es un medidor de angulo de timon de un barco con un 0 al medio y 35º a babor y 35º a estribor basado en un potenciometro el cual leo con el adc del pic y lo transformo en las tan dichosas barras las cuales no fueron necesarias usar les adjunto el programa y les agradezco de antemano por sus opiniones y les estoy muy agradecido por contestarme antes Saludos!!!!!!
 

Adjuntos

  • prueba axiometro.txt
    2.9 KB · Visitas: 39
Código:
#include<16f88.h>
#device adc =10
#use delay (clock=4M)
#fuses XT,NOWDT
#include <lcd.c>


void main()
{
int16 q;
//float p;
  setup_adc_ports(sAN0|sAN1|sAN2|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_2);
lcd_init();

while(1){
set_adc_channel(0); //habilitacion canal 0
delay_us(20);

q = read_adc();     //lectura canal 0
//p =(float) read_adc() / 64; //conversion a tension

if (q<96&&q>0)
{

lcd_gotoxy(6,1);
printf(lcd_putc,"35\337er");
delay_ms(100);

lcd_gotoxy(8,2);
printf(lcd_putc,"|>>>>>>>>");
delay_ms(100);


}

if (q<160&&q>96)
{

lcd_gotoxy(6,1);
printf(lcd_putc,"30\337er");
delay_ms(100);

lcd_gotoxy(8,2);
printf(lcd_putc,"|>>>>>>> ");
delay_ms(100);


}

if (q<224&&q>160)
{

lcd_gotoxy(6,1);
printf(lcd_putc,"25\337er");
delay_ms(100);

lcd_gotoxy(8,2);
printf(lcd_putc,"|>>>>>>  ");
delay_ms(100);


}

if (q<288&&q>224)
{

lcd_gotoxy(6,1);
printf(lcd_putc,"20\337er");
delay_ms(100);

lcd_gotoxy(8,2);
printf(lcd_putc,"|>>>>>   ");
delay_ms(100);


}

if (q<352&&q>288)
{

lcd_gotoxy(6,1);
printf(lcd_putc,"15\337er");
delay_ms(100);

lcd_gotoxy(8,2);
printf(lcd_putc,"|>>>    ");
delay_ms(100);


}
if (q<416&&q>352)
{

lcd_gotoxy(6,1);
printf(lcd_putc,"10\337er");
delay_ms(100);

lcd_gotoxy(8,2);
printf(lcd_putc,"|>>     ");
delay_ms(100);


}

if (q<480&&q>416)
{

lcd_gotoxy(7,1);
printf(lcd_putc,"5\337er");
delay_ms(100);

lcd_gotoxy(8,2);
printf(lcd_putc,"|>      ");
delay_ms(100);


}
//**************a la via**************
if  (q>480&&q<544)
{

lcd_gotoxy(8,1);
printf(lcd_putc,"\f       0");
delay_ms(100);


lcd_gotoxy(1,2);
printf(lcd_putc,"       |        ");
delay_ms(100);
}
//*****************************************
if (q>544&&q<608)
{


lcd_gotoxy(7,1);
printf(lcd_putc,"5\337br");
delay_ms(100);

lcd_gotoxy(1,2);
printf(lcd_putc,"      <|       ");
delay_ms(100);
}

if (q>608&&q<672)
{


lcd_gotoxy(6,1);
printf(lcd_putc,"10\337br");
delay_ms(100);

lcd_gotoxy(1,2);
printf(lcd_putc,"     <<|        ");
delay_ms(100);
}
if (q>672&&q<736)
{


lcd_gotoxy(6,1);
printf(lcd_putc,"15\337br");
delay_ms(100);

lcd_gotoxy(1,2);
printf(lcd_putc,"    <<<|        ");
delay_ms(100);
}
if (q>736&&q<800)
{


lcd_gotoxy(6,1);
printf(lcd_putc,"20\337br");
delay_ms(100);

lcd_gotoxy(1,2);
printf(lcd_putc,"   <<<<|        ");
delay_ms(100);
}

if (q>800&&q<864)
{


lcd_gotoxy(6,1);
printf(lcd_putc,"25\337br");
delay_ms(100);

lcd_gotoxy(1,2);
printf(lcd_putc,"  <<<<<|        ");
delay_ms(100);
}

if (q>864&&q<928)
{


lcd_gotoxy(6,1);
printf(lcd_putc,"30\337br");
delay_ms(100);

lcd_gotoxy(1,2);
printf(lcd_putc," <<<<<<|        ");
delay_ms(100);
}

if (q>928&&q<992)
{


lcd_gotoxy(6,1);
printf(lcd_putc,"35\337br");
delay_ms(100);

lcd_gotoxy(1,2);
printf(lcd_putc,"<<<<<<<|        ");
delay_ms(100);
}


}
}
 
Pues muy bien si funciona correctamente, por supuesto se puede depurar. Por ejemplo evitar los if y hacerlo todo en un for:

para las barritas a la derecha:
- lee el adc
- determina el numero de barritas que quieres
- haz un for que empiece desde 0 hasta el numero de barritas
- dentro, que imprima una barrita y se mueva un caracter a la derecha cada vez que se repite...

Y similar para las barritas a la izquierda. Supongo que sería una buena forma de hacerlo
 
Hola jmth que tal !!! sabes que estoy probando lo que me dijiste de hacer (que en principio me parecia claro ) todo en un for pero no me doy cuenta como es..., estoy re mareado , te agradeceria si me das una ayuda mas clara ya que soy muy principiante , un ejemplo algo como orientarme , no se como hacer para leer que si se decrementa o si se incrementa la lectura del adc me muestre las barras sin tener que colocar tantos if con tantas especificaciones,Saludos !!!!!!!!!
 
un ejemplo algo como orientarme, no sé cómo hacer para leer que si se decrementa o si se incrementa la lectura del adc me muestre las barras sin tener que colocar tantos if con tantas especificaciones.
Este ejemplo que adjunto escrito en C, está muy sencillo y tal vez te pueda servir para lo que quieres hacer.
El programa escribe caracteres personalizados en la CGRAM de la pantalla para ser usados como una barra.

Se toma el valor del ADC a 8 bits y se hace incrementar o decrementar la barra conforme al valor leído.
También se muestra un porcentaje de 0 a 100 para determinar la lectura del ADC.
Este ejemplo puede servir para un vumeter e indicar el nivel del volumen.

El procedimiento usado en este ejemplo es para variaciones algo lentas de la lectura del ADC.
Para mejorar la respuesta se pueden agregar mas espacios en blanco y así evitar que queden caracteres en la pantalla.
En el código se muestra en donde se deben agregar los espacios en blanco.

Espero te sirva. Suerte.
 

Adjuntos

  • 16F88 Vumeter.rar
    28.3 KB · Visitas: 94
hola D@rkbytes como estas !!! te agradezco mucho por responder y por el ejemplo que me mostras que ya me tiro una idea, pero quise probar el programa que me pasaste y me marca 5 errores
lcd_set_cgram_char(0,cgram0);
lcd_set_cgram_char(1,cgram1);
lcd_set_cgram_char(2,cgram2);
lcd_set_cgram_char(3,cgram3);
lcd_set_cgram_char(4,cgram4);
estoy compilando con ccs .Sabes que puede ser ?
te agradezco mucho tu colaboracion .Saludos !!!!!
 
Quise probar el programa que me pasaste y me marca 5 errores.
lcd_set_cgram_char(0,cgram0);
lcd_set_cgram_char(1,cgram1);
lcd_set_cgram_char(2,cgram2);
lcd_set_cgram_char(3,cgram3);
lcd_set_cgram_char(4,cgram4);
Estoy compilando con ccs. ¿Sabes que puede ser ?
Se debe a que estás usando una versión inferior de PCWHD Compiler de CCS a la cual yo usé (v 5.010)
Versiones inferiores a la 4.140 no tienen actualizada la librería LCD.C
Prueba con la librería que adjunto y si sigues teniendo problemas debes actualizar el compilador.

Saludos.
 

Adjuntos

  • LCD.rar
    3.5 KB · Visitas: 56
Hola. ¿Qué tal?
Te quería agradecer D@rKbytes por el programa que me enviaste, está muy bueno.
Lo pude hacer funcionar con la librería que me pasaste y me pareció buenísimo, pero sigo tratando de darle forma a este programita que hice y tengo el siguiente problema.
Les cuento a ver si alguien me puede ayudar lo que por ahí para ustedes es muy fácil o sencillo se ve que para mi es todo lo contrario ja ja.

Al grano: Como ya les conté, el programa marca el angulo que se mueve el timón de un barco, mediante un potenciómetro entro en el canal adc del pic y represento tanto en símbolos como en grados la posición del cursor del potenciómetro.
Hasta acá todo funciona perfectamente el problema surge que aunque el potenciómetro no llegue de 0 a 5 volts (osea de 0 a 1023 en el adc ) la escala representada en la pantalla si tiene que llegar a los máximos para los dos lados ( la escala está representada con un 0 al centro y aumentando cada 5º hasta un máximo de 35º tanto a un lado como al otro )

El tema es que al instalar esto yo tengo que colocar el potenciómetro al centro donde me marcara el 0 y luego tendría que poder elegir una escala que cumpla con las condiciones de llegar tanto a un extremo como al otro marcando los 35º finales sin importar si el potenciómetro llega tanto a 0 como a 5 v y lo tengo que poder hacer con el programa.

Lo que no sé si se puede hacer un par de tablas del estilo del programa que hice y seleccionar la que más se acerque al rango de escala que necesito, ya que no necesito tanta precisión y con tres o cuatro tablas ya se adaptaría a todas las posibilidades.
Espero haberme expresado correctamente, si no pregúntenme a ver si los puedo orientar mas a mi problema y ojala me puedan ayudar.

Desde ya muchas gracias a todos.
Saludos!!!!!
 
Última edición por un moderador:
Hola amigos!!! Vuelvo al tema ya que estuve trabajando bastante en él y lo he modificado bastante, tanto que lo de la representación de la lectura en barras ya no es un problema por que decidí usar un caracter convencional ,a pesar que me sirvieron mucho sus consejos sobre como escribir en la cgram y aprendí algo mas, lo cual estoy muy agradecido .
Bueno el tema ahora es que decidí hacer regulaciones a las escalas, es decir usar 4 canales adc con uno fijar el parámetro de uno de los topes, con otro regular el centro, con otro el otro tope y con el último el cursor que es el que lee los datos e imprime en pantalla.
Pero lo que me está sucediendo es que me lee solo los datos de un tope y el del centro, es como si no se estuviese cumpliendo la función que hace las cuentas, no le encuentro cual puede ser el error.
Adjunto el nuevo programa a ver si alguien me puede ayudar.

Desde ya muchas gracias.

PD: Solo para reducir el programa y sea más entendible, puse la lectura de un solo lado.
Código:
#include<16f88.h>
#device adc =10
#use delay (clock=4M)
#fuses XT,NOWDT
#include <lcd.c>

                     
int16 a=0,b=0,c=0,d=0,e=0,f=0;
int16 cursor=0,toper=0,topbr=0,cero=0;
int16 resultadoEr =0;
int16 calculoBandaEr(int16 cero,int16 toper);


void main()
{
   
     setup_adc_ports(sAN0|sAN1|sAN2|VSS_VDD);// habilitacion de canales adc 
     setup_adc(ADC_CLOCK_DIV_2);             
    
     lcd_init();
   
while(1){

    set_adc_channel(0);
   delay_us(20);           //parametro que se va a fijar cuando se instale el instrumento 
   cero=read_adc();     // y no se volvera a tocar
   //****************************************************************
  
   set_adc_channel(1);
   delay_us(20);           //parametro que se va a fijar cuando se instale el instrumento                          
   toper=read_adc();    //y no se volvera a tocar
   
   int16 resultadoEr= calculoBandaEr(cero,toper);
   
   a=resultadoEr*2;
   b=resultadoEr*3;
   c=resultadoEr*4;
   d=resultadoEr*5;  
   e=resultadoEr*6;  
   f=resultadoEr*7;
   
   //*********************************************************
   set_adc_channel(2); //
   delay_us(20);
   cursor=read_adc();     //lectura canal 2 a variable cursor 
   
   //********************************************* 


if(cursor==toper)
  {
  output_high(PIN_a3);//led************************
  lcd_gotoxy(1,1);
  printf(lcd_putc,"      35\337er  top ");
  lcd_gotoxy(1,2);
  printf(lcd_putc,"       |>>>>>>>>");

  }
 
if (cursor==a)
{

lcd_gotoxy(1,1);
printf(lcd_putc,"      30\337er     ");
lcd_gotoxy(1,2);
printf(lcd_putc,"       |>>>>>>> ");

}
if(cursor==b)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"      25\337er     ");
lcd_gotoxy(1,2);
printf(lcd_putc,"       |>>>>>>  ");
}
if (cursor==c)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"      20\337er     ");
lcd_gotoxy(1,2);
printf(lcd_putc,"       |>>>>>   ");
}

if (cursor==d)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"      15\337er    ");
lcd_gotoxy(1,2);
printf(lcd_putc,"       |>>>    ");
}
if (cursor==e)
{

lcd_gotoxy(1,1);
printf(lcd_putc,"      10\337er    ");
lcd_gotoxy(1,2);
printf(lcd_putc,"       |>>     ");
}
if(cursor==f)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"       5\337er    ");
lcd_gotoxy(1,2);
printf(lcd_putc,"       |>       ");
}

if (cursor==cero)
{
  lcd_gotoxy(1,1);
  printf(lcd_putc,"       0        ");
  lcd_gotoxy(1,2);
  printf(lcd_putc,"       |        ");
}

 
 
}

}
  int16 calculoBandaEr(int16 cero, int16 toper){
int16 resultadoEr =0;
 
    resultadoEr=(cero-toper)/7;
   return resultadoEr;
   
 }
 
Última edición por un moderador:
Bueno, solucionados los inconvenientes, ya está el programa funcionando, al menos en la simulación.
Ahora lo voy a hacer en físico y acá va una pregunta mas:
Para hacer las regulaciones de las escalas tenía pensado usar preset multivueltas de 5K.
¿Estará bien con ese valor? Es para entrar a cada canal adc del pic.
Agradezco a todos los que me ayudaron. (y)

Aquí va el código completo. Saludos !!!!
Código:
#include<16f88.h>
    #device adc =10
    #use delay (clock=4M)
    #fuses XT,NOWDT
    #include <lcd.c>
                       
    int16 calculoBandaEr(int16 cero,int16 toper);
    int16 z=0, a=0,b=0,c=0,d=0,e=0,f=0;
     
    int16 calculoBandaBr(int16 cero, int16 topbr);
    int16 g=0,h=0,i=0,j=0,k=0,l=0,m=0;
     
    int16 cursor=0,toper=0,topbr=0,cero=0;
    int16 resultadoEr =0,resultadoBr =0;
     
     
    void main()
    {
     
      setup_adc_ports (sAN0|sAN1|sAN2|sAN3|VSS_VDD);
      setup_adc (ADC_CLOCK_DIV_8);
      set_tris_a(0b00001111);
       //*************************************************************************
     
      set_adc_channel (3);
      delay_us (20);
      cero = read_adc();
    //***************************************************************************
         
      set_adc_channel (0);
      delay_us (20);
      topbr = read_adc ();
      resultadoBr = calculoBandaBr(topbr,cero);//( topbr -cero ) / 8;
      g = resultadoBr + cero;
      h =cero+resultadoBr+resultadoBr;
      i =cero+(resultadoBr*3);
      j =cero+(resultadoBr*4);
      k =cero+(resultadoBr*5);
      l =cero+(resultadoBr*6);
      m =cero+(resultadoBr*7);
     
     
      set_adc_channel (1);
      delay_us (20);
      toper = read_adc ();
     
      resultadoEr = calculoBandaEr (cero, toper);
      z=  resultadoEr + toper;
      a = (resultadoEr * 3)+toper;
      b =( resultadoEr * 4)+toper;
      c =( resultadoEr * 5)+toper;
      d =( resultadoEr * 6)+toper;
      e =( resultadoEr * 7)+toper;
      f =( resultadoEr * 8)+toper;
     
           
      lcd_init ();
     
      WHILE (1) {    
         
         //*********************************************************
         set_adc_channel (2);
         delay_us (20);
         cursor = read_adc ();
         
         //*********************************************
           IF (cursor >0 && cursor<= toper)
         {
       
           // output_high (PIN_a3); //led************************
            lcd_gotoxy (1,1) ;
            printf (lcd_putc, "      40\337er top ");
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>>>>>>>>");
         }
           IF (cursor > toper && cursor <=z)
         {  
            lcd_gotoxy (1,1) ;
            printf (lcd_putc, "      35\337er     ");
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>>>>>>>>");
         }
     
         IF (cursor >z && cursor <a)
         {
       
            lcd_gotoxy (1, 1) ;
            printf (lcd_putc, "      30\337er     ") ;
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>>>>>>> ");
         }
       
         IF (cursor >a &&cursor<b)
         {
     
            lcd_gotoxy (1, 1) ;
            printf (lcd_putc, "      25\337er     ") ;
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>>>>>> ");
         }
     
         IF (cursor >b && cursor<c)
         {
       
            lcd_gotoxy (1, 1) ;
            printf (lcd_putc, "      20\337er     ") ;
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>>>>>   ");
         }
     
         IF (cursor >c && cursor<d)
         {
       
            lcd_gotoxy (1, 1) ;
            printf (lcd_putc, "      15\337er     ");
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>>>        ");
         }
     
         IF (cursor >d && cursor<e)
         {
       
            lcd_gotoxy (1, 1) ;
            printf (lcd_putc, "      10\337er     ");
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>>         ") ;
         }
     
         IF (cursor>e&&cursor<f)
         {
       
            lcd_gotoxy (1, 1) ;
            printf (lcd_putc, "       5\337er     ");
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |>         ");
         }
    //*****************************************************************************
         IF (cursor == cero)
         {
       
            lcd_gotoxy (1, 1) ;
            printf (lcd_putc, "       0        ");
            lcd_gotoxy (1, 2) ;
            printf (lcd_putc, "       |        ");
         }
    //*****************************************************************************      
      if (cursor>cero&&cursor<g)
          {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"       5\337br  ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"      <|       ");
     
      }
     
      if (cursor>g&&cursor<h)
      {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"      10\337br   ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"     <<|        ");
     
      }
      if (cursor>h&&cursor<i)
      {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"      15\337br   ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"    <<<|        ");
     
      }
      if (cursor>i&&cursor<j)
      {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"      20\337br    ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"   <<<<|        ");
     
      }
      if (cursor>j&&cursor<k)
      {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"      25\337br    ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"  <<<<<|        ");
     
      }
     
      if (cursor>k&&cursor<l)
      {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"      30\337br    ");
      lcd_gotoxy(1,2);
      printf(lcd_putc," <<<<<<|        ");
     
      }
     
      if (cursor>l&&cursor<m)
      {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"      35\337br      ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"<<<<<<<|        ");
     
      }
     
      if (cursor>m&&cursor<=topbr)
      {
    //  output_high(PIN_a4);//led************************
     
      lcd_gotoxy(1,1);
      printf(lcd_putc,"top   40\337br      ");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"<<<<<<<|        ");
     
    }
         
      }
    }
     
     
    //funciones*********************************************
     
    int16 calculoBandaEr(int16 cero, int16 toper)
    {
     
      RETURN (cero - toper) / 8;
    }
    int16 calculoBandaBr(int16 topbr,int16 cero )
    {
     
      RETURN ( topbr -cero ) / 8;
    }
 
Última edición por un moderador:
Atrás
Arriba