Autor Tema: ADC, MikroC PIC 16F877A (Dudas)  (Leído 7116 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
ADC, MikroC PIC 16F877A (Dudas)
« en: 02 de Julio de 2015, 20:58:24 »
Buenas! Estoy necesitando saber como trabaja el PIC con ADC. Mi problema es que si yo a la entrada del chanel 1 le mando 2,5V el ADC al convertirlo tambien me forma ese numero?? como yo preciso mandar ese numero por SPI como devería hacer?? hasta ahora el programa que arme lo dejo adjunto, me seria de gran ayuda que me dijesen si esta bien o si hay que correguir cosas. desde ya muchas gracias!  :mrgreen:

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #1 en: 02 de Julio de 2015, 23:01:54 »
Te explico como funciona el ADC...

Si es un ADC de 8 bits, el resultado que vas a obtener es de 0 a 255, si es de 10 bits va de 0 a 1024.

Donde 0, es cuando la entrada esta sobre Vref- ( o GND segun como lo tengas configurado) y Verf+ ( o 5V - VCC , tambien como lo tengas configurado)
tomemos el caso mas simple de GND a Vcc

Si tenes 2.5V estas en la mitad de la escala, es decir vas a tener un numero que es igual a :

(2.5V / 5V ) * 255 = 127 o 128  (no tiene coma)

Para 1V

( 1V/5V) * 255 = 51

Asi de la misma forma sabiendo cual es el valor del ADC podes saber la tension

(51/255) * 5V = 1V
(127/255) * 5V = 2.49V


Ahora como mandas ese dato por SPI?
Normalmente mandas el resultado del ADC, creo que tu ejemplo es una conexcion entre 2 PIC, entonces vas a mandar esos 8bits del resultado, si tenes un ADC de 10bits, tenes que mandar 16, es decir los 8 mas bajos y de los 8 mas altos solo ocupas 2 bits. Igual en esos PIC el resultado se almacena de esa forma en 2 registros de 8 bits.
Para el micro es ideal que este en esos valores, es decir que sea un numero entero. Pero para las personas no, y cuando lo mostras en un LCD ahi es cuando por ahi necesitas hacer la formula que pase y mandar el float al LCD, pero en tu caso no es necesario.

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #2 en: 03 de Julio de 2015, 22:50:13 »
OK! comprendido, pero aún tengo una duda con el tema de la comunicacion. Yo tengo los valores que me tiran el eje X y el eje Y de un analgico de joystick, tengo que leer los dos canales, hacer la conversion y enviarlos. Como tendria que enviarlos para que marchen ordenadamente, y como deveria recivirlos para que concuerde?? es decir si yo lo envio solo con el SPI1_Write(); y lo recibo de la misma forma, al ser 2 paquetes de 8 bits el tamaño del dato enviado ¿se envia sin problemas o se pierde la mitad? se lee entero o hay que leerlo por partes?? Te agradezco por la ayuda!!
Saludos!  :mrgreen:

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #3 en: 04 de Julio de 2015, 03:17:16 »
Envias datos cada 8 bits.

Ejemplo, lado izquierdo 16 bits + lado derecho 16 bits (8 y 8)

entonces envias por ejemplo

8 bits izquierdo alto
8 bits izquierdo bajo
8 bits derecho alto
8 bits derecho bajo

Y del lado del receptor simplemente esperas que lleguen los 4 datos, cuando llegaron 4 entonces ahi comenzas la operacion de juntarlos

uint16_t varibleizq,variableder;
uint8_t  array_valores_rx[4];

y haces algo asi:
variableizq = (array_valores_rx[0]<<8) + array_valores_rx[1];
variableder = (array_valores_rx[2]<<8) + array_valores_rx[3];

Supuse que metiste todos los datos en ese array.

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #4 en: 06 de Julio de 2015, 07:33:27 »
ok! pero como haria para que los datos que llegan por el puerto serial se graben en uint8_t  array_valores_rx[4]??
Lo compile y no me reconoce el unit8_t a que seria equivalente?, yo uso mikroC.
Saludos!   :)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #5 en: 06 de Julio de 2015, 13:51:14 »
Es la convencion de C esa, que para mi es mas facil de recordar que lo demas,

uint8_t

U de unsigned ( sin signo) y 8 de 8 bits

http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/arithmetic_types.htm

Si me fijo en mikroC eso es un short/char simpre unsigned ( que es lo default )


Como haces para que se ordenen ? Y depende como recibas tus datos, si por interrupcion o por el programa principal. Si es por el programa principal seria algo asi:

Código: C
  1. short i=0;
  2. short array_valores_rx[4];
  3. int   resultado[2];  //16 bits supuestamente
  4.  
  5. main(){
  6. while(1)
  7. {
  8.         if(recibi_algo())
  9.         {
  10.                 array_valores_rx[i]=RCREG;
  11.                 i++;
  12.                 if(i==4)
  13.                 {
  14.                         resultado[0]= (array_valores_rx[0]<<8) + array_valores_rx[1];
  15.                         resultado[1]= (array_valores_rx[2]<<8) + array_valores_rx[3];
  16.                         i=0;
  17.                         // Aca podes hacer lo que quieras con lo que llego, ya tenes guardado en resultado[] tus valores de izquierda y derecha, o simplemente lo haces fuera de los IF y dentro del while,
  18.                         // Ya que podrias utilizar resulatdo una y otra ves si total no va a cambiar hasta que esten disponible los otros 4 datos.
  19.                 }
  20.         }
  21. }
  22. }


Si fuera una intrrupcion seria algo similar,

Código: C
  1. Interrupcion()
  2. {
  3.  
  4.         if(RCIF & RCIE)                         // Pregunto si fue por la recepcion de datos
  5.         {
  6.                 array_valores_rx[i]=RCREG;
  7.                 i++;
  8.                 if(i==4)
  9.                 {
  10.                         resultado[0]= (array_valores_rx[0]<<8) + array_valores_rx[1];
  11.                         resultado[1]= (array_valores_rx[2]<<8) + array_valores_rx[3];
  12.                         i=0;
  13.                         // Aca podes hacer lo que quieras con lo que llego si es corto tu programa, sino podrias poner a 1 una variable y con eso hacer algo en tu programa principal
  14.                 }
  15.         }
  16. }

OBserva que mi codigo NO se ajusta exactamente a mikroC, pero te va a dar una idea de como hacerlo.
« Última modificación: 06 de Julio de 2015, 13:53:23 por KILLERJC »

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #6 en: 06 de Julio de 2015, 15:47:34 »
Ok! aún tengo 3 dudas
1° que es RCREG?
2° a "i" le asigno el valor de los datos recibidos? es decir, i = SPI1_Read();
3° si yo escribo resultado[0] estoy eligiendo el lado derecho y si escribo resultado[1] estoy eligiendo el lado izquierdo?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #7 en: 06 de Julio de 2015, 16:49:19 »
1- RCREG ( o segun el PIC que tengas ) es el registro de la UART, ahi esta el dato que llego, seguro que mikroC tiene alguna funcion como para que te devuelva el valor que llego a la UART y estoy mas que seguro que tambien debe tener una funcion que indique si es que llego algo. Buscando por internet:

http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/uart_library.htm

Las funciones a reemplazar serian:

recibi_algo() por UART_Data_Ready() , este tambien es valido para reemplaza el (RCIF & RCIE)
y
RCREG por UART_Read()

2- "i" es una variable, comenzaria con valor 0, asi saber cuantos valores llegaron a tu UART, el primer valor es 0, el segundo 1, y asi. cuando llegues al cuarto, i=3, se guarda y aumenta i hasta 4, al detectarse que llegaron todos los valores (i=4) ( de 8 bits ) se procede a juntarlos en 2 variables de 16 bits que estan en un array (lo puse en un array por gusto nomas) y poner de nuevo i a 0 en espera de otros 4 datos mas, pero podrias haber reemplazado el resultado[2] por 2 variables ejemplo

Código: C
  1. int variableizq,variableder;
  2.  
  3. variableizq= (array_valores_rx[0]<<8) + array_valores_rx[1];
  4. variableder= (array_valores_rx[2]<<8) + array_valores_rx[3];

se entiende que es lo que quise hacer ? ..

3- eso depende como lo mandas, si mandas primero los 2 bytes del lado izquierdo entonces lo que salga de las variables array_valores_rx[0 y 1] va a ser del izquierdo, y los otros 2 del derecho.
Si mandas el del lado derecho primero entonces los indices 0 y 1 van a ser del derecho y 2,3 del izquierdo.
« Última modificación: 06 de Julio de 2015, 17:32:27 por KILLERJC »

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #8 en: 06 de Julio de 2015, 19:22:19 »
Si entiendo, gracias! como estoy usando spi cambio el uart_read() por spi_read() y uso el sspstat.bf para saber si hay algo en el buffer. lo simule y me da un corto en SCK. Te dejo los codigos modificados y el circuito en proteus para ver si le podes echar un ojo y cerrar definitivamente este tema, muchas gracias por todo genio!!
Saludos!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #9 en: 06 de Julio de 2015, 22:10:47 »
Tengo un problema que no se que hace SPI_Read() asi que directamente lo voy a reemplazar por su registro, es decir no deberia provocarte un corto en CLK por que el unico que deberia manejar el clk es el maestro, y el esclavo estar a la escucha nomas. Asi que si esa linea esta generando ese error, entonces lo reemplazo por el registro.

