Autor Tema: Las cositas del CCS  (Leído 2260 veces)

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

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Las cositas del CCS
« en: 05 de Junio de 2022, 04:11:43 »
Llevo dándole vueltas un buen rato a un bucle donde calculo la corriente consumida
Código: C
  1. for (i=0;i<IndMuestra;i++) {
  2.                delay_ms(10);
  3.                corriente =  (muestras[i]-OFFSET)*AJUSTAADC * 4.6;
  4.                SumaMuestras+=muestras[i];
  5.                muestras[i]=0;
  6.                onda = onda + corriente*corriente;
  7.             }

¿Os podéis creer que si le quito ese delay_ms(10) me hace los cálculos mal y me devuelve resultados aleatorios.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re:Las cositas del CCS
« Respuesta #1 en: 05 de Junio de 2022, 06:22:03 »
Pregunta tonta: alguno de los valores de las variables dentro de ese bucle ¿cambia por alguna interrupción o un DMA o algo parecido?
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Conectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 965
Re:Las cositas del CCS
« Respuesta #2 en: 05 de Junio de 2022, 12:18:10 »
...
¿Os podéis creer que si le quito ese delay_ms(10) me hace los cálculos mal y me devuelve resultados aleatorios.

 :shock: ¿Podés subir un bloque "compilable" donde haga el error?

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re:Las cositas del CCS
« Respuesta #3 en: 05 de Junio de 2022, 12:39:48 »
Pregunta tonta: alguno de los valores de las variables dentro de ese bucle ¿cambia por alguna interrupción o un DMA o algo parecido?
En teoría no, don Diego, porque si miras el fuente, el cálculo sólo se hace cuando capturado=1, mientras que el array se modifica en la interrupción del Timer cuando capturado=0.
Además, si alguna interrupción fuera la responsable de modificar alguna de esas variables, lo sería más en tanto más tiempo durase el cálculo. Por tanto, quitar el delay_ms no sería una fuente de errores, sino todo lo contrario.
Pero no sé, lo mismo se me está escapando algo.
Dejo aquí abajo el código. No me lo critiquéis mucho que está lleno de "mierda" porque aún ando debuggeando.

