TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: ncoliv en 20 de Agosto de 2008, 20:13:37

Título: inicio
Publicado por: ncoliv en 20 de Agosto de 2008, 20:13:37
Hola amigos del foro. quiero implemetar un adquisidor de datos para mostralos en una pc al mismo tiempo que estan siendo leidos por el micro. Quiero emplear un PIC 16f873A, la señal es analógica y en principio sería una obtenida de un pote ( entre 0 y 5 Volts). Desearía saber como tengo que configurar el micro donde tengo que alojar los valores leidos y en fin como sería mas o menos el programa. desde ya muchas gracias. Lo que deseo hacer no parece tan complicado. en caso contrario algun link para estudiar el tema.
Muchas gracias   
Título: Re: inicio
Publicado por: MLO__ en 21 de Agosto de 2008, 12:28:34
Hola.

Revisa aqui 7 segmentos con int Timer0 (http://www.todopic.com.ar/foros/index.php?topic=21738.0). Esta todo lo que necesitas.

Saludos
Título: Re: inicio
Publicado por: ncoliv en 21 de Agosto de 2008, 13:58:05
GRacias MLO estudiaré el programita. Quisiera colaboración con este que conseguí, es practicamente lo que quiero hacer . resulta que cuando lo compilo me arroja 3 errores en el driver LCD.c y ellos son lo siguiente
*** Error 12 "C:\ARCHIV~1\PICC\drivers\lcd.c" Line 91(29,30): Undefined identifier  -- set_tris_d
*** Error 12 "C:\ARCHIV~1\PICC\drivers\lcd.c" Line 103(30,31): Undefined identifier  -- set_tris_d
*** Error 12 "C:\ARCHIV~1\PICC\drivers\lcd.c" Line 133(28,29): Undefined identifier  -- set_tris_d
el programa estaba para un f877a la unica modificación que hice es cambiar #include <16F873a.h>
Que puede estar pasando?
muchas gracias
Título: Re: inicio
Publicado por: firepic en 21 de Agosto de 2008, 14:12:25
Saludos!

Es muy sencillo ncoliv, aunque tal vez cuando uno comienza no sean tan obvios los errores, así que no te preocupes.

El micro que tú estás usando, con el que estás compilando el programa, no posee PortD, así que en esas líneas donde aparece el TRISD (el registro que configura portd como entrada o salida) te da el error. Simplemente quita esas líneas y si no hay otro error debe compilar bien.

Por cierto, te recomiendo el Microcursillo en C, que está en el subforo de C en los "Hilos destacados"... allí encontraras muchos ejemplos, entre ellos enviar datos a la PC, leer el puerto analógico, etc...busca y encontrarás lo que necesitas.
Si te trancas aquí se te ayudará.

Ok nos leemos!  :mrgreen:
Título: Re: inicio
Publicado por: MLO__ en 21 de Agosto de 2008, 22:29:07
Hola.

Debes colocar antes del #include "LCD.C" : #define use_portb_lcd TRUE y listo, queda activado el puertoB para la LCD.

Saludos
Título: Re: inicio
Publicado por: firepic en 22 de Agosto de 2008, 12:27:25
Tienes razón Miguel! No me había fijado que el error está en el archivo driver LCD.C  :D  :D  :D
Eso me pasa por no leer bien, yo nada más me fijé en lo que decía el error.
O sea que el LCD.C configura por defecto el PORTD para el LCD no? Eso sí no lo sabía, yo siempre uso el flexlcd.c  :)
Ok saludos, nos leemos!  :mrgreen:
Título: Re: inicio
Publicado por: ncoliv en 22 de Agosto de 2008, 18:13:59
muchas gracias por las respuestas, compilo con esa modificación y da 0 error y 0 warning Hast aahra todo oK! .Siguiendo con esta modificación las conexiones del puerto B al lcd serían como las del puerto D ?serian de esta forma :
B0----E
B1----RS
B2----RW
B4----D4
B5----D5
B6----D6
B7----D7
Título: Re: inicio
Publicado por: MLO__ en 23 de Agosto de 2008, 15:49:25
Hola.

Si amigo Fire, el LCD.C asigna la estructura al puerto D, pero es muy simple modificarla, claro que trabaja con el puerto completo.

Ncoliv, en la libreria estan las conexiones ... la estructura se define:
Código: C#
  1. struct lcd_pin_map {                
  2.            BOOLEAN rs;               //pin 0 del puerto
  3.            BOOLEAN rw;              //pin 1 del puerto, etc
  4.            BOOLEAN enable;
  5.            BOOLEAN unused;
  6.            int     data : 4;
  7.         } lcd;

