Autor Tema: Libreria para Max6675 en CCS  (Leído 6953 veces)

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

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #15 en: 15 de Enero de 2021, 16:03:02 »
Si perdon... ahí te lo corrijo.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #16 en: 17 de Enero de 2021, 21:44:00 »
Código: C
  1. volatile uint8_t tcState;  // Usaria static, solo que el compilador CCS no le va a bien demasiados archivos.
  2.  
  3. #INT_TIMER0                                                                        //Ojo que asi no se llama, pero no uso CCS demasiado
  4. void intetTm0(void) {
  5.   tcInterruptTimerHandler();
  6. }
  7.  
  8.  
  9.  
  10. float do_everything(void)
  11. {
  12.   // Defino las variables
  13.   float resultado = 0;
  14.  
  15.  
  16.   switch (tcState) {
  17.     case 0:
  18.       init_TC();
  19.       set_timer0(3036); //Valor al timer
  20.       enable_interrupts(INT_TIMER0);
  21.       tcState++;
  22.       break;
  23.     case 1:
  24.       //Espero por el timer
  25.       break;
  26.     case 2:
  27.       resultado = toFloat_TC(sortout(read_TC()));
  28.       tcState = 0;
  29.       break;
  30.     default:
  31.       // Por si las dudas
  32.       tcState = 0;
  33.       break;
  34.   }
  35.  
  36.   return resultado;
  37. }
  38.  
  39. void tcInterruptTimerHandler(void) {
  40.   if(tcState==1) {
  41.     tcState++;
  42.   } else {
  43.     tcState = 0;
  44.   }
  45.   disable_interrupts(INT_TIMER0);
  46. }
  47.  
  48. void main()
  49. {
  50. lcd_init();      
  51. setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);                
  52. enable_interrupts(global);                                                       //Activamos las interrupciones globales
  53.  
  54.  while(true){
  55.    float aux;
  56.    aux = do_everything();
  57.    if (aux != 0){
  58.       lcd_gotoxy(1,2);
  59.       printf(lcd_putc,"Todopic %3.2f%cC ",aux,0xDF);  
  60.    }
  61.  }
  62. }

Solo una cosa, recorda que el codigo NO ESTA probado, simplemente lo acabo de editar en el bloc de notas y te lo estoy entregando..
« Última modificación: 17 de Enero de 2021, 21:51:16 por KILLERJC »

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 56
Re:Libreria para Max6675 en CCS
« Respuesta #17 en: 18 de Enero de 2021, 12:44:46 »
Grcias Killerjc. Ahora lo compilo en ccs c y pongo resultados. Gracias nuevamente por responder.

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 56
Re:Libreria para Max6675 en CCS
« Respuesta #18 en: 20 de Enero de 2021, 00:07:01 »
KILLERJC.

Ahora pude probar el código que me colocaste en el post.  Ahora funciona..  :P

Aquí el code para 20Mhz ...

Código: C++
  1. float do_everything(void);
  2.          void tcInterruptTimerHandler(void);
  3.          
  4.          volatile int8 tcState;
  5.          float aux;
  6.                  
  7.          #INT_TIMER0                                                                      
  8.          void intetTm0(void)
  9.          {
  10.          tcInterruptTimerHandler();        
  11.          }        
  12.          
  13.          float do_everything(void)
  14.          {
  15.          float resultado = 0;
  16.  
  17.          switch(tcState)
  18.          {
  19.          case 0:
  20.                   init_TC();
  21.                   set_timer0(3036);                                  // Valor al timer
  22.                   enable_interrupts(INT_TIMER0);
  23.                   tcState++;                  
  24.                   break;
  25.          case 1:
  26.                                                                      // Espero por el timer                  
  27.                   break;
  28.                  
  29.          case 2:  
  30.                   resultado = toFloat_TC(sortout(read_TC()));
  31.                   tcState = 0;
  32.                   break;
  33.                   default:                  
  34.                   tcState = 0;                                       // Por si las dudas
  35.                   break;
  36.          }
  37.                   return resultado;
  38.          }
  39.  
  40.          void tcInterruptTimerHandler(void) {
  41.          if(tcState==1) {output_toggle(pin_b0);
  42.          tcState++;
  43.          } else {
  44.          tcState = 0;
  45.          }
  46.          disable_interrupts(INT_TIMER0);
  47.          }
  48.          
  49.          void main()
  50.          {
  51.          lcd_init();      
  52.          setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);                  
  53.          set_timer0(3036);
  54.          enable_interrupts(INT_TIMER0);  
  55.          enable_interrupts(global);                                                       //Activamos las interrupciones globales
  56.          
  57.          while(true){
  58.          aux = do_everything();
  59.          if (aux != 0){
  60.          lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",aux,0xDF);        
  61.          }
  62.          }
  63.          }