:shock: ¿Podés subir un bloque "compilable" donde haga el error?
Aquí va:
Código: C
  1. #include <18F1320.h>
  2. #device ADC=10
  3. #device HIGH_INTS=TRUE
  4. #include "math.h"
  5. #FUSES NOWDT                    //No Watch Dog Timer
  6.  
  7. #use delay(internal=8MHz)
  8. #use rs232(baud=115200,parity=N,bits=8,stream=PORT1, xmit=PIN_B1, rcv=PIN_B4)
  9.  
  10. #define SALIDA             PIN_B3
  11. #define MUESTRASENCICLO      72
  12. #define NUMMUESTRAS        MUESTRASENCICLO*10   // Cada onda a 50Hz está dividida en 36 muestras. Cogemos 10 ondas
  13.  
  14. #define  OFFSET      512.0       // Restamos 512 porque la señal tiene un offset de 2.5V
  15. #define  AJUSTAADC   5.0/1024.0  // 5V a 10bits de resolución
  16.  
  17. unsigned int16 muestras[50];
  18.  
  19. int16 buffer, objetivo;
  20. float onda, consumo;
  21. int16 potencia;
  22.  
  23. unsigned int8 capturado, calculado;
  24. unsigned int8 contadorPWM, cortePWM;
  25. unsigned int8 IndMuestra=0;
  26.  
  27. #INT_RDA HIGH
  28. void intser()
  29. {
  30.    char c;
  31.    
  32.    c = getc();
  33.  
  34.    if ((c>='0') && (c<='9'))
  35.       buffer = buffer*10 + c - '0';
  36.    
  37.    if ((c == '\r')) {
  38.       objetivo = buffer;
  39.       buffer=0;
  40.    }
  41.    
  42.    if (c=='0')
  43.       output_low(SALIDA);
  44.    if (c=='1')
  45.       output_high(SALIDA);
  46.    // Como la interrupción RDA habrá interrumpido la lectura de la onda, empezamos de nuevo
  47.    IndMuestra=0;
  48.    onda = 0;
  49.    
  50. }
  51.  
  52. #INT_EXT
  53. void cruce_por_cero() {
  54.    
  55.    output_low(SALIDA);
  56.    set_timer2(0);
  57.    contadorPWM=0;
  58.    
  59.    if (!capturado) {
  60.       capturado=1;
  61.    }
  62.    
  63.    if (calculado) {
  64.       calculado=0;
  65.       capturado=0;
  66.       IndMuestra=0;
  67.    }
  68. }
  69.  
  70.  
  71. #INT_TIMER2
  72. void LeerADC() {
  73.    if (!capturado) {
  74.       muestras[IndMuestra]=read_adc();
  75.       IndMuestra++;
  76.    };
  77.    if (contadorPWM++ == cortePWM) {
  78.        output_high(SALIDA);
  79.    }
  80. }
  81.  
  82.  
  83. void main()
  84. {
  85.    int8 i;
  86.    float corriente;
  87.    int16 SumaMuestras;
  88.    
  89.    setup_adc_ports(sAN0, VSS_VDD);
  90.    setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_0);
  91.    output_low(SALIDA);
  92.    setup_timer_2 (T2_DIV_BY_1,198,2); // 187 para 36 ciclos
  93.    output_float(PIN_B0);
  94.    output_float(PIN_B4);
  95.    set_adc_channel(0);
  96.    onda = 0;
  97.    IndMuestra=0;
  98.    contadorPWM=0;
  99.    enable_interrupts(INT_TIMER2);
  100.    enable_interrupts(INT_RDA);
  101.    enable_interrupts(INT_EXT);
  102.    enable_interrupts(GLOBAL);
  103.    delay_ms(50);
  104.    objetivo = 0;
  105.    cortePWM=25;
  106.    
  107.    while (1) {
  108.       if (capturado) {    
  109.          onda=0;
  110.          SumaMuestras=0;
  111.          if (IndMuestra==50) {
  112.             for (i=0;i<IndMuestra;i++) {
  113.                delay_ms(10);
  114.                corriente =  (muestras[i]-OFFSET)*AJUSTAADC * 4.6;
  115.                SumaMuestras+=muestras[i];
  116.                muestras[i]=0;
  117.                onda = onda + corriente*corriente;
  118.             }
  119.             if (!SumaMuestras) {// eliminamos el ruido
  120.                consumo=0.0;
  121.                potencia = 0;
  122.             } else {
  123.                consumo = sqrt(2*onda/IndMuestra);
  124.                potencia = (int16)(consumo * 181.0);
  125.             }
  126.             printf ("%u -> %6.2fA -> %4luW. Obj %lu - CortePWM %u\n", IndMuestra, consumo, potencia, objetivo, cortePWM);
  127.          }
  128.          if ((potencia<objetivo) && (cortePWM>0))
  129.             cortePWM--;
  130.          if ((potencia>objetivo) && (cortePWM<49))
  131.             cortePWM++;
  132.          calculado=1;
  133.       }
  134.     }
  135.  }

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Las cositas del CCS
« Respuesta #4 en: 06 de Junio de 2022, 10:56:22 »
Llevo dándole vueltas un buen rato a un bucle donde calculo la corriente consumida
Código: C
  1. for (i=0;i<IndMuestra;i++) {
  2.                delay_ms(10);
  3.                corriente =  (muestras[i]-OFFSET)*AJUSTAADC * 4.6;
  4.                SumaMuestras+=muestras[i];
  5.                muestras[i]=0;
  6.                onda = onda + corriente*corriente;
  7.             }

¿Os podéis creer que si le quito ese delay_ms(10) me hace los cálculos mal y me devuelve resultados aleatorios.