de esta manera tu puedes modificar los pines de asignacion para la LCD, pero ten en cuenta que solo pueden estar en el mismo puerto.

Saludos
Título: Re: inicio
Publicado por: ncoliv en 23 de Agosto de 2008, 20:35:57
Ok, muchachos, hice las conexiones segubn las describí y y anda bárbaro, muestro el valor de voltaje del cursor del pote en el lcd . les paso el programa con las modificaciones para el pic 16f8773A.
#include <16F873a.h>
#include <STDLIB.H>

#use delay(clock=4000000)
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#byte portb=6
#define use_portb_lcd TRUE
#include <lcd.c>

void main(void)
{
float const resoluc=5.0/256.0;
int8 valor=0;
float kk=0;


set_tris_b(0x00);
set_tris_a(0xFF);
portb=0x00;

lcd_init();
lcd_gotoxy(1,1);

setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(20);

while(true)
{

valor=read_adc();
kk=valor*resoluc;
lcd_gotoxy(1, 1);
printf(lcd_putc,"fconv: %d",valor);
lcd_gotoxy(1, 2);
printf(lcd_putc,"medida: %f",kk);
delay_ms(500);
}
}
 
Surge otra consulta . Que tendría que agregar en el programa para que se muestre el valor medido (KK) en la PC alguna idea tengo pero como lo harían UDS.
 
Título: Re: inicio
Publicado por: MLO__ en 24 de Agosto de 2008, 12:23:41
Hola.

Pues debes usar alguno de los puertos del PC para comunicarse con el micro. Se usa mucho el puerto serial, para esto debes colocar:
Código: [Seleccionar]
#use rs232(baud=9600, xmit=pin_b6, rcv=pin_b7, parity=N, bits=8)

y asignar la variable de salida con:
Código: [Seleccionar]
printf("%f [v]", kk);

La configuracion en el PC del hyperterminal del puerto debe ser la misma que la del micro.

Saludos
Título: Re: inicio
Publicado por: ncoliv en 25 de Agosto de 2008, 16:22:40
Gracias MLO, lo probaré. Hasta ahora todo marcha a la perfección, de a poco va tomando color. Tengo una pregunta. El PIC 16F873A tiene ADC 5 canales de 10bits cada uno. En el programa que les envio la resolución la da la cuenta  5volts/ 256. estos 256 salen de 2 a la 8. si divido por 1024 que correspondería a 2 a la 10 tendría que realizar alguna modificación en las  variables del programa. De hecho hice este ccambio y no tengo la maxima excursión de tensión en el pote. solo veo en el lcd 1,5 cuando tengo el pote en su recorrido total.
Título: Re: inicio
Publicado por: MLO__ en 25 de Agosto de 2008, 17:58:17
Hola.

El numero correspondiente a la conversion AD esta entre 0 y 1024 (2^n), si tu Vref es 5v, la resolucion sera de 4.88mV. Para convertir el valor binario al analogico nuevamente para visualizarlo, debes multiplicar esa resolucion por el valor leido de la conversion.

Hay que colocar al inicio:
Código: [Seleccionar]
#device adc=10

Para que las conversiones sean a 10 bits y la variable donde guardas la conversion debe ser de mas de 8 bits, asi que valor debe ser un int16.

Saludos.
Título: Re: inicio
Publicado por: ncoliv en 25 de Agosto de 2008, 23:32:34
Ok. Gracias por la cooperación. Cuando compilo de acuerdo a la modificación me aparece este error :
*** Error 128 "analo3.c" Line 1(8,14): A #DEVICE required before this line
      1 Errors,  0 Warnings.
a que se debe::::
Título: Re: inicio
Publicado por: MLO__ en 26 de Agosto de 2008, 00:05:07
Hola

Debes colocar la linea de codigo que te di despues del #include<16F873A.h>

Saludos
Título: Re: inicio
Publicado por: ncoliv en 26 de Agosto de 2008, 09:50:17
Cuando cambio la variable valor int8 por una int16 , esta parte de muestra por el display
la hago de esta manera printf(lcd_putc,"fconv: %lu",valor);   cambio %d por %lu
esta correcto ese cambio.
Título: Re: inicio
Publicado por: ncoliv en 26 de Agosto de 2008, 10:31:25
Ok, todo muy bien. Hay algo que todavía no me cierra. Es lo siguiente : el pote en su recorrido creciente de 0 a 5 votlts se corresponde con el fconv que va de 0 a 1024 como corresponde. Cuando llevo el pote de 5 a 0volts la medida se muestra en el display en forma correcta decreciente  pero fconv continua creciendo y llega al orden de los 9000.Recien cuando reseteo el micro vuelve a lo que debería ser. Que puede estar sucendiendo, como lo solucionaría?
Título: Re: inicio
Publicado por: MLO__ en 26 de Agosto de 2008, 10:58:01
Hola.