En la imagen del proteus se muestra el tiempo de los 200 ms del timer0 obtenida con un output_toggle(pin_b0); del pin_b0.

Ahora tengo una pregunta... veo que ¿si dentro del ciclo infinito while (true) { genero alguna demora con delay_ms(); ese delay_ms(x); esos X tiempo se suma a los 200 ms del timer0, eso por que?. Si supuestamente esos 200ms del timer0 son continuos y fijos.

Ahora también lo probé físico y funciona!!.


« Última modificación: 20 de Enero de 2021, 00:12:53 por Ruco »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #19 en: 20 de Enero de 2021, 12:34:01 »
Por eso mismo te dije que ibas a tener que cambiar toda la forma de programar.

Como regla general

- Lo que ocupa demasiado tiempo, hacerlo en loop (while) del main.
- En las interrupciones, en lo posible entrar y salir.

Pero eso es por lo general. Esos son buenos lineamientos si consideras que podes llegar a tener varias interrupciones, y mucho mas cuando trabajas con comunicaciones (UART) que puedan implicar recibir muchos datos y no leerlos.

Entonces voy a explicarme un poco mas sobre tu programa:

Código: C
  1. int16 read_TC(void)               //It takes 200ms (ish) for the MAX6675 to perform a conversion
  2.          {
  3.          int8 i;
  4.          int16 data;
  5.          output_low(TC_CS);            //stop any conversion processes
  6.          delay_ms(1);               //and give it some time to power up (not very much, admittedly)
  7.            
  8.          for (i=0;i<16;i++){
  9.          shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
  10.          output_high(TC_CLK);
  11.          delay_us(100); //Descomentar si usa crystal mayor a 10MHz
  12.          output_low(TC_CLK);
  13.          delay_us(100);
  14.          }

Esa función de lectura, es lo mismo que un SPI, la diferencia es que tiene 16 bits. Que los PICs vienen fijo de 8, pero eso no quita que puedas usar el SPI dos veces y su interrupción para comunicarte. De esa forma no usas demoras.
Si comenzas a sumar delays, tenes 1ms al comienzo, luego 0.2ms por cada bit, tenes un total de 4.2ms en esa comunicación del SPI.


Código: C
  1. int16 sortout(int16 raw)
  2.          {
  3.          return(0x0FFF & (raw>>3));      //returns only the bits converning temperature
  4.          }
  5.  
  6.          float toFloat_TC(int16 tmp)
  7.          {
  8.          return((((float)tmp)-48.725)/1.9835);
  9.          }

La funcion sortout, no es problema, ya que una AND y un shift no son demasiados costosos computacionalmente. Pero el toFloat_TC si, una division de flotantes no es nada "barato" y se lleva su tiempo. Y ni hablar el LCD que esta lleno de demoras tambien.

Por eso mismo no esta puesto en la interrupción.

Ahora veamos el while y el porque se suma tu demora.

Código: C
  1. while(true){
  2.    aux = do_everything();
  3.    if (aux != 0){
  4.       lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",aux,0xDF);        
  5.    }
  6. }

Observa como funciona. Se obtiene lo que se devuelve desde do_eveything, esta funcion va a devolver 0 siempre y cuando este esperando el tiempo necesario y no tenga un resultado valido (luego del proceso de lectura)
Entonces al no tener resultado valido directamente no grafica naada en el LCD, por eso esta el if.

Ahora tenemos que tener en cuenta algunas cosas.
- Tu interrupcion lo unico que hace es contar 200ms y decir "YA TERMINE!" y para de contar
- Si lo lees tarde es tu problema. Lo lees unicamente cuando ejecutas el do_everything.

Si vos pones un delay supongamos de 500ms. entonces el timer recien habia comenzado a contar, se van a cumplir los 200ms del timer, va a decir YA TERMINE!, pero no va a pasar nada, ya que todavia faltan 300ms de ese delay que tenias. Esto suponiendo que no tenes ninguna otra instruccion antes. En este caso no se "sumaria", quedaria lo que falta, el codigo seria:

Código: C
  1. while(true){
  2.    aux = do_everything();
  3.    if (aux != 0){
  4.       lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",aux,0xDF);        
  5.    }
  6.    delay_ms(500);
  7. }

Ahora, que pasa si agregamos MAS instrucciones, supongamos que tengo una funciona que tarda 300ms en ejecutarse

Código: C
  1. while(true){
  2.    aux = do_everything();
  3.    if (aux != 0){
  4.       lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",aux,0xDF);        
  5.    }
  6.    mi_funcion_que_tarda_300_ms();
  7.    delay_ms(500);
  8. }

Ahora esos 200ms van a pasar en esa funcion nueva, pero hasta que se ejecute el do_everything de nuevo necesita 100ms mas de esa función y los 500ms del delay.
Entonces ahora vas 600ms atrasado.


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

Que pasaría si pongo todo en la interrupción?
Y ahora tal ves los delays de 500ms de mi loop principal por ahí sean de 500, 524, 551 ms etc. Puede ser cualquier valor. Ya que segun lo que tarde la interrupcion, es lo que va cambiar mi tiempo.
Vos debes saber que mientras este en la funcion de interrupcion, todo lo demas se detiene, asi que mientras mas tiempo esté dentro de la interrupcion, mas se atrasa o cambia el comportamiento del programa principal. Hay cosas que no son importantes en tiempos, pero otros si.

Si queres paso todo el código a la interrupción, solo vas a tener que tener en cuenta eso. Y otra cosa mas estamos hablando de únicamente una sola interrupción. Ya que mientras esta encerrado en una interrupcion usualmente no puede atender otra, hasta que termina (excepciones a esto son interupciones con prioridades que tiene PIC18 en adelante)

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

¿Qué código usaste que te dio problemas?

Una cosa mas, muchos de las librerías están realizadas todo por software, como te dije el MAX6675 lo podes hacer con 2 interrupciones por SPI + 1 interrupcion del Timer, pero como la interrupción es demasiado dependiente del hardware, la librería haría que sea poco flexible, por eso mismo la mayoría de las librerías que vas a encontrar, especialmente las de Arduino, todos los SPI están realizados por software.


Alguna forma sencilla para reducir estos problemas es reducir y mantener unicamente un delay, por ejemplo uno de 10ms, nuestra funciona que tenia una demora de 300ms antes porque queriamos que se ejecutara cada 300ms, ahora le ponemos un contador, que cuando entre 30 veces, lo ejecute, y le quitamos esos delays.

Código: C
  1. while(true){
  2.    aux = do_everything();
  3.    if (aux != 0){
  4.       lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",aux,0xDF);        
  5.    }
  6.    if(contador_mi_funcion++ == 30) {
  7.       mi_funcion_sin_demoras()
  8.       contador_mi funcion =0;
  9.     }
  10.    delay_ms(10);
  11. }
« Última modificación: 20 de Enero de 2021, 12:40:50 por KILLERJC »

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 56
Re:Libreria para Max6675 en CCS
« Respuesta #20 en: 20 de Enero de 2021, 13:31:39 »
Saludos Killerjc me queda claro y es exactame te a lo me referia. Los tiempos se van sumando. Cual seria la mejor solucion para optimizar el codigo y hacerlo mas efectivo sin tantas demosras en cuestion de la libreria del max6675. Olvidandonos de los delay denteo del while(true)?. Casi todo dentro del timer como mencionaste?... o hacetlo spi por harware y de igualmanera usando interrupvuon del timer?... Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #21 en: 20 de Enero de 2021, 13:56:25 »
Todo va a depender de tu proyecto de las cosas que pienses en agregarle, etc, en realidad tenes que verlo como un todo.

Si no vas a usar otra interrupcion, y tampoco te importa algunos milisegundos de mas en tu programa principal, llevamos todo eso a la interrupcion.

Vos luego vas a tener que definir si lo queres ciclico, o si queres que no siempre se muestre en el LCD, etc. Como dije antes, depende de que necesitas que haga el codigo. Porque puedo programarlo de una forma, pero luego al querer agregar otra terminas con otro problema.

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 56
Re:Libreria para Max6675 en CCS
« Respuesta #22 en: 20 de Enero de 2021, 14:04:33 »
Ok. Yo como.bien lo dices. Depende de como este  todo el cosigo a la necesidad. E aprendido mucho en este foro gracias apersonas como tu. Te agradezco tanto tu tiempo.

Solo algo mas. Como seria pasarlo lo mas posible del codigo dentro del timer?...

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #23 en: 20 de Enero de 2021, 15:48:49 »
Es decir hacerlo todo en la interrupcion, y el while te queda para lo que quieras.

Así como esta el código, cada 400ms tendrías una conversión, si lo queres cada 200ms hay que modificar un poco el código.

Código: C
  1. float do_everything(void);
  2.  
  3. volatile int8 tcState;
  4.                
  5. #INT_TIMER0                                                                      
  6. void intetTm0(void)
  7. {
  8.   set_timer0(3036);
  9.   do_everything();  
  10. }        
  11.        
  12. void do_everything(void)
  13. {
  14.   float resultado = 0;
  15.  
  16.   if(!tcState){
  17.     init_TC();
  18.     tcState = 1;
  19.   } else {
  20.     resultado = toFloat_TC(sortout(read_TC()));
  21.     lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",resultado,0xDF); // No es necesario imprimir todo, podes solo imprimir el numero        
  22.     tcState = 0;
  23.   }
  24. }
  25.  
  26.  
  27. void main()
  28. {
  29.   lcd_init();      
  30.   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);                  
  31.   set_timer0(3036);
  32.   enable_interrupts(INT_TIMER0);  
  33.   enable_interrupts(global); //Activamos las interrupciones globales
  34.  
  35.   while(true){
  36.   }
  37. }

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 56
Re:Libreria para Max6675 en CCS
« Respuesta #24 en: 22 de Enero de 2021, 02:57:59 »
KillerJC, así como mencionas queda mejor.

Creo que así queda mejor por que realiza independientemente el proceso del MAX6675. Se puede verificar que los 400ms del sensor son tiempor constantes aunque haya retardo de 500ms en el while (true).

Código: C++
  1. void do_everything(void);
  2.          
  3.          volatile int8 tcState;
  4.          float resultado = 0;
  5.                  
  6.          #INT_TIMER0                                                                      
  7.          void intetTm0(void)
  8.          {
  9.          set_timer0(3036);
  10.          do_everything();  
  11.          }        
  12.    
  13.          void do_everything(void)
  14.          {
  15.          if(!tcState){
  16.          init_TC(); output_toggle(pin_b0);
  17.          tcState = 1;
  18.          } else {        
  19.          tcState = 0;
  20.          }
  21.          }
  22.  
  23.          void main()
  24.          {
  25.          lcd_init();      
  26.          setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);                  
  27.          set_timer0(3036);
  28.          enable_interrupts(INT_TIMER0);  
  29.          enable_interrupts(global);                                                       //Activamos las interrupciones globales
  30.          
  31.          while(true){
  32.          resultado = toFloat_TC(sortout(read_TC()));
  33.          lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",resultado,0xDF); // No es necesario imprimir todo, podes solo imprimir el numero  
  34.          output_high(pin_b1); delay_ms(500);
  35.          output_low(pin_b1);  delay_ms(500);
  36.          }
  37.          }


