TODOPIC

Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: juancho056 en 05 de Abril de 2015, 23:59:55

Título: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 05 de Abril de 2015, 23:59:55
Hola!

Estoy realizando un programa en el cual uso la funcion make8 o bien corrimientos y una and para sacar la parte alta y baja de un dato capturado por el adc de 10 bit que poseen los microcontroladores, esta parte alta y la baja del dato las envio en 2 registro en al memoria eeprom a VB6, y hasta y todo de maravilla.
El problema es que no entiendo como volver a unir la parte alta y baja del dato para saber el valor del voltaje capturado, el voltaje que estoy capturando con el adc es de 0-5V, si alguien tiene conocimientos respecto al tema o sabe como volvera  unir ambos datos con una formula estare muy agradecido.

Feliz dia!   :)
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: elgarbe en 06 de Abril de 2015, 07:25:27
int datoCompleto

datoCompleto = (ParteAlta << 8) + ParteBaja;

algo así?

sds.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: Nocturno en 06 de Abril de 2015, 08:06:21
También sirve con matemáticas tradicionales:

datoCompleto = ParteAlta *256 + ParteBaja;
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juaperser1 en 06 de Abril de 2015, 11:20:41
Citar
datoCompleto = (ParteAlta << Cool + ParteBaja;
.

Estas desplazando la parte alta, un numero equivalente a un emoticono con gafas xd, haha ;-)
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 06 de Abril de 2015, 12:54:54
Hola gracias por sus respuestas  ((:-)), pero el caso es el siguiente:

La simulacion la estoy haciendo en proteus, al medir el valor suministrado al adc es 3.40 v, el programa al cual me llegan ls datos como entreos se visualiza este valor como parte alta 2 y parte baja 184 entonces

(2*256)+184=696

Todo esto dividido por 2 me esta dando 348 que es un valor con una tolerancia aceptable.

El problema ya vi que radica en que cuando los voltajes disminuyen por debajo de 1v la parte alta toma el valor de 0 y la parte baja siempre toma un valor de 138 sin importar cual sea el voltaje  0.85, o 0.25v los 2 registros simepre son los mismos. Es posible que este valor se de por la manera en que estoy imprimiendo el mensaje desde CCS %U, o cual puede ser el motivo?

Gracias por responder  :mrgreen:

 

Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: KILLERJC en 06 de Abril de 2015, 13:21:02
El problema ya vi que radica en que cuando los voltajes disminuyen por debajo de 1v la parte alta toma el valor de 0 y la parte baja siempre toma un valor de 138 sin importar cual sea el voltaje  0.85, o 0.25v los 2 registros simepre son los mismos. Es posible que este valor se de por la manera en que estoy imprimiendo el mensaje desde CCS %U, o cual puede ser el motivo?

Si parece que tu problema es esem es que se esta enviando mal. Deberias enviar el hexadecimal a la PC o aunque sea en 2 partes.

Si usas una referencia de 5V deberia variar la lectura de 0 a 5V significa que el AD  varia desde 0 a 1023 (0x000 a 0x3FF ). Para obtener el valor que da el AD en voltios es simplemente:

Voltios = (AD * 5) / 1023

Si seguimos con la misma referencia de tension 5V. cada bit del ADC reprentaria 5 /1023 aproximadamente 4.88mV

Citar
Todo esto dividido por 2 me esta dando 348 que es un valor con una tolerancia aceptable.

Por que dividirlo por 2 ? no entiendo cual es tu objetivo ahi.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 06 de Abril de 2015, 14:21:57
Hola KILLERJC, gracias por responder.

Al estar enviando los datos de forma entera desde CCS el planteamineto era el siguiente (Parte alta*256)+parte baja que al ser dividido por 2 me da un valor bastante aproximado al valor dc medido sin el punto flotante por estar trabajando en entero:

Valor DC medido: 3.40V

valor parte alta enviando los datos como entero:2 y parte baja:184

Utilizando la formula  (2*256)+184=696     donde 696/2=348 me da un valor aproximado sin el punto, que con funciones de VB6 pensaba acomodar para que graficara 3.48v
(trabajo inecesario  8)), valores similares se aprecian con diferentes voltajes.

Cuando envio los datos en hexadecimal desde ccs osea %x,  5v es parte alta 3 y parte baja FF como explicas, pero sigue ocurriendo lo mismo para valores inferiores a 1.25v los registros siempre toman el mismo valor para este caso 00 parte alta y 8a parte baja,  no varian.