Coloca el codigo y alguna simulacion en proteus, no entiendo a que te refieres ... normalmente el valor debe bajar ... prueba dejar algunos espacios en blanco:
Código: [Seleccionar]
printf(lcd_putc,"fconv: %lu   ",valor);

Saludos.
Título: Re: inicio
Publicado por: ncoliv en 26 de Agosto de 2008, 12:16:40
Gracias por las respuesta. No tengo el proteus, trabajo con el mplab V8.10. donde los puedo conseguir?
El "fconv" y "medida" son dos variables que muestro por el Lcd y se corresponden a la captura del adc que va de 0 a 1024 y la otra a la variaciòn de tensiòn del pote que es de 0 a 5 volts respectivamente.
El problema es que fconv no regresa de 1024 a 0 cuando medida va de 5 a 0 volts
probarè lo que me dices
Título: Re: inicio
Publicado por: MLO__ en 27 de Agosto de 2008, 00:13:43
Hola.

Postea el codigo para probarlo listo?

Saludos
Título: Re: inicio
Publicado por: ncoliv en 27 de Agosto de 2008, 18:52:43
Aqui va el codigo MLO, gracias por tu colaboración.
#include <16F877a.h>
#device adc=10
#include <STDLIB.H>
#use delay(clock=4000000)
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#byte portb=6
#include <lcd.c>

void main(void)
{
float const resoluc=5.0/1024.0;
int16 valor=0;
float kk=0;


set_tris_b(0x00);
set_tris_a(0xFF);
portb=0x00;

lcd_init();
lcd_gotoxy(1,1);

setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(20);

while(true)
{

valor=read_adc();
kk=valor*resoluc;
lcd_gotoxy(1, 1);
printf(lcd_putc,"fconv: %lu",valor);
lcd_gotoxy(1, 2);
printf(lcd_putc,"medida: %f",kk);
delay_ms(500);
}
}
Título: Re: inicio
Publicado por: MLO__ en 28 de Agosto de 2008, 11:03:51
Hola.

El programa esta bien. Efectivamente era lo que te habia dicho antes, coloca unos espacios en blanco despues de la asignacion de la variable de salida, ya que al pasar de 1024 a 900, en la LCD queda escrito el ultimo valor que es el 4 y se escribe el 900, lo que da la sensacion de 9004, y asi para los otros valores.

Colocalo asi:
Código: C#
  1. while(true)
  2. {
  3.         valor=read_adc();
  4.         kk=valor*resoluc;
  5.         lcd_gotoxy(1, 1);
  6.         printf(lcd_putc,"fconv: %lu  ",valor);
  7.         lcd_gotoxy(1, 2);
  8.         printf(lcd_putc,"medida: %f  ",kk);
  9.         delay_ms(500);
  10. }

y listo

Saludos
Título: Re: inicio
Publicado por: firepic en 28 de Agosto de 2008, 18:54:13
Saludos! MLO, corrígeme si estoy equivocado.
Yo suelo refrescar (borrar) el LCD antes de enviar nuevos datos para evitar cualquier colisión u "embasuramiento".
Lo hago con el comando \f, por ejemplo así:
Código: C
  1. printf(lcd_putc,"\f%f",kk);
Tú qué dices? A mí hasta ahora me ha funcionado bien, pero no sé... crees que sea óptimo hacerlo así?
Ok nos leemos!  :mrgreen:
Título: Re: inicio
Publicado por: ncoliv en 29 de Agosto de 2008, 09:36:14
Gracias muchachos,probaré lo aportado por Uds.
saludos
Título: Re: inicio
Publicado por: MLO__ en 29 de Agosto de 2008, 11:08:55
Hola.

Tambien se puede hacer asi Javier, el problema es que hay un titileo en la pantalla cuando se hace, y si el tiempo de refresco es muy pequeno, se vera muy "destellante" la situa. Si se colocara en el ejemplo del amigo ncoliv se veria un titileo cada 500mS. Solo es por cuestion de presentacion  :mrgreen:

Saludos
Título: Re: inicio
Publicado por: firepic en 29 de Agosto de 2008, 13:03:31
Entendido!  :)
Saludos a todos, nos leemos!  :mrgreen:
Título: Re: inicio
Publicado por: ncoliv en 04 de Septiembre de 2008, 12:21:12
Ok.amigos todo sobre ruedas. Otra pregunta es la de como puedo incrementar los decimales en la variable medida, es decir por ejemplo de 3,42 que se mide llevarlo a 3,426 ( un decir). otra, Comopuedo lograr estabilidad en la mediciòn analogica, sucede que sin mover el potenciométro. tengo una variación en el valor analógico este oscila permanentemente por ejemplo de 215 a 220. Desde ya muchas gracias por las respuestas y su colaboración
Título: Re: inicio
Publicado por: MLO__ en 04 de Septiembre de 2008, 13:37:21
Hola.

Para aumentar el numero de decimales lo haces asi: %2.4f, donde el 4 es el numero de decimales a mostrar en la LCD. Para lo del titileo de los ultimos numeros, debes garantizar la estabilidad de la fuente y hacer un filtrado  en software ( un moving average de unos 20 datos es suficiente ).

Saludos
Título: Re: inicio
Publicado por: ncoliv en 06 de Septiembre de 2008, 12:08:04
Gracias MLO tal cual, eso es lo que quería ver en el LCD. Con  respecto al filtrado por software como, se implementaria en este pequeño programita, escuche lo de filtrar mediante programa pero aun no tuve oprtunidad de implementar uno, seria bueno el realizarlo ahora con ayuda de este foro.
Muchas gracias!
Saludos y nuevamente uno aprende mucho en este medio.
dejaré el programita cuando lo tenga listo para que le sirva de guia a otro usuario en mis misma condiciones .
Gracias !!
Título: Re: inicio
Publicado por: MLO__ en 06 de Septiembre de 2008, 15:43:41
Hola.

El fitrado digital mas simple es hacer un promedio de varias muestras. Un prototipo de filtro podria ser el siguiente (para 8 bits):

Código: C#
  1. unsigned int8 filtro (int chan)
  2. {
  3.  int8 valor[100]="\0";//Espacio para 100 muestras
  4.  unsigned int16 sld=0;
  5.  int i=0, j=0, res=0;
  6.    
  7.    set_adc_channel(chan);//Seteo el canal a convertir
  8.    for (i=0;i<=99;++i)
  9.    {
  10.     delay_us(10);
  11.     valor[i] = read_adc();//Lleno el vector con 100 conversiones
  12.    }
  13.  
  14.    for (j=0;j<=99;j++)
  15.    {
  16.    sld += valor[j];//Sumo todos los valores del vector
  17.    }
  18.    res = sld/100;//Calculo el promedio de las medidas
  19.  
  20.  return res;//Retorno el valor
  21. }

A la funcion le envio como parametro el canal a convertir. Mira que saco el promedio de 100 muestras, lo cual me toma 1mS, que no es mucho tiempo que digamos.

Saludos
Título: Re: inicio
Publicado por: ncoliv en 16 de Septiembre de 2008, 12:59:22
es una pregunta fuera de línea de esta post. Es la siguiente. Tengo un pic 18fXXX .... Lo puedo programar con el CCS PCH
Título: Re: inicio
Publicado por: MLO__ en 16 de Septiembre de 2008, 13:29:35
Hola.

Si, amigo ese es el compilador para esa gama de PICs.

Saludos
Título: Re: inicio
Publicado por: ncoliv en 16 de Septiembre de 2008, 23:10:34
Gracias MLO
nos estamos leyendo
saludos
Título: Re: inicio
Publicado por: ncoliv en 18 de Septiembre de 2008, 21:35:47
Otra pregunta MLO que no hace referencia  a este post.
Coseguí este programa. Es del ds1307 y el f877 Muestra el tiempo (h,m,s) por un lcd. Lo que sucede que no tengo los conexionados ni la forma de ponerlo en hora. Me podrian dar una mano con el mismo e indicar algun vinculo, lo estuve viendo y no me dice nada a cerca de pulsadores ......
Muchas gracias.
PD. Ya seguiré con  el post original debido a que no termine con el tema.
Título: Re: inicio
Publicado por: ncoliv en 18 de Septiembre de 2008, 21:39:30
aqí va el programita:
////////////////////////////////////////////////////////////////////////////////
////////////ESTE PROGRAMA UTILZA EL CIRCUITO DS1307 PARA MOSTRAR LA ////////////
//////////HORA EN TIEMPO REAL A TRAVEs DE UNA LCD DE 2 POR 16 CARACTERES/////


#include <16F877A.h>                ///   libreria para el manejo del pic16f877a
#use delay(clock=8000000)          ///   declara  la frecuencia del cristal
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT
#include <ds1307.c>
#include <lcd.c>


#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                     ///   con esta instruccion evitamos que
#use fast_io(D)                     ///   se este configurando cada vez que usamos
#use fast_io(E)                     ///   alguna instruccion de entrada o salida