Si coloco:

Código: C++
  1. resultado = toFloat_TC(sortout(read_TC()));
  2.          lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",resultado,0xDF); // No es necesario imprimir todo, podes solo imprimir el numero

dentro de la función void do_everything(void) me marca unos warning que dicen... >>> Warning 216  Interrupts disabled during call to prevent re-entrancy:  (@delay_ms1).

Por eso creu que es mejor sacarlo de ahi y colocarlo en el while(true), ya que ahi esta libre de Warning.

KillerJC

Citar
Así como esta el código, cada 400ms tendrías una conversión, si lo queres cada 200ms hay que modificar un poco el código.

Mencionaste de esos 400ms que ahora los vemos en el proteus; y mencionas también que se pueden reducir a 200ms, como se haria eso?...


En la imagen los 400ms del sensor y los 500ms de un led parpadeante
« Última modificación: 22 de Enero de 2021, 03:00:52 por Ruco »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #25 en: 22 de Enero de 2021, 11:31:10 »
En tu codigo es como que esta todo aparte, ya no tiene sentido.
Vos tenes 2 partes a tener en cuenta y es necesario tener en claro:

init_tc() es la funcion que inicia la conversion. Espero el 200ms
read_tc() es la funcion que lee la conversion una ves que termino el tiempo.


