2 Replies Latest reply on Jul 28, 2020 8:32 AM by SwathiS_86

    Sporadic errors when timer captures

    JoNe_4268451

      Hello, I'm doing a proyect where I have to measure the angular speed of a BLDC motor. It has hall sensors, so I measure the electrical frequency through them, then I calculate the rotary speed knowing the number of poles of the motor. But this is not my problem. I measure the electrical frequency using a timer component, which is continuosly running, when it does a capture it means an electrical turn is achieved, so I only have to calculate the difference between two consecutive captures.

      The following image shows the blocks that I'm using:

      bloques.png

      The next image shows how I've configured the timer:

      conftimer.png

      Then, an interrupt occurs when the timer gets a capture or finishs a period (on TC), in the code, I have to differentiate the two cases. In the first case, I have to store the value of the capture if it is the first time, or (if it isn't the first capture) calculate the "delay" between the last capture value and get a new value of angular speed. In the second option, I have to take into account that the timer has finished a period, so I increment a variable called "n_periodos" which measure the number of timer periods between two consecutive captures, the following image could clear up this method:

       

      w_real.png

      T0 is the last capture, T1 is the current capture, when it uses the value of actual T1, it is stored in T0 until the next capture.

      w_real_diagrama.png

      /************************************* SPEED MEASUREMENT ************************************/
      
      CY_ISR(ISR_SPEED_MEASURE_HANDLER) 
      {
          /*=================================================================================
          *                       Averiguar causa de la interrupción
          *                       Figure out the interrupt origin
          =================================================================================*/
          
          
          status_register = Timer_speed_ReadStatusRegister();     //Se lee el registro y se limpia la interrupción
          //Read the status register, and clear the interrupt
          
      
          /*============================== INTERRUPCIÓN DEBIDA A TC =========================================
           *                               INTERRUPT DUE TO TC
           * Si la interrupción es porque ha llegado al final de la cuenta, y además el motor está en marcha
           * de esta forma evitamos que el timer cuente cuando esté el motor parado y la variable se desborde
           ================================================================================================*/
          
          if ((status_register & Timer_speed_STATUS_TC_INT_MASK) && SYSTEM_STATE.run){
              n_periodos++;                                   //Incrementamos variable que almacena el número de períodos transcurridos
              //Variable which store the number of periods
          }
          
          
          /*========================== INTERRUPCIÓN DEBIDA A CAPTURA ======================================*/
          /*                              INTERRUPT DUE TO CAPTURE    */
          
          if ((status_register & Timer_speed_STATUS_CAPTURE_INT_MASK) && SYSTEM_STATE.run){
             
              if (first_turn){                                /* Es la primera vez */
                  n_periodos = 0;                             //Reseteamos cuenta de los períodos
                  first_turn = FALSE;                         //Cambiamos variable para mostrar que la próxima vez ya no será la primera
                  T0 = Timer_speed_ReadCapture();             //Guardamos la captura, está en n*bits
                  
              }else if (!first_turn){                                             /* No es la primera vez */
                  T1 = Timer_speed_ReadCapture();                                 //Almacenamos el valor de T1  
                  delay = (T0+n_periodos*TIMER_SPD_PERIOD-T1);                    //Calculamos el nº de ciclos ocurridos
                  T0 = T1;                                                        //Actualizamos T0 
                  n_periodos = 0;                                                 //Limpiamos variable que cuenta los períodos almacenados       
                  w_real = 60/(MOTOR.NPolePairs*delay*CLCK_SPD_PERIOD*1e-9);      //Calculate the angular speed
              }
              
          }
          
      }
      

       

      Well, after this vast explanation, finally I can present my problem. All looks work propertly, but sometimes, the timer looks like skip a capture, then the time measured is double, this produces an error in the velocity, showing the half of the real. The next images (get from the bridge control panel) show this errors:

      errores1.png errores2.png

      The high frequency noise is easily removed with a low pass filter, but I can't eliminate these sporadic errors. If I decrease the frequency of the clock connected to the timer, these errors are more frequently. For example, with a "speed_clock = 1kHz" I get the following result:

      errores3.png errores3_1.png

      And if I increase the frequency of the clock, the errors also are more frequently. I don't know why these errors are produced, I suspect like the timer omit one capture sometimes, because it show exactly the half of the real velocity. Somebody could help me to find a solution?