#byte portc = 7                     /// se definen direcciones de memoria
#byte portd = 8

int sec;
int min;
int hrs;
int  day;
int  month;
int  yr;
int  dow;


////////////////////////////////////////////////////////////////////////////////
//////////////////////Comienzo de la funcion principal//////////////////////////
////////////////////////////////////////////////////////////////////////////////
void main()
{

   ds1307_init(0);                          ///se inicializa el ds1307
   
   set_tris_a(0xff);
   set_tris_d(0x00);
   set_tris_b(0x00);
   set_tris_c(0x04);
   set_tris_e(0x01);
   port_b_pullups(true);
 
 
  lcd_init();                               /// inicializamos lcd
 
 
 
  // Set date for -> 15 June 2005 Tuesday
  // Set time for -> 15:20:55 (9:49:00 am)
 
  ds1307_set_date_time(8,11,7,2,9,49,00);   /// se escribe en el displositivo
                                            /// el tiempo deseado
  while(1)
  {
 
    delay_ms(100);
   
  ds1307_get_date(day,month,yr,dow);        /// se obtiene la fecha 
  ds1307_get_time(hrs,min,sec);             /// se obtiene la hora
  lcd_gotoxy(1,2);
  printf(lcd_putc,"%02d:%02d:%02d          ",hrs,min,sec);   ///se despliegan los datos
 
  lcd_gotoxy(1,1);
  lcd_putc("WWW.ELHACKER.NET");
       
  }
}
Título: Re: inicio
Publicado por: MLO__ en 18 de Septiembre de 2008, 21:50:21
Hola.

Lo que pasa con ese programa es que configuran el reloj por software con la funcion ds1307_set_date_time(8,11,7,2,9,49,00);. Si quieres modificar los valores a tu gusto, puedes colocar tu los pulsadores para variar los valores que cargaras en variables antes de colocar la funcion set_date_time().

Saludos
Título: Re: inicio
Publicado por: ncoliv en 18 de Septiembre de 2008, 22:40:32
tal vez es mucha la expliacion: como realizo el conexionado  de los  elementos, la comunicación I2C porque puerto se estaría haciendo.
Como configuraria el programa  para incrementar por pulsadores la h,m,s.
Saludos
Título: Re: inicio
Publicado por: MLO__ en 18 de Septiembre de 2008, 22:57:55
Hola.

Te recomiendo que veas el datasheet del reloj ds1307 y del 16F877A. El protocolo I2C se realiza por dos cables unicamente SDA y SCL. El conexionado es sencillo cierto??? lo que debes tener en cuenta es las resistencias de pull up y ya.

Que como configurarias el programa? mhh ... la idea es que antes de usar la funcion set_date_time() configures las variables. Lees el estado de los pines a los cuales van conectados los pulsadore y cada que cambian de estado aumentas en uno la variable correspondiente. Debe haber un pulsador de inicio, para indicarle que la configuracion a terminado y que comienza ya a dar la hora por la LCD.

Creo que con eso tienes una idea para que lo comiences a hacer. Publica los avances y vamos corriegiendo las cosas en el camino.

Saludos
Título: Re: inicio
Publicado por: ncoliv en 21 de Septiembre de 2008, 22:15:01
Ok muchas gracias MLO, empezaré por ver en primer lugar la hora cdo se configura por software.
hasta otro post.
saludos
Título: Re: inicio
Publicado por: ncoliv en 27 de Septiembre de 2008, 23:12:35
De vuelta con las preguntas .....que puede estar pasando: cuando compilo el archivo que muestra el tiempo en un lcd  obtengo este resultado:
>>> Warning 203 "C:\ARCHIV~1\PICC\drivers\ds1307.c" Line 233(1,1): Condition always TRUE
>>> Warning 203 "rtc0.c" Line 58(1,1): Condition always TRUE
      Memory usage:   ROM=16%      RAM=25% - 30%
      0 Errors,  2 Warnings.
Loaded C:\rtc0\rtc0.cof.
BUILD SUCCEEDED: Sat Sep 27 22:39:02 2008

La linea 233 del ds 1307.c es:

  while(1){

 y la linea del 58 del rtc0.c es:

  {
muchas gracias.
saludos
 
Título: Re: inicio
Publicado por: MLO__ en 28 de Septiembre de 2008, 12:35:34
Hola

Eso tiene que ver con la sentencia dentro del ciclo while(sentence), como hay un sentence=1, el compilador te avisa que la sentencia siempre se va a cumplir, es decir que tiene como valor true=verdadero=1.

Saludos.