Esas dos funciones tienen que estar separadas por 200ms, despues puede haber el tiempo que sea entre que termino read_tc y comienza el otro init_tc.

Vos estas midiendo temperatura. La temperatura normalmente no cambia RAPIDO, es un proceso lento, por lo que no tiene ningun sentido volverse loco con que si o si lo haga cada 200ms otra lectura.  Si lo haces cada 1 segundos te va a sobrar.

Citar
dentro de la función void do_everything(void) me marca unos warning que dicen... >>> Warning 216  Interrupts disabled during call to prevent re-entrancy:  (@delay_ms1).

Desactiva las interrupciones debido a que:
el LCD tarda demasiado.
el codigo de division de float tarda demasiado.
etc

Si todo ese tiempo supera los 200ms del timer, entonces nunca se ejecutaria lo del while, ya que apenas salga volveria a entrar a la interrupcion.
Por eso desabilita la interrupcion. Para prevenir la re-entrada.


Segun tu codigo cada 400ms se ejecuta init_TC
y luego de todo esto:

Código: C
  1. output_high(pin_b1); delay_ms(500);
  2.         output_low(pin_b1);  delay_ms(500);

Tenes tu conversion.. Vamos a suponerlo como que se ejecutan en paralelo, los tiempos donde se ejecutan init_tc y read_tc son estos:

