TODOPIC

Microcontroladores PIC => * PROYECTOS * => Mensaje iniciado por: Abner_emanuel en 24 de Marzo de 2017, 09:42:53

Título: Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 24 de Marzo de 2017, 09:42:53
Un saludo compañeros del foro.

Resulta que tengo dos microcontroladores a Diferente frecuencia que quiero comunicar por que mi proyecto así lo requiere el PIC18F8722 (trabajo máximo = 40 Mhz) y el PIC18F4550 (trabajo máximo = 48 Mhz)). El PIC18f4550 tiene que trabajar a 48Mhz forzosamente por que con el controlare una pantalla TFT y requiero esa velocidad.

Mi pregunta es, si es posible hacer la comunicación serie de ellos a  pesar de la diferencia velocidad de operación.

Agradecería su ayuda.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 24 de Marzo de 2017, 14:41:12
Es posible.

Las comunicaciones series que tenes usualmente son:

UART
SPI
I2C


La UART requiere que ambos tengan el mismo baudrate configurado. Lo vas a poder lograr con ambos
El SPI utiliza el Clock generado por el Maestro. Por lo cual si respetas los tiempos minimos que debe poseer el reloj del SPI del micro esclavo funcionaria correctamente.
El I2C por otra parte utiliza frecuencias fijas, 100KHz 400KHz y 1Mhz son las mas usuales,  lo que seria un "equivalente" a lo que tenes en la UART.

En todos podes, seguramente alguno es mejor que otro. Segun la aplicacion que le deseas dar.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 26 de Marzo de 2017, 21:47:11
Gracias por responder. La comunicación que pretendo es uart entre los pic.

En alguna ocasión había leído en la red que los microcontroladores deberían de trabajar a la misma velocidad para tener una correcta comunicación uart. Por eso hará mi pregunta killerjc.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: manwenwe en 27 de Marzo de 2017, 03:49:57
No tiene porqué. Tu configura ambas UART a la misma frecuencia y funcionará bien. Lo único que tienes que tener en cuenta es no enviar datos más rápido de lo que se puedan recibir y procesar (en ambos sentidos) pero esto no depende sólo de la frecuencia de reloj, yo diría que depende más de la cantidad de cosas que estén haciendo cada unos de ellos "al mismo tiempo" que envian/reciben.

Saludos!
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 27 de Marzo de 2017, 09:01:50

Entonces lo mejor sera desarrollar una interrupción UART para ambos microcontroladores tratando de no perder datos. Les comento que los 48 Mhz del PIC18F4550 los requiero para controlar una pantalla TFT de NEXTION ya que el PIC18F8722 no tiene esa velocidad. Sin embargo con el 4550 no me alcanzaron los recursos de memoria por eso es que no hice el code en el 8722.

Ahora pienso hacerlo así, el 8722 le trasmite los valores vía UART al 4550 y esta los recibe y los envía a la TFT.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: manwenwe en 27 de Marzo de 2017, 09:29:58
Ummm porqué no pones un PIC32MX que son más rápidos y también tienen más memoria¿?. Además me da a mi que uno con más memoria va a ser más barato que el 8722...
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 27 de Marzo de 2017, 14:25:55
Como dijo manwewe, la velocidad de la UART estra prefijada en ambos micros y deben ser la misma.

El transmisor no va a poder enviar mas rapido de lo que hace la UART, asi que la unica que le queda por mas rapido que vaya es esperar que se termine de enviar. Si la espera resulta contraproducente, deberas tener una interrupcion de TX y un buffer circular, aseurandote que siempre se pueda vaciar.

El receptor si o si no lo vas a hacer por poll a los datos de la UART sino por interrupcion. Y luego dependiendo del tipo de datos pasara por una maquina de estados o ira a un buffer que luego se vaciara cuando posea tiempo el PIC.

Tambien coincido con manwewe, de buscar un micro que pueda hacer todo, especialmente si posee una interfaz TFT.. El gasto deberia ser casi comparable y tedrias un micro con muchas mas prestaciones.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: manwenwe en 27 de Marzo de 2017, 14:52:17
No había leido bien lo del TFT jeje. Con ese PIC por pequeño que sea el TFT no va a funcionar fluido. Vete a un PIC32MX o un PIC32MZ.

Saludos!
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 29 de Marzo de 2017, 23:13:04
Gracias por sus comentarios, e estado leyendo sobre los  Pic32 y veo que no es ccs exactamente el lenguaje, es c pero varían las instrucciones.

Veo mas fácil implementar en el código ya realizado lo que comenta killerjc. Implementado  interrupción uart y veo que este pic18f8722 trae 2 de ellas.

Ahora me surge una duda, y espero me ayuden por favor.