La idea de tomar todos estos valores es graficar el comportamiento de unos sensores, como los registros toman el mismo valor siempre que bajen de 1.25 v, el comportamiento de la grafica seria el mismo para 1v, 0.85v o 0.25v.  Mientras el voltaje sea menor de 1.25v no podre saber cual fue le voltaje minimo que registro el sensor  :(

Gracias por responder lo aprecio bastante  :mrgreen:


Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: Nocturno en 06 de Abril de 2015, 15:23:15
No te fíes de Proteus trabajando con analógica, pruébalo en real.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: KILLERJC en 06 de Abril de 2015, 23:13:40
La idea de tomar todos estos valores es graficar el comportamiento de unos sensores, como los registros toman el mismo valor siempre que bajen de 1.25 v, el comportamiento de la grafica seria el mismo para 1v, 0.85v o 0.25v.  Mientras el voltaje sea menor de 1.25v no podre saber cual fue le voltaje minimo que registro el sensor  :(

Entiendo perfectamente. el AD como dije da un numero de 0 a 1023 asi que siempre trabajas con enteros, luego si lo convertis a flotante para saber el voltaje.
Tu problema pasaria a otro. me parece raro que el ADC no este dandote los valores como corresponde. O el mismo printf te lo esta convirtiendo en un mal valor o hay un problema de simulacion si lo estas haciendo por simulacion. Ya que deberia variar, sino puede haber algo raro en el programa ( pero esto no lo creo por que te da el maximo como 0x3FF ).

Citar
Al estar enviando los datos de forma entera desde CCS el planteamineto era el siguiente (Parte alta*256)+parte baja que al ser dividido por 2 me da un valor bastante aproximado al valor dc medido sin el punto flotante por estar trabajando en entero:

Si da un aproximado pero es un error mas cuando queres graficar lo de un sensor y a la PC no le cuesta nada hacer una multiplicacion y division para dar con el resultado en coma flotante.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: RALF2 en 06 de Abril de 2015, 23:40:54
Citar
El problema ya vi que radica en que cuando los voltajes disminuyen por debajo de 1v la parte alta toma el valor de 0 y la parte baja siempre toma un valor de 138 sin importar cual sea el voltaje  0.85, o 0.25v los 2 registros simepre son los mismos. Es posible que este valor se de por la manera en que estoy imprimiendo el mensaje desde CCS %U, o cual puede ser el motivo?

Coloca el codigo del pic que estas programando en ccs, para ver como tienes configurado el printf.
Ya que, tal como lo indicas arriba no es posible que te esten dando esos valores  :?
Si lo muestras por la lcd o por RS232, la parte baja del resultado, deberia estar disminuyendo a medidas que reduces el voltaje.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: Daikataro en 07 de Abril de 2015, 01:31:34
Si tu compilador tiene la opción de manipular los bits individuales que forman cada byte o word, tienes la vida hecha. En PSI sería así:

Resultado_ADC.LB = Parte_baja
Resultado_ADC.HB = Parte_alta

En PSI el .LB significa el byte menos significativo de un Word (2 bytes) y HB el byte más significativo. Simplemente escribes el valor de cada byte en un solo word y tienes tu resultado ADC.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: RALF2 en 07 de Abril de 2015, 19:14:49
Código: [Seleccionar]
#include <18f252.h>
#device adc= 10
#fuses XT,NOWDT,PUT,NOBROWNOUT,NOWRTB,NOWRTD
#use delay (crystal= 4000000)

#use RS232(baud=9600,xmit= pin_b0,rcv=pin_b1)


void main()
{
   long res_adc;
   int h_adc, l_adc;
   
   setup_adc_ports(an0);
   setup_adc(adc_clock_internal);
   set_adc_channel(0);
   
   while(true)
   {
      res_adc= read_adc();
      h_adc= make8(res_adc,1);
      l_adc= make8(res_adc,0);
     
      printf("El valor del adc= %lu\r",res_adc);
      printf("Parte alta del adc= %u\r",h_adc);
      printf("Parte baja del adc= %u\r",l_adc);
     
      delay_ms(1500);
   }   
}

El codigo adjunto lo probe y funciona a la perfeccion con el ccs  :mrgreen:
Pruebalo y nos das tus impresiones.  ;-)
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 08 de Abril de 2015, 14:17:03
Hola a todos Gracias por responder, pero el problema persiste, lo explicare paso a paso.

Inicialmente realice todo el montaje para descartar que fuese problemas de simulacion en proteus como indicaba Nocturno, pero proteus y el monatje me funcionan exactamente igual. Actualemente estoy trabajando con el pic16f1936 que es la gama avanzada del pic16f886 que ya no sale, osea tiene muchas mas funciones, mas memoria, pero en sintesis es lo mismo obviamente mucho mas caro.

El problema es que los datos que estoy tomando del adc al ser de 10 bits los tengo que enviar en 2 registros con lo cual uso la funcion make8(dato,1) parte alta y make8(dato,0) parte baja o lo que es lo mismo (dato>>8) y (dato&255), de igual manera lo estoy haciendo para un encoder que me estara contando lo metros (3500)  se hace lo mismo divido el dato en la parte alta y baja para guardarlo en 2 registros de la eeprom y poder contar hasta 65535, hasta ahi todo muy bien.

Los datos los estoy guardando en diercciones de la memoria eeprom, una vez se active una bandera  asi :

 if(flagcommand) {
     commad_process(); // Hay algo pendiente de procesar y lo procesa.
     write_eeprom(0,voltL1);
     delay_us(150);   // minimo de tiempo que se debe esperar para guardar el dato en al eeprom
     write_eeprom(3,voltH1);
     delay_us(150);
     write_eeprom(6,voltL2);
     delay_us(300);
     write_eeprom(9,voltH2);
     delay_us(300);
     write_eeprom(12,metrosH);
     delay_us(200);
     write_eeprom(15,metrosL);
     delay_us(200);
     }
Todo funciona perfecto al recibir y enviar la trama, los datos toman la posicion que requiero, los estoy enviando en entero que la respresentacion ps no tiene mucha importancia en entero 5 v es (3-255) en hexa (3-ff) parte alta y parte baja.

Luego de explicar todo y que todo funciona bien el error es!

en la trama no se visualizan los valores por debajo de 1.25v para el adc captado siempre me muestra parte alta (0) y parte baja (138), para ponerlo mas claro en el contador de metros que empieza en 0 hasta 3500 cuando empieza se visualiza (0) parte alta y (137) parte baja.
Para visualizar que este contando bien estoy imprimendo los metros despues de que envio la trama asi:

 printf("%x-%x-%x-%U-%U-%U-%U-%U-%U-%x-%x\r\n",cmd[0],cmd[1],cmd[2],cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]cmd[8],cmd[9],cmd[10]); // ... y lo muestro
  printf("%lU Metros: \r\n",metros);