0ms - Lectura (read_tc)
200ms - Inicio ( init_tc )
600ms - Inicio de vuelta
1000ms - inicio y Lectura, condicion de carrera por cual es primero.
1400ms - Inicio
1800ms - Inicio
2000ms - Lectura
2200ms - Inicio

Ves que es un desastre ?

Si lo queres "continuo", entonces dejalo como estaba... a pesar que aparezca el warning ya que como te dije: NO DEBO PONER COSAS QUE DEMOREN MUCHO EN LA INTERRUPCION!.
Pero como es una sola interrupción no nos molesta.

Y modificale esta parte del codigo


Código: C
  1. #INT_TIMER0                                                                      
  2.          void intetTm0(void)
  3.          {
  4.          do_everything();  
  5.          set_timer0(3036);
  6.          clear_interrupt(INT_TIMER0);
  7.          }

De esa forma, el init_TC no va a tener problemas, se va aejecutar y salir.
El read_tc con todo lo que trae aparejado, al salir (tarde lo que tarde) pone el timer a 200ms, y limpia el flag para que no entre de unevo si se pasaron los 200ms.

Con esto vas a lograr que:

entre el init_tc y el read_tc tengas los 200ms
Entre el final del read_tc y el nuevo init_tc vas a tener 200ms + lo que tarde lo del LCD, el float, read_tc, etc.

Ahi te vas a dar cuenta, cuanto tarda todo eso que se puso en la interrupcion.

Obviamente si observas los "500ms" de tu while, ya no son mas "500ms". Si queres precision en varias coisas, entonces todo pasaria por un timer y volveriamos al primer codigo que te pase.

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 56
Re:Libreria para Max6675 en CCS
« Respuesta #26 en: 22 de Enero de 2021, 12:20:53 »

Gracias. Lo voy a colocar como dices
Código: C++
  1. #INT_TIMER0                                                                      
  2.          void intetTm0(void)
  3.          {
  4.          do_everything();  
  5.          set_timer0(3036);
  6.          clear_interrupt(INT_TIMER0);
  7.          }

Y aunque aparezca.el warning lo coloco dentro de la funcion.


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #27 en: 22 de Enero de 2021, 12:34:14 »
Usalo asi y ahora si queres pone el ouput_toggle en esa función, de esa forma vas a ver el tiempo que tarda cada cosa.

Código: C
  1. #INT_TIMER0                                                                      
  2.          void intetTm0(void)
  3.          {
  4.          output_toggle(pin_b0);
  5.          do_everything();  
  6.          set_timer0(3036);
  7.          clear_interrupt(INT_TIMER0);
  8.          }

Entonces cambia cada vez que entra.. De esa forma podes ver el tiempo...

Si lo del LCD mas todo lo demas no supera los 200ms, podes mover el set_timer antes del do_everything.

PD:
Si por las dudas... ya que odio que los compiladores te agreguen cosas por ellos solos... si no te funciona, activa las interrupciones tambien LUEGO del clear_interrupt. (solo activa la del timer 0)

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 56
Re:Libreria para Max6675 en CCS
« Respuesta #28 en: 23 de Enero de 2021, 22:40:30 »
Todo bien, la lectura de temperatura es buena y dentro de la interrupción  :-/ .