Para el 18f8722, cuales son los fuses correctos para obtener los 40Mhz(velocidad más alta de este pic) y con un cristal de cuarzo externo de 4 Mhz(ya que es el unico que tengo).

En verdad agradezco su ayuda.
 
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: manwenwe en 30 de Marzo de 2017, 04:44:25
Un apunte CCS y XC32 ambos son C. Otra cosa diferente es que en CCS tengas funciones precompilados que hagan ciertas cosas. En XC32 tienes librerías equivalentes.  Saludos.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 30 de Marzo de 2017, 14:32:16
Citar
Para el 18f8722, cuales son los fuses correctos para obtener los 40Mhz(velocidad más alta de este pic) y con un cristal de cuarzo externo de 4 Mhz(ya que es el unico que tengo).

Los FUSES van a depender del compilador que uses (en el sentido de como deben escribirse.

Con cristal de 4Mhz, No podes, por que el PLL es fijo de 4x, deberias poner un cristal de 10Mhz para obtener los 40Mhz y elegir HSPLL

La otra que te queda es usar el oscilador interno y pasarlo por el PLL, FUSE: INTOSCIO67, en el cual vas a poder llegar a los 32Mhz. Pero no solo los FUSES tenes que modificar, ya que eso solo indica la fuente del oscilador, sino que tambien deberas corregir los bits del registro OSCCON seleccionando la frecuencia a 8Mhz (porque default es 1Mhz) y luego el registro OSCTUNE para habilitar el PLL.

Es util mencionar que si tenes el PIC y no lo borraste, al final tenes el valor de calibracion que va en OSCTUNE para que cumpla los parametros del datasheet con los 8Mhz.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 01 de Abril de 2017, 00:15:02
Creo que esto funcionará. En fuses H4  y un cristal externo de 10 Mhz como lo dice Killerjc para consegir los 40Mhz.

En el pic 18F8722 seria:

#use delay(clock=40000000)

Código: C++
  1. #FUSES NOWDT,WDT128,H4,NOPROTECT,NOIESO,NOBROWNOUT,NOPUT,NOCPD,noSTVREN,nODEBUG,NOLVP,NOWRT,NOCPB,NOEBTRB,NOEBTR,CCP2C1,NOWRTD,NOWRTC,NOWRTB,NOFCMEN,LPT1OSC,MCLR,NOXINST,MCU

Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 08 de Abril de 2017, 10:58:43
Ahora estoy con el envío de datos a la TFT Nextion, solo que me encontre con un Warning que dice: interrupts disabled during call to prevent re-entrancy y es debido a la función que tengo a continuación:

Bueno, lo que hago es enviar los datos de las variables hacia la pantalla TFT cada 200ms (este tiempo puede variar) pero lo quise poner con un timer1 por que quiero que el envió sea temporizado y me tope con ese warning. Alguien a encontrado una solución a esto?.

#use delay(crystal=4000000) 

int desborde_tmr1=0;
char string_str[1];

Código: C
  1. #INT_timer1
  2.          void interrupcion_tmr1(void)
  3.          {  
  4.          set_timer1(40536);
  5.          desborde_tmr1++;  
  6.          if (desborde_tmr1==1)
  7.          {
  8.          
  9.          desborde_tmr1=0;
  10.          }
  11.          }

         setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);                  // Configuracion del Timer1 para clock interno = 1E6 dividido por 8
         enable_interrupts(INT_TIMER1);                                          // Habilita interrupción timer1
         enable_interrupts(GLOBAL);
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 08 de Abril de 2017, 11:04:51
Tal ves y mas que seguro es porque el tiempo consumido para :

- Generar el string que pedis, esto incluye pasar valores float a string que no es algo liviano ni rapido.
- Enviar todo el texto y encima quedarte en la interrupcion enviandolo, por que el fputs se queda encerrado alli hasta que se termine de enviar TODOS los datos que le pusiste.

Supera o posiblemente supere a la interrupcion del timer, es decir que podrian ocurrir 2 interrupciones mientras esta haciendose eso, de ocurrir esto apenas termine volveria a entrar a la interrupcion y seria algo de nunca terminar, jamas ejecutaria la parte de tu programa principal, por eso deshabilita las interrupciones.

Resumen:
Nunca pongas funciones bloqueantes y/o que consuman demasiado tiempo en una interrupcion. Para eso activa una flag y hacelo desde el programa principal.
Aclaro una cosa, no digo que no se pueda hacer, pero hay que tener cuidado.

La parte del envio si no queres que te bloquee el programa principal (por el fputs), lo podes hacer con la interrupcion del TX Y enviar desde un buffer.
Otro tema no hace falta que escribas TODO el texto cuando la mayoria son datos fijos:

Código: [Seleccionar]
"h0.val=%1.0f%c%c%c h1.val=%1.0f h2.val=%1.0f h3.val=%1.0f h4.val=%1.0f"Tenes 4 datos en fomato float, lo demas es fijo... porque darle todo el laburo de escribir todo de nuevo?
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 08 de Abril de 2017, 11:57:19
Como podría utilizar esas banderas que me decis?.  Lo intento con int flag bandera; pero no se donde colocarlas.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 08 de Abril de 2017, 16:20:30
Como crear y manejarse bandera:

Código: C
  1. #include <stdbool.h>
  2. bool bandera;
  3.  
  4. void Timer(void){
  5.         //Recargo Timer
  6.         //Borro Bandera de interrupcion
  7.         if(bandera){
  8.                 //Manejo de error en caso que reentre (si es que queres), sino omitis este if
  9.         }
  10.         bandera=true;
  11. }
  12.  
  13.  
  14. void main(void){
  15.         while(1){
  16.                 if(bandera){
  17.                         bandera = false;
  18.                         //Aca envio los datos
  19.                 }
  20.         }
  21. }
CSS Posee el int1. en ves de bool y usar el stdbool.h
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 16 de Abril de 2017, 19:08:22
 ;- :-)
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 25 de Mayo de 2017, 03:37:17
Que tal amigos del foro.

Estoy trabajando con el pic18f8722 y ahora veo algo muy raro en este pic.
No se por que pero los pines a los cuales no tengo conectado nada me dan un voltaje entre 1.5 volts y 0.8V. (El pic lo alimento con 5V)

Me di cuenta al momento de desconectar un sensor de corriente conectado al pin AN0; desconecte el sensor y observe una lectura en la lcd,  :shock:raro no  :shock:, después que observe que seguia midiendo sin tener el sensor conectado en esa patilla medí con mi volmetro y observe esa lectura de 1.5V.

Alguien me podría decir que pasa, esto es en todos los pines que no conecto algo, pensaría que es la impedancia de entrada que necesita o que?. También no se por que este pic tiene tantas conexiones a vc y gnd de alimentación.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 25 de Mayo de 2017, 15:04:13
Esta flotando el pin, no esta conectado a nada. Cuando esta como entrada no tenes nada que lo tenga a GND o VCC (como si ocurre en una salida ), por eso mismo cuando se quiere asegurar que una entrada se encuentre en un estado definido se necesita de un pull-up o pull-down externo.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 25 de Mayo de 2017, 16:33:59
Entonces tengo que asignar el estado de los pines del pic con set_tris_a(0b11100000);   dependiendo de las necesidades
output_a(0x00); ......  Para si no tenerlo flotando?.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 25 de Mayo de 2017, 16:54:36
No, si es una entrada del sensor, no los desconectes o si pensas desconectarlo ponele un pull-down. Ya que no sabes cuando es que esta desconectado para ponerlo como salida al pin.

De esa forma si lo desconectas detectas 0.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 25 de Mayo de 2017, 17:03:21
Ok, pull-down como la de la imagen que anexo?. Algo mas, si este voltaje esta presente en todos los pines, al asignarles un estado de salida en 0 conectado a tietta servirá?. Por que también la lectura del sensor brinca mucho por lo que implemente un filtro de media móvil y me ayudo, pero creo que también hay ruido en las patas del pic. Gracias tu pronta respuesta amigo.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 26 de Mayo de 2017, 09:13:35
Quiero compartir la solucion , a esto del voltaje presente en pines no utilizados del pic. Como bien dice killer nunca hay que dejar los pines al aire, se puede solucionar con una resistencia pull o configurando los Set_tris para asignarles un estado.

En mi caso opte por poner en cero las salidas no utilizadas configurando los set_tris y eureka.. :P, se soluciono, pues el voltaje que había en los s pines no utilizados desapareció.

También importante, en el pic 18f8722 la entrada analógica an4 o LVDIN, no lo pude configurar como un adC por que siempre mostró un voltaje a su salida a pesar de ponerle su set_tris.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 26 de Mayo de 2017, 13:43:47
Exacto, como en la imagen.

El problema de ponerlo como salida siguiendo el ejemplo que pasaste pero sin la resistencia, es si por ejemplo el sensor lo pusiste, esta activado lo cual pasarian los 5V al pin, y vos tenes la salida en 0V, haria que fluya una corriente grande por el pin, posiblemente quemando el pin/puerto.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 27 de Mayo de 2017, 10:13:50
Respecto a lo del PIN LVDIN que esta en la patilla 33 del PIC18F8722 por e leído que es para probar la detección de baja tensión.