Deberías dejar a un lado los "delays" y programar en estados de máquina (o máquina de estados). Te permite aislar los procesos en tareas independientes y la búsquedas de errores se simplifica.
Aunque también, ese tipo de errores en el CCS no me sorprende en ese compilador.
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Conectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 965
Re:Las cositas del CCS
« Respuesta #5 en: 06 de Junio de 2022, 13:20:24 »
....
:shock: ¿Podés subir un bloque "compilable" donde haga el error?
Aquí va:
Código: C
  1. #include <18F1320.h>
  2. #device ADC=10
  3. #device HIGH_INTS=TRUE
  4. #include "math.h"
  5. #FUSES NOWDT                    //No Watch Dog Timer
  6.  
  7. #use delay(internal=8MHz)
  8. #use rs232(baud=115200,parity=N,bits=8,stream=PORT1, xmit=PIN_B1, rcv=PIN_B4)
  9.  
  10. #define SALIDA             PIN_B3
  11. #define MUESTRASENCICLO      72
  12. #define NUMMUESTRAS        MUESTRASENCICLO*10   // Cada onda a 50Hz está dividida en 36 muestras. Cogemos 10 ondas
  13.  
  14. #define  OFFSET      512.0       // Restamos 512 porque la señal tiene un offset de 2.5V
  15. #define  AJUSTAADC   5.0/1024.0  // 5V a 10bits de resolución
  16.  
  17. unsigned int16 muestras[50];
  18.  
  19. int16 buffer, objetivo;
  20. float onda, consumo;
  21. int16 potencia;
  22.  
  23. unsigned int8 capturado, calculado;
  24. unsigned int8 contadorPWM, cortePWM;
  25. unsigned int8 IndMuestra=0;
  26.  
  27. #INT_RDA HIGH
  28. void intser()
  29. {
  30.    char c;
  31.    
  32.    c = getc();
  33.  
  34.    if ((c>='0') && (c<='9'))
  35.       buffer = buffer*10 + c - '0';
  36.    
  37.    if ((c == '\r')) {
  38.       objetivo = buffer;
  39.       buffer=0;
  40.    }
  41.    
  42.    if (c=='0')
  43.       output_low(SALIDA);
  44.    if (c=='1')
  45.       output_high(SALIDA);
  46.    // Como la interrupción RDA habrá interrumpido la lectura de la onda, empezamos de nuevo
  47.    IndMuestra=0;
  48.    onda = 0;
  49.    
  50. }
  51.  
  52. #INT_EXT
  53. void cruce_por_cero() {
  54.    
  55.    output_low(SALIDA);
  56.    set_timer2(0);
  57.    contadorPWM=0;
  58.    
  59.    if (!capturado) {
  60.       capturado=1;
  61.    }
  62.    
  63.    if (calculado) {
  64.       calculado=0;
  65.       capturado=0;
  66.       IndMuestra=0;
  67.    }
  68. }
  69.  
  70.  
  71. #INT_TIMER2
  72. void LeerADC() {
  73.    if (!capturado) {
  74.       muestras[IndMuestra]=read_adc();
  75.       IndMuestra++;
  76.    };
  77.    if (contadorPWM++ == cortePWM) {
  78.        output_high(SALIDA);
  79.    }
  80. }
  81.  
  82.  
  83. void main()
  84. {
  85.    int8 i;
  86.    float corriente;
  87.    int16 SumaMuestras;
  88.    
  89.    setup_adc_ports(sAN0, VSS_VDD);
  90.    setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_0);
  91.    output_low(SALIDA);
  92.    setup_timer_2 (T2_DIV_BY_1,198,2); // 187 para 36 ciclos
  93.    output_float(PIN_B0);
  94.    output_float(PIN_B4);
  95.    set_adc_channel(0);
  96.    onda = 0;
  97.    IndMuestra=0;
  98.    contadorPWM=0;
  99.    enable_interrupts(INT_TIMER2);
  100.    enable_interrupts(INT_RDA);
  101.    enable_interrupts(INT_EXT);
  102.    enable_interrupts(GLOBAL);
  103.    delay_ms(50);
  104.    objetivo = 0;
  105.    cortePWM=25;
  106.    
  107.    while (1) {
  108.       if (capturado) {    
  109.          onda=0;
  110.          SumaMuestras=0;
  111.          if (IndMuestra==50) {
  112.             for (i=0;i<IndMuestra;i++) {
  113.                delay_ms(10);
  114.                corriente =  (muestras[i]-OFFSET)*AJUSTAADC * 4.6;
  115.                SumaMuestras+=muestras[i];
  116.                muestras[i]=0;
  117.                onda = onda + corriente*corriente;
  118.             }
  119.             if (!SumaMuestras) {// eliminamos el ruido
  120.                consumo=0.0;
  121.                potencia = 0;
  122.             } else {
  123.                consumo = sqrt(2*onda/IndMuestra);
  124.                potencia = (int16)(consumo * 181.0);
  125.             }
  126.             printf ("%u -> %6.2fA -> %4luW. Obj %lu - CortePWM %u\n", IndMuestra, consumo, potencia, objetivo, cortePWM);
  127.          }
  128.          if ((potencia<objetivo) && (cortePWM>0))
  129.             cortePWM--;
  130.          if ((potencia>objetivo) && (cortePWM<49))
  131.             cortePWM++;
  132.          calculado=1;
  133.       }
  134.     }
  135.  }

Mirá, cuando simulo ese código veo que el índice IndMuestra alcanza el valor 58 antes de resetearlo --> Como muestra[] es de 50 elementos se está escriibiendo sobre las variables que hay después --> resultado impredecible.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re:Las cositas del CCS
« Respuesta #6 en: 07 de Junio de 2022, 02:04:54 »
Deberías dejar a un lado los "delays" y programar en estados de máquina (o máquina de estados). Te permite aislar los procesos en tareas independientes y la búsquedas de errores se simplifica.
Aunque también, ese tipo de errores en el CCS no me sorprende en ese compilador.