Solo como comentario. Valdría la pena tratar de meter las  funciones return(raw & 0b0111111111111000)>>3; y return((((float)tmp)-48.725)/1.9835); en la funcion  int16 read_TC(void), para no tener tantas funciones y después unirlas o seria mejor tener solo una función?.

Me refiero a estas...

Código: C++
  1. int16 read_TC(void)               //It takes 200ms (ish) for the MAX6675 to perform a conversion
  2.          {
  3.          int8 i;
  4.          int16 data;
  5.          output_low(TC_CS);            //stop any conversion processes
  6.          [b]delay_us(1);[/b]               //and give it some time to power up (not very much, admittedly)
  7.            
  8.          for (i=0;i<16;i++){
  9.          shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
  10.          output_high(TC_CLK);
  11.          [b]delay_us(1); [/b]//Descomentar si usa crystal mayor a 10MHz
  12.          output_low(TC_CLK);
  13.          [b]delay_us(1);[/b]
  14.          }
  15.            
  16.          thermocouple_error=bit_test(data,2);      //this is the thermocouple status bit
  17.          output_high(TC_CS);
  18.          
  19.          return (data);      
  20.          }
  21.  
  22.          int16 sortout(int16 raw)
  23.          {
  24.          return(raw & 0b0111111111111000)>>3;      //returns only the bits converning temperature
  25.          }
  26.  
  27.          float toFloat_TC(int16 tmp)
  28.          {
  29.          return((((float)tmp)-48.725)/1.9835);
  30.          }

Por cierto e cambiado los tiempos  (marcados en negrita) de 1ms y de 100us a 1us todos ellos y manteniéndose la buena lectura del sensor.

KillerJC. Muy agradecido por todo,  :-/
« Última modificación: 23 de Enero de 2021, 22:44:10 por Ruco »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #29 en: 24 de Enero de 2021, 09:58:20 »
En la parte del SPI es decir esta:

Código: C
  1. for (i=0;i<16;i++){
  2.          shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
  3.          output_high(TC_CLK);
  4.          [b]delay_us(1); [/b]//Descomentar si usa crystal mayor a 10MHz
  5.          output_low(TC_CLK);
  6.          [b]delay_us(1);

El tamaño minimo en 1 y en 0 del clock es de 100ns segun el datasheet. Si tenes un micro PIC16/18 a 20Mhz, incluso quitando los delays, tendrias 200ns, por lo que SOBRA.
Asi que hasta 40Mhz para ser exactos con un PIC16/18 no existiria problemas y no es necesario el delay. Lo mismo ocurre con el tiempo entre la señal del CS y el comienzo del clk.

Código: C
  1. output_low(TC_CS);            //stop any conversion processes
  2.          [b]delay_us(1);[/b]               //and give it some time to power up (not very much, admittedly)

Tambien el tiempo necesario es de 100ns segun datasheet del MAX, si a 20Mhz las instrucciones tardan 200ns no tendrias problemas, ademas observa que tenes el for, el shift, etc, lo que hace mas tiempo aun. También se podría quitar este delay por completo.
O comentarlos así quedan por si las dudas


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


Citar
Valdría la pena tratar de meter las  funciones return(raw & 0b0111111111111000)>>3; y return((((float)tmp)-48.725)/1.9835); en la funcion  int16 read_TC(void), para no tener tantas funciones y después unirlas o seria mejor tener solo una función?.

Normalmente para esos casos cuando son conversiones asi tan cortas por legibilidad se prefiere que este en alguna funcion aparte. Da mas sentido a lo que se esta haciendo cuando lees el codigo.
Se suele usar el palabra "inline" para definir la funcion, de esa forma el compilador no crea una llamada, sino que solo la reemplaza en el lugar. Reduciendo el stack, etc.
Pero dependiendo del compilador, y de las optimizaciones que tengan, puede que solo lo haga "inline". Asi que vos solo te preocuparias por la legibilidad de tu codigo.

Hay compiladores que no soportan el uso de inline... Solo por las dudas lo nombro.

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

Uno de los grandes problemas que vas a tener con CCS es la no posibilidad de crear varios archivos, por ejemplo estas funciones que son de MAX, deberian estar en un archivo aparte exclusivamente con fuciones para este, de esa forma hay menos cosas en tu archivo principal.


 

anything