Pero tengo muchas dudas,por que yo quería utilizar este pin como lectura del ADC AN4 pero me daba lectura de 1.5v mas o menos aun sin tener conectado mi sensor en ese pin del ADC. Me podrían ayudar a utilizar esa entrada correctamente como ADC?. O me podrían explicar mas acerca de ese pin?.




Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 27 de Mayo de 2017, 14:51:11
Ese pin como decis tiene 2 posiblidades...

- Digital para el GPIO
- Analogico para el ADC y el HLVD


El modulo HLVD esta desactivado.. Si queres usar estos modulos los dejas en analogico, si no pasas a digital. De querer usar el HLVD lo dejas en ananlogico y activas el modulo, En el modulo tenes que seleccionar que la tension proviene de esa entrada. Eso se compara con una referencia de 1.2V
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 28 de Mayo de 2017, 18:55:04
Entiendo killer, gracias por compartir. Referente al filtro del lectura media móvil tomo 20 muestras mas sin embargo en la LCD aun salta mucho los valores decimales. Cuantas muestras serán necesarias tomar sin que afecte o retarde mi programa?. Actualmente lo tengo a 4mhz del clock.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 28 de Mayo de 2017, 19:10:04
Por que haces una media movil?, por que no hacer directamente un promediado de 16 muestras? 16 en el sentido que la division sea un simple shift, ademas con 8 deberia ser suficiente.

Si ya salta puede ser que la entrada no sea del todo correcta, o es que estas midiendo mal por que el tiempo de adquisicion no es el adecuado, o tal ves sea la misma operacion para pasarlo a flotante lo que lo causa.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 29 de Mayo de 2017, 08:59:18
Brevemente, así es como tomo las lecturas del adc, sin la media móvil los valores variaban de 3 a 4 volts dentro del protoboard. Yo pensaba que era el ruido pero al parecer es otra la causa.

Ahora con esta media móvil los valores se mueven mucho solo en decimales. Quizás estén mal declaradas las variables Killer, tu me dirás..

Código: C#
  1. #include <18F8722.h>
  2.          #device ADC=10
  3.          #device *=16
  4.          #FUSES NOWDT                    //No Watch Dog Timer
  5.          #FUSES MCLR                     //No Watch Dog Timer
  6.          #FUSES XT                       //Crystal osc <= 4mhz
  7.          #FUSES PUT                      //Power Up Timer
  8.          #FUSES NOPROTECT                //Code not protected from reading
  9.          #FUSES BROWNOUT                 //Reset when brownout detected
  10.          #FUSES NOLVP                    //No low voltage programing, B3(PIC16) or B5(PIC18) used for I/O
  11.          #FUSES NOCPD                    //No EE protection
  12.          #FUSES NOWRT                    //Program memory not write protected
  13.          #FUSES NODEBUG                  //No Debug mode for ICD
  14.  
  15.          float Volt_AC_F1,Volt_AC_F2,volt_DC_12,valor_lm35,temp_lm35,ADC_CTE_DC_12,CTE_DC_12;
  16.          unsigned int16 ADC_F1,ADC_F2,ADC_CD_12;
  17.  
  18.           int16 filtro_medida_movil(void)
  19.          {
  20.          int j=0,k=0,x,t,w;                                                                            
  21.          int Muestras = 20;                                                                    
  22.          
  23.          set_adc_channel(0);                                                                            
  24.          for(j=0; j<Muestras;j++)                                                                
  25.          { ADC_F1+= read_adc(); delay_us(20); }                                                        
  26.          ADC_F1 /= Muestras+1;                                                                    
  27.          Volt_AC_F1 = ADC_F1*0.48875855327468230694037145650049;                                        
  28.          
  29.          set_adc_channel(1);                                                                            
  30.          for(k=0; k<Muestras;k++)                                                                  
  31.          { ADC_F2+= read_adc(); delay_us(20); }                                                        
  32.          ADC_F2 /= Muestras+1;                                                                  
  33.          Volt_AC_F2 = ADC_F2*0.48875855327468230694037145650049;                                        
  34.                  
  35.          set_adc_channel(2);                                                                            
  36.          for(x=0; x<Muestras;x++)                                                                  
  37.          { ADC_CD_12+= read_adc(); delay_us(20); }                                                      
  38.          ADC_CD_12 /= Muestras+1;                                                                
  39.          volt_DC_12 = ADC_CD_12*0.04887585532746823069403714565005;                                  
  40.          
  41.          set_adc_channel(3);                                                                            
  42.          for(t=0; t<Muestras;t++)                                                                
  43.          { valor_lm35+= read_adc(); delay_us(20); }
  44.          valor_lm35 /= Muestras+1;                                                                
  45.          temp_lm35 = valor_lm35*0.48875855327468230694037145650049;                                    
  46.          
  47.          set_adc_channel(5);                                                                            
  48.          for(w=0; w<Muestras;w++)                                                                
  49.          { ADC_CTE_DC_12+= read_adc(); delay_us(20); }
  50.          ADC_CTE_DC_12 /= Muestras+1;                                                            
  51.          CTE_DC_12 = ADC_CTE_DC_12*0.06109481915933528836754643206256;                                  
  52.          return((int16)(Volt_AC_F2,Volt_AC_F1,volt_DC_12,temp_lm35,CTE_DC_12));
  53.          }


