5 Replies Latest reply on Jul 29, 2019 6:17 PM by MoTa_728816

    Timer_Counter too slow

    MuKa_284621

      Hello,

       

      I've created a project that is essentially a pulse generator. It is implemented using the TCPWM block set as a Timer Counter. I'm using the CY8CKIT-042 Pioneer Kit.

       

      The count frequency is set to 20 kHz (50 us between counts) and it runs continuously. What I did was the following:

       

      1) Init Compare register of the counter with a first value.

      2) After the counter reaches the set value, the compare register performs a swap with the Compare Buffer. This is done by ticking the option given in the Counter tab.

      3) An interrupt is signaled at the time of compare equal, and it updates the Compare Buffer with the next value (with a counter increment after update).

      4) The signal from the cc output of the TCPWM was hooked to the reload input in order to reset the counter.

       

      All the compare values are below 20000, so in theory I expect to get a pulse every less than a second or so. But in this setting, I had about 2-3 seconds interval before the next pulse arrives. To make sure it wasn't the compare value that I got wrong, I used 20000 as a fixed value in both Compare and Compare Buffer registers (without any update of these values) and it still outputs one pulse every 3 seconds.

       

      I'm wondering if I did something wrong. I attach the project in this post. UART is for debug. Alternatively, you can reroute HR_Out_Pin to the polychromatic LED pins.

       

      Thanks,

        • 1. Re: Timer_Counter too slow
          MoTa_728816

          Hi,

           

          I notices some points I'd like to suggest to change

          (1) make index which is updated in the ISR to volatile

          volatile uint16 hrCountIdx = 0; // modified

          (2) WriteCompareBuf should be changed to WriteCompare

          (3) The reload may not working correctly, so I added WriteCounter(0) ;

          (4) Do not put UartPutString() inside an ISR instead I used the red led.

          At least the LED's on/off interval seems to be around 1sec or less on my CY8CKIT-042.

           

          so my modified main.c looked like

          ===============

          /* Heart-Rate Sensor

          *

          * Muhammad Haziq Kamarul Azman

          * Universiti Kuala Lumpur

          * British Malaysian Institute

          *

          */

          #include <device.h>

           

           

          #define HR_COUNTER_IDX_NUM 748

          uint16 hrCountVal[HR_COUNTER_IDX_NUM] = {

          /* removed to make it shorter to display here */

          17425,  17689,  17749,  17423,  17342,  17620 };

          volatile uint16 hrCountIdx = 0; // modified

           

          CY_ISR_PROTO(HR_Update_Swap_Int_EXISR);

          CY_ISR(HR_Update_Swap_Int_EXISR)

          {

          //    HR_Trigger_Counter_WriteCompareBuf(hrCountVal[hrCountIdx]) ;

              HR_Trigger_Counter_WriteCompare(hrCountVal[hrCountIdx]) ;

           

              HR_Trigger_Counter_WriteCounter(0) ;

           

              hrCountIdx = (hrCountIdx + 1) % HR_COUNTER_IDX_NUM ;

            

              LED_Write(!LED_Read()) ;

          //    Comm_UART_UartPutString("Sample!\r\n");

           

              HR_Update_Swap_Int_ClearPending();

              HR_Trigger_Counter_ClearInterrupt(HR_Trigger_Counter_INTR_MASK_CC_MATCH);

          }

           

          int main(void)

          {

              CyGlobalIntEnable;  // Enable global interrupts.

            

              /* Initialization */

              HR_Sample_Clock_Start();

              HR_Update_Swap_Int_StartEx(HR_Update_Swap_Int_EXISR);

              Comm_UART_Start();

              Comm_UART_UartPutString("Starting\r\n");

            

              /* Start sampling*/

              HR_Trigger_Counter_WriteCompare(20000);//hrCountVal[hrCountIdx++]);

              HR_Trigger_Counter_Start();

            

              while(1);

          }

          ===============

           

          moto

          • 2. Re: Timer_Counter too slow
            MoTa_728816

            Hi,

             

            After posting previous response, I felt having reload, which is not working uneasy.

            So I modified your project like below

             

            Schematic

            000-schematic.JPG

            Since you are using TCPWM as a timer, let's use "period" for the control

            so that when period hits, TC is asserted and reload is automatically done

            001-Timer_config_1.JPG

            002-Timer_config_2.JPG

             

            Then I set the initial period to 20000, instead of 65535.

            And I modified your ISR as

            ======================

            CY_ISR(HR_Update_Swap_Int_EXISR)

            {

                period = hrCountVal[hrCountIdx] ;

            //    HR_Trigger_Counter_WritePeriod(period) ;

                HR_Trigger_Counter_WritePeriodBuf(period) ;

                hrCountIdx = (hrCountIdx + 1) % HR_COUNTER_IDX_NUM ;

              

                LED_Write(!LED_Read()) ;

                HR_Update_Swap_Int_ClearPending();

                HR_Trigger_Counter_ClearInterrupt(HR_Trigger_Counter_INTR_MASK_TC) ;

            }

            ======================

             

            I tried both

                HR_Trigger_Counter_WritePeriod(period) ;

            and

                HR_Trigger_Counter_WritePeriodBuf(period) ;

            for my human sense I did not notice difference,

            but may be WritePeriodBuf() can set more exact timing.

             

            And let main report the change of the period

            ======================

            int main(void)

            {

                CyGlobalIntEnable;  // Enable global interrupts.

              

                Comm_UART_Start();

                sprintf(str, "Starting (%s %s)\r\n",__DATE__, __TIME__);

                print(str) ;

             

                /* Initialization */

                HR_Sample_Clock_Start();

                HR_Update_Swap_Int_StartEx(HR_Update_Swap_Int_EXISR);

             

                /* Start sampling*/

                HR_Trigger_Counter_WritePeriod(period);//hrCountVal[hrCountIdx++]);

                HR_Trigger_Counter_Start();

              

                while(1) {

                    if (period != prev_period) {

                        sprintf(str, "period %d\r\n", period) ;

                        print(str) ;

                        prev_period = period ;

                    }

                }

            }

            ======================

             

            Then Tera Term log was

            003-TeraTerm-Log.JPG

             

            moto

            • 3. Re: Timer_Counter too slow
              EktaN_26

              Hello

               

              The pulse takes 2 to 3 seconds interval to arrive in the initial project because although the compare buffer values are being continuously changed, the period value remains a constant 65535 (i.e., reload does not happen) as shown in the figure below:

              The interrupt will be generated once the counter value equals the compare value but this will happen only once during a period. This is because even after the interrupt is generated the counter will keep on incrementing upto the maximum value and reload only after that. Thus the interrupt interval will be around 65535/20000 = 3.27 sec

               

              In order to generate pulse within 1 or less than 1 sec (depending upon the hrCountVal), we need to change the 'period' value also along with the compare value.

              In order to do this we need to use the API: HR_Trigger_Counter_WritePeriod(hrCountVal[hrCountIdx++]); in the sampling part of the code

               

               

              Also set the initial period, compare value and compare buffer value as 20000 as shown in the figure below.

               

              I have attached the modified project below.

               

              Regards

              Ekta

              • 4. Re: Timer_Counter too slow
                MuKa_284621

                Hello,

                 

                Thanks for the replies (also to Tanaka).

                 

                The thing about the counter not stopping makes sense (also answers why the period is roughly 3 secs).

                 

                However, I don't understand why the reload input is not working. I might be wrong about the cc output being a pulse.

                 

                Anyone knows about this issue?

                • 5. Re: Timer_Counter too slow
                  MoTa_728816

                  Hi,

                   

                  I tried to measure what was happening

                  with slightly modified schematic.

                  000-schematic-190730.JPG

                  I probed LED(P1[1]) pin and HR_Out_Pin (P0[2])

                   

                  The pulse at CC (HR_Out_Pin) was

                  cc_pulse.jpg

                  pulse width was about 136ns (= 7.353MHz),

                  where the clock to the counter is 24MHz divided by 1200 = 20KHz?

                  So this pulse will be very difficult to be caught by the counter.

                   

                  Meantime, I measured the delay from the pulse to the LED(ISR assignment)

                  pulse2intr.jpg

                  The delay was about 5+ us.

                  So resetting counter from ISR may be slow.

                  If we compare it with 20kHz (= 50us), it may be ignored.

                  But I'd rather let the hardware reset (or reload) the counter.

                   

                  So I prefer to use counter period with which at TC the reload will take place automatically by the hardware

                  instead of using compare which will cause some delay before we can do something to reset the counter.

                   

                  moto