Código: C
  1. while(1){
  2.          if(SSPSTAT.BF==1)
  3.         {
  4.  
  5.                 array_valores_rx[i]= SSPBUF;
  6.                 i++;
  7.                 if(i==4)
  8.                 {
  9.                         ladoderecho = (array_valores_rx[0]<<8) + array_valores_rx[1];
  10.                         ladoizquierdo = (array_valores_rx[2]<<8) + array_valores_rx[3];
  11.                         i=0;
  12.                         PORTB = resultado[0];          // Esto es imposible ya que tenes una variable de 16 bits ( aunque solo 10 tenga informacion) si haces eso, solo se van a mostrar esos 8 de menor peso
  13.                         PORTD = resultado[1];          // Lo que seria iguar a mostrar unicamente array_valores_rx[1] y array_valores_rx[3].
  14.          }
  15.          }
  16.    }
  17. }

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #10 en: 07 de Julio de 2015, 10:15:56 »
Ok lo corregui y lo probé pero me sigue tirando el error en SCK :( (se pone en corto)
Busqué en google alguna solucion pero no encontre algo que pudiese entender, el error que me tira proteus es "MSSP slave mode with no SS pin control and CKE==1 is ambiguous!"
Otra cosa que habia probado antes es que cuando convertia y mandaba un solo canal no tenia problemas, asique nose porque se complico tanto.

Cambié el PORTB=resultado[0]; por un PWM1_Set_duty(ladoderecho); al simularlo y ver que tira con el osciloscopio vi ruidos, pero no respondian al potenciometro.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #11 en: 07 de Julio de 2015, 15:03:35 »
Yo no entiendo por que dice que es ambiguo, siendo esclavo no le importa el SS, si el maestro va a enviar el clock con los datos directamente, y de ahi se tomaran los datos, sea un sampling en el medio o al final

Sino luego de iniciar el SPI, ponele a 0 el  el bit de CKE o quitale esto:

SPI1_Init_Advanced(_SPI_SLAVE_SS_DIS, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_LOW_2_HIGH);

es decir dejalo:

SPI1_Init_Advanced(_SPI_SLAVE_SS_DIS, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH);

a ver si tira error ahi.. Supuestamente el CKE solo se usa para transmitir, pero no creo que eso afecte en algo.

Citar
Otra cosa que habia probado antes es que cuando convertia y mandaba un solo canal no tenia problemas, asique nose porque se complico tanto.

Si funciona para uno deberia funcionar para todos. El problema en cuestion aca es el SPI, no la conversion ni nada por el estilo.
« Última modificación: 07 de Julio de 2015, 15:06:32 por KILLERJC »

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #12 en: 07 de Julio de 2015, 23:25:10 »
Lo borre y me tiro error, como que quedaba incompleto, asi que puse CKE a 0 y tampoco nada, despues me di cuenta de algo que se nos paso a ambos y es como para reir y no parar!!
El SPI_Init(); esta vacio, es decir no le asigne ninguna frecuencia en la que tenga que trabajar el SCK por lo tanto nunca iba a funcionar asi que le puse un 1KHz y se acabo el corto!! :D
El problema es que yo puse displays al puerto B y D del receptor y programe PORTD = ladoderecho; PORTB = ladoizquierdo; y nada, no me tira ningun valor. Que decis que pueda ser?? tal vez sea el tema de los vectores que no los pueda leer.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #13 en: 08 de Julio de 2015, 00:54:52 »
e.e xD

es cualquiera ese error, te tendria que haber tirado otro tipo de error pero no eso.. incluso al compilarlo.

Desconectado Ryuzaki

  • PIC10
  • *
  • Mensajes: 16
Re: ADC, MikroC PIC 16F877A (Dudas)
« Respuesta #14 en: 08 de Julio de 2015, 06:48:29 »
Bueno metiendole mano vi que si yo uso SS DIS y coloco una frecuencia de trabajo en SPI1_Init(); me tira error pero si pongo SS ENABLE trabaja bien, y ya puedo ver los cambios de VRX y VRY en los puerto del PIC receptor!!
Pero siguen habiendo problemas desafortunadamente :(
El tema es asi, si yo vario el voltaje de el chanel 1 del ADC, VRX cambia de valor y se envia y recibe todo correctamente, pero me salen en el display del puertoB (del receptor) los valores de VRX y VRY es decir indistintamente el que mueva hace que varie el resultado en ese display de forma titilante, es decir me muestra por ej, un 4 de VRX titila cambiando a una A de VRY y vuelve a titilar cambiando al 4. Asi constantemente, y el display del puertoD solo cambia aveces, pero siempre respondiendo a VRY, supuse que como esta programado para enviar uno detras del otro si yo muevo vrx y pasa por varios valores, me va a enviar eso y al recivirlo lo va a clasificar en 2 pero en realidad fue la misma variable que paso por varios valores. Nose si me explique bien, espero me puedas entender, y lograr una solucion.
Saludos!