En el main tengo lo siguiente:

         setup_adc_ports(AN0_TO_AN5|VSS_VDD);
         setup_adc(ADC_CLOCK_INTERNAL);

Y como veras en el code, con 20 muestras apenas estabilice un poco, ahora se mueven mucho las decimales.


Podrías decirme que es lo que causa que se mueva mucho el adc?.

Algo mas el pic lo tengo a 4mhz
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 29 de Mayo de 2017, 17:21:14
Hay un par de cosas que no entiendo a que queres llegar, pienso que queres que te devuelva todos los valores, pero te debe estar devolviendo 1 solo ( por el return como lo tenes).
Ademas por que devolver un entero... ¿cuando vos buscas decimales ?..

Este numero:

0.48875855327468230694037145650049

Es irrealizable en un micro. Lo maximo que se le aproxima es:
0.48875856399536133 expresado en un float como 0x3efa3e90 segun la IEEE 754.

Asi que ahi ya tenes un pequeño error.

Por otro lado esto:

Código: C
  1. return((int16)(Volt_AC_F2,Volt_AC_F1,volt_DC_12,temp_lm35,CTE_DC_12));

Si no falla mi C, quiere decir que va a castear cada uno de los valores, pero el unico que va a devolver casteado es el CTE_DC_12, los demas no.

Si lo haria y pudiera ponerle una variable dentro del set_adc_channel seria asi:


Código: C
  1. #define MUESTRAS (1<<3)
  2.  
  3. float ADC_Values[5];
  4. const int8 ADC_Channels[5] = {0,1,2,3,5,0xFF};
  5. const float ADC_Coef[5] = {0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.06109481915933528836754643206256};
  6.  
  7.  
  8. void filtro_promediado(float * ADC_Val)
  9. {
  10.  
  11.       int8 i,j;
  12.       for(i=0; i!=0xFF ; i++)
  13.       {
  14.             set_adc_channel(ADC_Channels[i]);
  15.             delay_us(20);
  16.             for(j=0; j<MUESTRAS;j++) {
  17.                   ADC_Val[i] = read_adc();
  18.             }
  19.             ADC_Val[i] /= MUESTRAS;
  20.             ADC_Val[i] *= ADC_Coef[i];
  21.       }
  22. }

Tambien buscaria como configurar el ADC para que use 20 TAD para el tiempo de adquisición.

Citar
Podrías decirme que es lo que causa que se mueva mucho el adc?.

- Que el tiempo de adquisicion no sea el correcto lo cual tendrias una lectura erronea. Esto depende del circuito.
- Errores al codificar en 32 bits algun numero con muchos decimales como comente arriba. y al hacer la operacion arroja un resultado que no es el adecuado comparado con usar todos los numeros.
- Que la tension realmente varie demasiado en la entrada del pin del ADC
- Que fluctue la alimentacion al momento de medir
- No cuento errores que pueda tener el mismo ADC.

En si, si todo esta correcto, VDD se mantiene constante, La tension de entrada al pin del ADC igual, y se cumple los tiempos deberia fluctuar a lo sumo 1 bit o 2 como maximo, con lo cual un promediado de 8 muestras ya te lo limpiaria.
Hay que tratar de determinar cual es el problema en realidad. Podrias mostrar primero los valores obtenidos por el ADC para ver si es ahi donde cambia tanto.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 29 de Mayo de 2017, 18:29:19
 

Una pregunta y perdona mi ignorancia, que significa esta linea: #define MUESTRAS (1 << 3)   (¿cuantas muestras va a tomar? o ¿como la interpreto?)
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 29 de Mayo de 2017, 22:31:57
Cuando tenes valores constantes, no es necesario crear una variable. Por ejemplo del modo que vos hiciste "Muestras" el compilador va a reservar un lugar en la RAM para Muestras, le va a cargar un valor, luego cuando hagas Muestras + 1 , va a generar las instrucciones para sumarle 1.