Como se observa envio una trama los %U son los dos sensores y el encoder para los metros en sus partes altas y bajas
En la trama tomando las dos ultimas (%U-%U) es la respresentacion del encoder, mientras la variable  metros que la imprimo abajo no llega hasta 255 se ve asi (0)-(137) parte alta y baja en la trama

lo cual me daria mal para tomar el metraja inicial osea

(0*256)+137=137 ese seria el valor siempre desd 1 hasta que supere 255 una vez los lo supera la trama se visualiza asi

(1)-(0) para los registros del encoder, por lo que se puede calcular el metraje
1*256+0=256

(1)-(3)

1*256+3=259

Mientras no se supere el valor de 255 los registros del encoder se veran (0)-(137), lo mismo sucede para el adc que los estoy haciendo para varoles de 0 a 5v, cuando esta por debajo de 1.25 v el valor del registro siempre es (0)-(138), minetras el valor sea >=1.25v todo funciona a la mil maravillas en el adc y mientras el valor sea mayor a 255 funcioan perfecto para llevar el calculo de los metros.

Espero haber expresado bien la idea y que me puedan ayudar, yo vengo rebentando cabeza y no entiendo por uqe se da eso.
Gracias por sus aportes  :mrgreen:
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: Nocturno en 08 de Abril de 2015, 14:49:13
Pega la parte del código de inicialización y lectura del ADC, por favor.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 08 de Abril de 2015, 14:53:14
Claro Nocturno, gracias,
 va asi:

void main()             //Principal
{
  //setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
  ext_int_edge(H_TO_L);  // para contar pulsos de encoder
  setup_adc_ports(sAN0);
  setup_adc_ports(sAN1);
  setup_adc(adc_clock_internal);

  delay_ms(100);
 
  init_cbuff();               // Borra buffer al inicio
  enable_interrupts(int_ext);
  enable_interrupts(int_rda); // Habilita Interrupción RDA
  enable_interrupts(global);  // Habilita interrupciones

 
  do {
  set_adc_channel(0);
   delay_us(20);
   adc1=read_adc();
   voltL1=adc1>>8;
   voltH1=adc1&255;
   voltaje1=(5.0*adc1)/1024.0;
   
  set_adc_channel(1);
   delay_us(20);
   adc2=read_adc();
   voltL2=adc2>>8;
   voltH2=adc2&255;
   voltaje2=(5.0*adc2)/1024.0;

   
     if(flagcommand) {
     commad_process(); // Hay algo pendiente de procesar y lo procesa.
     write_eeprom(0,voltL1);
     delay_us(150);
     write_eeprom(3,voltH1);
     delay_us(150);
     write_eeprom(6,voltL2);
     delay_us(300);
     write_eeprom(9,voltH2);
     delay_us(300);
     write_eeprom(12,metrosH);
     delay_us(200);
     write_eeprom(15,metrosL);
     delay_us(200);
     }
  } while (TRUE);
 
}

Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: KILLERJC en 08 de Abril de 2015, 17:41:35
Esto no es referido a sobre enviar el dato

Yo lo unico que tengo para decir, es pobre EEPROM todas las veces que la estas grabando... podrias dejarlo en las variables voltL1,voltH1,voltL2 y voltH2 y los metros tambien,

Acordate que tenes limitada cantidad de veces para escribirla.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 08 de Abril de 2015, 17:49:47
Esto no es referido a sobre enviar el dato

Yo lo unico que tengo para decir, es pobre EEPROM todas las veces que la estas grabando... podrias dejarlo en las variables voltL1,voltH1,voltL2 y voltH2 y los metros tambien,

Acordate que tenes limitada cantidad de veces para escribirla.

Es una red modbus se se requieren registros no variables, por ende uso la eeprom :mrgreen:
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: KILLERJC en 08 de Abril de 2015, 18:22:45
Es una red modbus se se requieren registros no variables, por ende uso la eeprom :mrgreen:

las variables SON registros :)
A nivel hardware son registros, la unica diferencia es que cuando se corta la luz lo perdes (RAM), es la unica diferencia con EEPROM que tendrias.
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 08 de Abril de 2015, 18:50:06
 :oops: :oops: :oops:

jajaja tienes toda la razon KILLERJC, la verdad es que el sistema va funcionar continuamente, En el datasheet dice que vienen garantizados 100 000 ciclos de escritura/borrado por lo cual si es mejor solo usar las variables para no tener problemas proximamente, lo bueno de la eeprom es que puedo apuntar directamente a la direccion de memoria con read_eeprom(), mientras que si utilizo variables no sabria especificar en la trama por que direccion de registro preguntar. 

Se que la eeprom por defecto tiene inicializado el valor xff o en entero 255 por eso puede estar fallando, voy a investigar como direccionar el registro que ocupan las variables y hare pruebas.

Si alguien sabe y me puede echar una mano no estaria de mas.

KILLERJC y a todos agradece mucho sus comentarios  ((:-))
Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: KILLERJC en 08 de Abril de 2015, 20:13:07
int variable;
int *direccion;

Esto: &variable te da la direccion de "variable", suponete que lo guardas en un puntero llamado direccion

direccion = &variable
(ahora "direccion" tiene la direccion del registro donde se almacena "variable")

si haces *direccion es lo mismo que leer "variable", ya que estarias apuntando a lo contenido en esa direccion

o sea "variable" es equivalente a "*direccion"

Seria util/mas facil si proveyeras el codigo donde envias los datos para el MODBUS, imagino que es una funcion.


Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 09 de Abril de 2015, 02:00:35

KILLERJC, muchas gracias  ((:-)) un algun dia sere como tu  :mrgreen:
La verdad no sabia manejar apuntadores con tu explicacion me quedo mas que claro y funciona exactamente igual, con el agregado que ya no gasta la memoria eeprom.
La funcion donde la imprimo es este prinf que me envia todos los datos de un vector de 11 posiciones separados por "-" como lo explique anteriormente, sigue pasando exactamente lo mismo, y en la cita ya modifique la forma de llamar los registros gracias a ti. 

Hola a todos Gracias por responder, pero el problema persiste, lo explicare paso a paso.

Inicialmente realice todo el montaje para descartar que fuese problemas de simulacion en proteus como indicaba Nocturno, pero proteus y el monatje me funcionan exactamente igual. Actualemente estoy trabajando con el pic16f1936 que es la gama avanzada del pic16f886 que ya no sale, osea tiene muchas mas funciones, mas memoria, pero en sintesis es lo mismo obviamente mucho mas caro.

