7 Replies Latest reply on Sep 21, 2018 5:18 AM by gani

    Reading a frequency value using PWM + Counter

    pgrlopes_3232321

      Hello again

       

      I am trying to read a sensor that outputs a frequency value and while trying to understand how I could do that I came across this example that does just that: http://www.cypress.com/file/144696/download and Frequency Measurement.

      While trying to get the example given in the last link to work I ran into an issue while debugging because the debugger seems to get stuck in the if operation when checking for the interrupt flag to be true and I'm not sure why (line 141 from the main.c file in the attachment). I tried changing the interrupt routing into a CY_ISR function like I did with one of my other projects but to no avail.

       

      I'm also trying to understand the component functioning because I'm pretty sure I'm not getting the full picture. As far as I understood, the PWM is there to create an interval where the counter can count the rising edges of the signal placed in the input pin. What I'm not understanding is how the pwm clock influences the whole thing. I will eventually need to use this with a much lower period, so I'm already trying to be ahead of things for when I need to change it. I'm not sure what I should change to turn the period down, if the PWM clock or the PWM pulse width itself, and I also haven't understood fully what the counter clock influences.

       

      I will attach the project example that I fiddled with.

       

      Would appreciate any help you guys could give.

       

      Thank you very much

        • 1. Re: Reading a frequency value using PWM + Counter
          bob.marlowe

          The PWM clock sets the measure interval to 100ms. This means you can accept frequencies between ~100Hz(will give 10 counts) and something like 10MHz.

          The counter clock is used internally to detect a rising edge at the count input, so the counter can see pulses up to 12MHz

          When you lower the PWM frequency only the lower limit will be affected. With a period of 1s you will be able to measure 10Hz frequencies.

           

          Your error is within your interrupt handler: You need to clear the interrupt cause of the PWM by reading its status.

          PWM_Window_ReadStatusRegister() API will clear the TC flag.

          And:

          Every global variable (compare_occured) that is changed within an interrupt handler must be declared as "volatile" (or you run into deep trouble when optimization level is changed!!!)

           

          Bob

          • 2. Re: Reading a frequency value using PWM + Counter
            pgrlopes_3232321

            Allright, thanks Bob but im still a bit confused. So lets say I wanted to have a frequency read every second, for that I would need to change the clock value to 10KHz, meaning that the period would be 1/10000 and the interrupt would fire after counting 10000 times, so it would fire after one second. My question is how does this affect the counter read? Wouldn't the widening of the interrupt window mean that the counter would be using a much higher time interval while reading the rising edges?

             

            I changes the counter_occured variable to volatile and added the PWM_Window_ReadStatusRegister() to the CY_ISR(isr_counter) function but its still getting stuck on the debug mode, so I can't even understand if it is reading anything at all. Any idea why?

             

            Thank you!

             

            Edit: Here is the code I am using now, the debugger gets stuck and on line 81

             

            #include <project.h>
            /* The clock frequency for the PWM_Window. The PWM_Window clock frequency must be in KHz. 
             * Please update this define if the clock is updated in the TopDesign */
            #define PWM_FREQ 100
            /* Define for 1 second in terms of millisecond */
            #define NO_OF_MSEC 1000
            /* These variables are accessed in the ISRs 
             * Accessed in ISR_Compare to update the counter value */
            volatile uint8 compare_occured;
            uint32 input_freq = 0;
             
            /* Variables to store the Period of the PWM_Window */
            static uint16 PWM_windowPeriod = 0;
             
            /* Variable to store the count value after capture */
            static uint32 counter_countVal;
            CY_ISR(isr_counter) // ISR Timer to report temperature at regular interval
            {
                PWM_Window_ReadStatusRegister();
                compare_occured=1;
            }
            
            void Initialize(){
                
                CYGlobalIntEnable;
             
             /* Initializations */
             pwm_interrupt_StartEx(isr_counter);
             PWM_Window_Start();
             Counter_Start(); 
             Clock_Start();
                
                /* Calculate the time window during which the counter will count */
             PWM_windowPeriod = PWM_Window_ReadPeriod() ;
             
             /* Update the Time window value according to the clock given to the PWM_Window */
             PWM_windowPeriod = PWM_windowPeriod/ PWM_FREQ;
            }
            
            float irradiance_read(){
                
                
                /* Check if the PWM interrupt has occurred
               * The code works in such a way that, the PWM Compare event has an interrupt.
               * The interrupt occurs for every 100 millisec (Interrupt on Compare Event)
               * The frequency calculation is done whenever the interrupt occurs */
              if (compare_occured)
              {
               /* Read the Counter capture register */
               counter_countVal = Counter_ReadCapture();
               
               /* Convert the counts to frequency.
                * Frequency is the number of counts in seconds
                * In this case counts within "PWM time window" (100 millisecond in this example) is got from Counter. 
                * So we need to find for 1000 milliseconds */
               input_freq = ((uint32)(NO_OF_MSEC * (uint32)counter_countVal) / (uint32)PWM_windowPeriod);     
               
               /* Clear the interrupt flag */
               compare_occured = 0;
              }
                    else{
                    input_freq = -1000;
                    }
                    
                    return input_freq;
                
            }
            
            int main()
            {
                Initialize();
                
                compare_occured=1;
                
                float frequency_read;
                 
             for(;;)
                {
                    /* Your code here. */
                    
                    frequency_read = irradiance_read();
              
              
                }
            }
            /* [] END OF FILE */
            
            • 3. Re: Reading a frequency value using PWM + Counter
              bob.marlowe

              Probably a debugger pitfall. When line 81 is reached, remove the breakpoint and step into your code.

              or

              set a breakpoint at line 47 (if(...))

               

              under Project -> Build settings -> Arm -> Compiler -> Optimization set to "none" to prevent removing of an unused result.

               

              Bob

              • 4. Re: Reading a frequency value using PWM + Counter
                pgrlopes_3232321

                Thank you Bob, its working now but I have another question.

                 

                Do you know how I could add this logic to a project that is supposed to be sending info only when another interrupt fires? I'm having a lot of trouble understanding how I could send the frequency measure with my other data without messing with the pwm interrupt and therefor the frequency measure itself.

                 

                If needed I can post my project, would really appreciate some help in this last step

                 

                Thank you so much.

                • 5. Re: Reading a frequency value using PWM + Counter
                  bob.marlowe

                  Upload your project and make quite clear what you want to perform, Ill have a look at.

                   

                  Bob

                  • 6. Re: Reading a frequency value using PWM + Counter
                    pgrlopes_3232321

                    Right now I have 2 sensors (temperature and current) and a voltage divider connected to an ADC sending their info at the same time by using an ISR interrupt connected to the output of a frequency divider, with a clock added to that frequency divider.

                     

                    I have a CY_ISR function where I set all sensor flags to true when the interrupt fires and in the main loop I process the data and send it, and it's working well. I want to add this frequency value I'm reading to that data now so it can be sent at the same time as all others, because I need all the data as a set of values to then process on another microcontroller.

                     

                    Basically I want a way I can send all the data I acquire at once without screwing the frequency reading, because as far as I understood messing with that interrupt could mess with the frequency calculation itself. Right now it's working for smaller periods for debugging purposes, but the ultimate goal is getting it to work with a period of 2 to 5 minutes.

                     

                     

                    I will attach the project, thank you so much for helping me out

                    • 7. Re: Reading a frequency value using PWM + Counter
                      gani

                      Hi,

                       

                      In your application you have used several interrupts with same priority. You can actually change the priority of the interrupts to be serviced. In PSoC 5LP device the interrupts/exceptions would be pre-emptive.

                      Please increase the priority of interrupts that are crucial for the measurement of the quantities those vary fast or those you feel important for your application. You can reduce the priority number of the interrupt to increase its priority. You can change this in the interrupts tab in the PSoC Creator. Please find the attached screenshot.

                       

                      Thanks

                      Ganesh