En mi caso al usar el #define le estoy diciendo al compilador que cuando encuentre la palabra MUESTRAS en el codigo simplemente lo reemplaze con (1<<3) es decir 8. En resumen es como si tuvieras un valor constante, el cual no se reserva RAM para este, ni tampoco deberia generar instrucciones si sumas una constante como es si pones un MUESTRAS +1, ya que el compilador luego de reemplazarlo se daria cuenta que el numero es constante y por lo tanto reemplazaria por un numero simple en ese lugar.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 30 de Mayo de 2017, 12:50:05
Otra vez yo preguntando killer y perdona eso pero me a gustado mucho la forma en que reduces el code, solo que no entiendo estas lineas.

Porqué el 0xFF en ese vector?.. Chanels séra [6] en lugar de 5, por que así me da error al compilar.

const int8 ADC_Channels[5] =
{0,1,2,3,5,0xFF};

Y aquí también como se interpreta ese 0xFF del for
 
      for(i=0; i!=0xFF ; i++)

Aquí seria += para ir acumulando las lecturas en el adC?

ADC_Val[ i ] = read_adc();

Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 30 de Mayo de 2017, 14:08:02
Si en realidad cometi MAS errores. Luego te doy el codigo coorregido y te digo los errores que tuve. Primero te cuento mis intenciones.

Cuando intente reducir el codigo me encontre que no utilizas las entradas 0,1,2,3,4 sino que la ultima es el 5. Es decir no son todas seguidas.

Una solución es en el codigo fijarse que si el indice es el 4, usar el canal 5. Esta es una solucion muy simple, pero que si algun dia cambias las entradas o la cantidad de entradas tendrias que modificar el codigo. Lo cual no sirve, y es mejor un codigo que pueda ser reutilizado

La otra solucion fue hacer una tabla. De los canales y coeficientes.

Código: C
  1. const int8 ADC_Channels[5] = {0,1,2,3,5};

Esto me permite que yo pueda cambiar el orden de las entradas leidas o coeficientes sin tener que cambiar el codigo, lo cual me permite reutilizarlo.

Y aqui llega un nuevo problema.... Cuando se cuando se terminan las entradas?

Existen 2 formas de realizarlo.. La primera y mas simple es agregar un termino que finalice el loop. Como yo hice fue agregar un 0xFF, entonces la idea es que cuando ADC_Channels sea igual a 0xFF salga. (Este es uno de mis errores). Entonces el codigo correcto seria asi:

Código: C
  1. #define MUESTRAS (1<<3)
  2.  
  3. float ADC_Values[5];
  4. const int8 ADC_Channels[6] = {0,1,2,3,5,0xFF};
  5. const float ADC_Coef[5] = {0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.06109481915933528836754643206256};
  6.  
  7. void filtro_promediado(float * ADC_Val)
  8. {
  9.  
  10.       int8 i,j;
  11.       for(i=0; ADC_Channels[i]!=0xFF ; i++)
  12.       {
  13.             set_adc_channel(ADC_Channels[i]);
  14.             delay_us(20);
  15.             for(j=0; j<MUESTRAS;j++) {
  16.                   ADC_Val[i] = read_adc();
  17.             }
  18.             ADC_Val[i] /= MUESTRAS;
  19.             ADC_Val[i] *= ADC_Coef[i];
  20.       }
  21. }

Otra forma de saber cuando termina es darle de antemano la cantidad. Utilizando el operador sizeof, para esto ya no utilizamos mas un termino para indicarnos el fin. Lo cual hace mas intuitivo la parte de elegir los canales y coeficientes, ya que si tenes 5 canales necesitas si o si 5 coeficientes y 5 lugares donde ponerlo.

Código: C
  1. #define MUESTRAS (1<<3)
  2. #define CANT_CANALES 5
  3.  
  4. float ADC_Values[CANT_CANALES];
  5. const int8 ADC_Channels[CANT_CANALES] = {0,1,2,3,5};
  6. const float ADC_Coef[CANT_CANALES] = {0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.06109481915933528836754643206256};
  7.  
  8. void filtro_promediado(float * ADC_Val, int8 Asize)
  9. {
  10.  
  11.       int8 i,j;
  12.       for(i=0; i < Asize ; i++)
  13.       {
  14.             set_adc_channel(ADC_Channels[i]);
  15.             delay_us(20);
  16.             for(j=0; j<MUESTRAS;j++) {
  17.                   ADC_Val[i] = read_adc();
  18.             }
  19.             ADC_Val[i] /= MUESTRAS;
  20.             ADC_Val[i] *= ADC_Coef[i];
  21.       }
  22. }

Para esto vamos a llamar a la funcion de esta forma:

Código: C
  1. filtro_promediado(ADC_Values, (sizeof ADC_Values)/(sizeof ADC_Values[0]))

sizeof se precalcula antes por el compilador y luego es reemplazado por una constante en el programa. Es decir no es una funcion que va a tener sus instrucciones en el microcontrolador.