El problema es que los datos que estoy tomando del adc al ser de 10 bits los tengo que enviar en 2 registros con lo cual uso la funcion make8(dato,1) parte alta y make8(dato,0) parte baja o lo que es lo mismo (dato>>8) y (dato&255), de igual manera lo estoy haciendo para un encoder que me estara contando lo metros (3500)  se hace lo mismo divido el dato en la parte alta y baja para guardarlo en 2 registros  y poder contar hasta 65535, hasta ahi todo muy bien.

Los datos los estoy guardando en diercciones de la memoria flash con apuntadores que me llevan la direccion del registro y toman el valor almacenado, una vez se active una bandera  asi :

 if(flagcommand) {
     commad_process(); // Hay algo pendiente de procesar y lo procesa.
     dir1=&voltL1;
     dir2=&voltH1;
     dir3=&voltL2;
     dir4=&voltH2;
     dir5=&metrosH;
     dir6=&metrosL;
     }
Todo funciona perfecto al recibir y enviar la trama, los datos toman la posicion que requiero, los estoy enviando en entero que la respresentacion ps no tiene mucha importancia en entero 5 v es (3-255) en hexa (3-ff) parte alta y parte baja.

Luego de explicar todo y que todo funciona bien el error es!

en la trama no se visualizan los valores por debajo de 1.25v para el adc captado siempre me muestra parte alta (0) y parte baja (138), para ponerlo mas claro en el contador de metros que empieza en 0 hasta 3500 cuando empieza se visualiza (0) parte alta y (137) parte baja.
Para visualizar que este contando bien estoy imprimendo los metros despues de que envio la trama asi:

 printf("%x-%x-%x-%U-%U-%U-%U-%U-%U-%x-%x\r\n",cmd[0],cmd[1],cmd[2],cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]cmd[8],cmd[9],cmd[10]); // ... y lo muestro
  printf("%lU Metros: \r\n",metros);

Como se observa envio una trama los %U son los dos sensores y el encoder para los metros en sus partes altas y bajas
En la trama tomando las dos ultimas (%U-%U) es la respresentacion del encoder, mientras la variable  metros que la imprimo abajo no llega hasta 255 se ve asi (0)-(137) parte alta y baja en la trama

lo cual me daria mal para tomar el metraja inicial osea

(0*256)+137=137 ese seria el valor siempre desd 1 hasta que supere 255 una vez los lo supera la trama se visualiza asi

(1)-(0) para los registros del encoder, por lo que se puede calcular el metraje
1*256+0=256

(1)-(3)

1*256+3=259

Mientras no se supere el valor de 255 los registros del encoder se veran (0)-(137), lo mismo sucede para el adc que los estoy haciendo para varoles de 0 a 5v, cuando esta por debajo de 1.25 v el valor del registro siempre es (0)-(138), minetras el valor sea >=1.25v todo funciona a la mil maravillas en el adc y mientras el valor sea mayor a 255 funcioan perfecto para llevar el calculo de los metros.

Espero haber expresado bien la idea y que me puedan ayudar, yo vengo rebentando cabeza y no entiendo por que se da esto.
Gracias por sus aportes  :mrgreen:




 

Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: KILLERJC en 09 de Abril de 2015, 02:19:08
KILLERJC, muchas gracias  ((:-)) un algun dia sere como tu  :mrgreen:

Vas a ir mal si es asi.


Siguiendo con el tema
El problema persiste. Estaria bueno si pudieras hacer un programita simple que use el ADC y fijarte si funciona como corresponde.
Si funciona correctamente entonces puede que sea tu programa., si funciona mal, entonces existe algo mal en el circuito o el PIC.

Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: juancho056 en 09 de Abril de 2015, 14:26:37
Ya lo  logre solucionar, realice el programa de manera que solo contara los metros y lo puse a imprmir en hyperterminal, y funcionaba bien. Examienando el codigo estoy utilizando una funcion en ccs, antes de imprimir la trama donde almacenaba los registros

  strcpy(cmd,modbus.trama);        // Lo copio para procesarlo

Basicamente copiaba modbus.trama que es la trama recibida del maestro modbus en otra de igual tamaño llamada cmd, pensando que asi evitaba  que se solaparan los datos  y salvaguardaba la trama.
Y al parecer como la funcion es para guardar una cadena de  strig y los datos los guardaba en enteros, se presentaban los conflictos.

KILLERJC, eres grande!!, me ayudaron mucho tus aportes  ((:-))  :mrgreen:

Título: Re: como unir un dato parte alta y baja despues de usar make8 si no es ccs
Publicado por: Nocturno en 10 de Abril de 2015, 03:30:23
Felicidades