Pero si precisamente lo que quiero es eliminar el delay_ms. Está puesto ahí artificialmente porque de lo contrario los cálculos no funcionan bien. No es una tarea síncrona; todo lo contrario.

Mirá, cuando simulo ese código veo que el índice IndMuestra alcanza el valor 58 antes de resetearlo --> Como muestra[] es de 50 elementos se está escriibiendo sobre las variables que hay después --> resultado impredecible.

Muchas gracias por ayudarme Eduardo2. Si le inyectas una señal cuadrada de 50Hz por la interrupción externa, IndMuestra no pasa de 50.
De todas formas, por prevenir, probaré poniendo un tope de 50 al incremento de IndMuestra.

Conectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 965
Re:Las cositas del CCS
« Respuesta #7 en: 07 de Junio de 2022, 07:49:58 »
.... Si le inyectas una señal cuadrada de 50Hz por la interrupción externa, IndMuestra no pasa de 50.
...
Le inyecte un pulso de 50hz duty 5%, y llegaba a 58.
« Última modificación: 07 de Junio de 2022, 07:52:27 por Eduardo2 »

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re:Las cositas del CCS
« Respuesta #8 en: 07 de Junio de 2022, 08:53:32 »
Sin haber podido estudiar cómo se incrementa y sobre todo cómo se reinicia IndMuestra prueba a sustituir el IndMuestra==50 por un IndMuestra > 50 e inmediatamente ponerlo a cero tras la comparación, así te asegurarás de que nunca sobrepase el valor límite. 
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Conectado Eduardo2

  • PIC24F
  • *****
  • Mensajes: 965
Re:Las cositas del CCS
« Respuesta #9 en: 07 de Junio de 2022, 10:23:39 »
.... Si le inyectas una señal cuadrada de 50Hz por la interrupción externa, IndMuestra no pasa de 50.
...
Le inyecte un pulso de 50hz duty 5%, y llegaba a 58.

Error mio,  los pulsos deben ser de 100Hz y ahí IndMuestra no pasa de 50.   Igual no está bien porque si no llegan pulsos por la razón que sea  se escribiría encima a un montón de variables.

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Las cositas del CCS
« Respuesta #10 en: 07 de Junio de 2022, 10:44:02 »
Deberías dejar a un lado los "delays" y programar en estados de máquina (o máquina de estados). Te permite aislar los procesos en tareas independientes y la búsquedas de errores se simplifica.
Aunque también, ese tipo de errores en el CCS no me sorprende en ese compilador.

Pero si precisamente lo que quiero es eliminar el delay_ms. Está puesto ahí artificialmente porque de lo contrario los cálculos no funcionan bien. No es una tarea síncrona; todo lo contrario.



Lo que me refería es que se puede crear retardos sin recurrir a los delay que son procesos apropiativos del CPU y generan latencia en el sistema. Mientras se produce un retardo, el CPU podría atender otros procesos de tal manera que se crea un proceso cooperativo y ante los ojos del usuario, por la velocidad del CPU, es como que hiciera varios procesos al mismo tiempo, paralelismo como se lo conoce en sistemas embebidos.
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re:Las cositas del CCS
« Respuesta #11 en: 08 de Junio de 2022, 02:16:55 »
He puesto tope al incremento de IndMuestra para que, si se diera el caso, nunca pase de 50.
El programa funciona perfecto con el delay, y cuando se lo quito se vuelve loco.

No sé por qué pero me da que tiene algo que ver con las operaciones matemáticas con los float; ¿pudiera ser que se ejecutan en segundo plano y sólo tiene tiempo de realizarlas cuando meto delays en el bucle principal?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Las cositas del CCS
« Respuesta #12 en: 08 de Junio de 2022, 07:30:19 »
No sé por qué pero me da que tiene algo que ver con las operaciones matemáticas con los float; ¿pudiera ser que se ejecutan en segundo plano y sólo tiene tiempo de realizarlas cuando meto delays en el bucle principal?

Tiene un solo nucleo el PIC por lo que nada es paralelo.. La unica que se me ocurre es tirar el ASM generado y verlo ahi..
Probaste otra version del compilador?

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re:Las cositas del CCS
« Respuesta #13 en: 08 de Junio de 2022, 07:55:18 »
Manolo, yo tengo en perfecto orden de marcha las versiones 3.245, 4.093, 5.048 y 5.099 ... por si quieres que te compile con alguna de ellas tu código y te pase el HEX ... por si cuela  :?
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re:Las cositas del CCS
« Respuesta #14 en: 08 de Junio de 2022, 08:16:00 »
Hola, ya va por la version 5.109.... :D
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.