--------------

Si aun asi queres mas generalizacion de la funcion podes hacer:

Código: C
  1. #define MUESTRAS (1<<3)
  2. #define CANT_CANALES 5
  3.  
  4. float ADC_Values[CANT_CANALES];
  5. const int8 ADC_Channels[CANT_CANALES] = {0,1,2,3,5};
  6. const float ADC_Coef[CANT_CANALES] = {0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.06109481915933528836754643206256};
  7.  
  8. void filtro_promediado(float * ADC_Val, const int8 * ADC_Chan, const float * ADC_Cof, int8 Asize)
  9. {
  10.  
  11.       int8 i,j;
  12.       for(i=0; i < Asize ; i++)
  13.       {
  14.             set_adc_channel(ADC_Chan[i]);
  15.             delay_us(20);
  16.             for(j=0; j<MUESTRAS;j++) {
  17.                   ADC_Val[i] = read_adc();
  18.             }
  19.             ADC_Val[i] /= MUESTRAS;
  20.             ADC_Val[i] *= ADC_Cof[i];
  21.       }
  22. }

El #define CANT_CANALES nos permite que si por algun motivos no ponemos la cantidad correcta tengamos un error y todos los arrays tengan el mismo largo.
El pasar todos los punteros permite que no importa el nombre que le des vos a tus arrays siempre y cuando lo pases en orden.
Respecto a la proteccion para que se usen solo los valores dados y no entradas de mas que no estan contempladas en el array, esto depende de quien hace el codigo, ya que posee un campo de "tamaño"
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 30 de Mayo de 2017, 20:57:20
Gracias  ((:-)) muy bien explicado. Voy a pasarlo al compilador y veremos que pasa. Ten agradezco..
Como paso esa funcion dentro del while (true){


Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 03 de Julio de 2017, 10:51:06
Killer JC.  No encontré como hacer la función void dentro del while para que me compile correctamente el code que pusiste de ejemplo:

Citar
#define MUESTRAS (1 << 3)
#define CANT_CANALES 5
 
float ADC_Values[CANT_CANALES];
const int8 ADC_Channels[CANT_CANALES] = {0,1,2,3,5};
const float ADC_Coef[CANT_CANALES] = {0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.48875855327468230694037145650049,0.06109481915933528836754643206256};
 
void filtro_promediado(float * ADC_Val, const int8 * ADC_Chan, const float * ADC_Cof, int8 Asize)
{
 
      int8 i,j;
      for(i=0; i < Asize ; i++)
      {
            set_adc_channel(ADC_Chan);
            delay_us(20);
            for(j=0; j<MUESTRAS;j++) {
                  ADC_Val = read_adc();
            }
            ADC_Val /= MUESTRAS;
            ADC_Val *= ADC_Cof;
      }
}

Esto me marca error const int8 * ADC_Chan, Asize y que significa #define MUESTRAS (1<< 3)

Anexo el code en c.

Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 19 de Julio de 2018, 10:40:31
Alguien sabe por que me aparece este error en el proteus al simular este filtro de medida móvil?

El mensaje del proteus es el siguiente:

Código: C++
  1. [PIC18 ADC] PC=0x0252. ADC conversion started before 'wait' time has expired following previous conversion or channel change. [U1]

Dice algo de los tiempos de carga del canal, pero donde poner esos retardos o es el proteus el que no funciona bien?. El pic es el 4550 y lo estoy utilizando a 48Mhz.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 19 de Julio de 2018, 12:07:07
cuando vos cambias de canal, o vas a comenzar otra muestra, dependiendo del ADC necesita un pequeño tiempo para cargarse al voltaje correcto, y mientras mayor la resistencia a la entrada del ADC mayor el tiempo a esperar. Es lo que se conoce como tiempo de adquisicion. Algunos PICs permiten modificar el tiempo de adquisicion, otros es fijo, y asi varian con cada familia.

En resumen el proceso es un tiempo de adquisicion (capacitor conectado al circuito), y un tiempo de conversion (capacitor conectado al ADC).
Luego de una conversion el capacitor se descarga, al cambiar de canal el capacitor necesita acomodar la tension que posee dentro, entonces necesitas esperar un tiempo ANTES de la proxima conversion.. Algo asi:

Código: C
  1. set_adc_channel(1)
  2. delay_us(10);           // Este tiempo es parte de la adquisicion.
  3. valor = read_adc();
  4. set_adc_channel(0)
  5. delay_us(10);           // Este tiempo es parte de la adquisicion.
  6. valor = read_adc();

Obviamente el tiempo de adquisicion va a depender de tu circuito. el datasheet explica bien como calcularlo. A su ves el tiempo de adquisicion se separa en otros mas.
Y el tiempo de adquisicion debe cumplirse para que los valores del datasheet del ADC se cumplan.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 19 de Julio de 2018, 12:22:59
KILLER_JC, Siempre atento a responder nuestras dudas. Un agradecimiento.

E visto la hoja de datos, sin embargo, en este caso no se donde colocar bien el o los delay para esto:

Código: C++
  1. .   int8 i,j;
  2.  
  3.          for(i=0; i < Asize ; i++)
  4.  
  5.          {
  6.             set_adc_channel(ADC_Chan[i]);
  7.  
  8.             delay_us(20);
  9.             for(j=0; j<MUESTRAS;j++) {
  10.                   ADC_Val[i] = read_adc();
  11.             }
  12.  
  13.             ADC_Val[i] /= MUESTRAS;
  14.             ADC_Val[i] *= ADC_Cof[i];
  15.          }


Por que al ser array la lectura de los canales es diferente estar colocando el de delay para cada canal por separado.

Quizás sera que se deberá utilizar algúna bandera ?. O algún timer del pic para tomar las muestras.

Pero si es como bien dices KILLER, ahora con el pic a 4 MHz trabaja bien y no muestra el warning, sin embargo  lo pretendo tener trabajando a 48Mhz.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 19 de Julio de 2018, 15:38:23
Código: C
  1. delay_us(20);
  2.             for(j=0; j<MUESTRAS;j++) {
  3.                   ADC_Val[i] = read_adc();
  4.             }

por esto:
         
Código: C
  1. for(j=0; j<MUESTRAS;j++) {
  2.                   delay_us(20);
  3.                   ADC_Val[i] = read_adc();
  4.             }

tal ves no afecte (hay que calcularlo), pero si queres sacar ese warning que te da el proteus es asi.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 20 de Julio de 2018, 09:52:06
 ((:-)) :-/ :mrgreen:  excelente!!!
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: Abner_emanuel en 05 de Agosto de 2018, 10:28:41
Ahora puedo ver correctamente las lecturas de los canales seleccionados. Ahora me surge una pregunta.

Es posible lograr que este algoritmo lea los ADC a 10ks/s (10kilo muestras por segundo). Si estoy a 48Mhz y un cristal externo de 4Mhz?. Y leyendo 10 canales analógicos?. AN0 a AN9 del 18f4550.
Título: Re:Comunicación serie de 2 Pic a Diferente Frecuencia
Publicado por: KILLERJC en 05 de Agosto de 2018, 11:06:10
La velocidad maxima del ADC esta definida en el datasheet.

para un PIC, su ciclo TAD, y donde su reloj sea:
- alimentado por FOSC tenes que el TAD debe ser de un minimo de 0.7us y maximo de 25us
- alimentado por el RC que posee 1us maximo, el minimo no esta definido. (oscilador interno del ADC)

En resumen se podria decir que el oscilador del mismo ADC ya le da un tiempo suficiente.
Ahora... necesitamos saber cuantos ciclos TAD necesitas.

Para la conversion son entre 11 y 12 TAD, supongamos 12.
Para la adquisicion depende de tu circuito, si no posee una gran impedancia de entrada, podrias seleccionar el minimo. El minimo,maximo permitido por el hardware son:
- FOSC: 0TAD y 12TAD
- RC AD: 1TAD y 12TAD  (podes seleccionar 0, pero le incluye 1 si o si)
0.2us del tiempo de descarga del capacitor.

En el peor de los casos serian 12TAD conversion + 12TAD adquisicion + 0.2us, suponiendo 1us = TAD, tenes que 24.2us de conversion. Por simplicidad omitimos los cambios de canal, el for, etc, que depende del compilador como lo tradusca pero masomenos seria 1 salto, 1 incremento, 1 de comparacion, 2,3 o 4 para cambiar de canal, 1 incio de conversion, 1 salto espera  , aproximadamente unos 0.8us mas quedado asi unos 25us para redondear.

A 25us cada conversion, tenes que podes samplear maximo 40Ks/s, en 10 entradas son 4Ks/s.  ( retirando el delay que hay puesto )
Aunque disminuyas el tiempo de adquisicion a 1 TAD para el caso del RC, tendrias un maximo de 70Ks/s ( suponiendo que puedas disminuirlo )

Esto es lo que puedo asegurar con el datasheet.
La otra es unicamente tomar 8 bits, usar el FOSC para que el TAD sea menor de lo que especifica el datasheet, supongamos 0.5us, y ver si los resultados son conformes, discriminando los ultumos 2 bits de menos peso. Ya aca entramos en un terreno donde las especificaciones del datasheet no se cumplen, por no utilizarlo correctamente.