How do I measure a PWM duty cycle from a servo signal?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Background story:  I built a 3d printed excavator arm for my son for christmas a couple years back (https://www.thingiverse.com/thing:2041143) and he broke the lame servo I put on it, so I redesigned the connection for a stepper, but instead of reprogramming the psoc 1 that runs the controls, I'm going to put in a psoc4 to intercept the servo output from the psoc 1 and control the stepper motor.  It should be easy and a good excuse to put one of the red boards in the box...

Problem: I'm using a psoc 4 4200 protoboard to intercept a PWM servo signal and drive a stepper motor, but I can't get the timer interrupt to trigger on the rising/falling edge of the signal.  I've read Re: Measuring 8 Hobby Servo Signals downloaded the example 1 servo project and watched the psoc 101 tutorials on how to use the TCPWM component in count mode, but the ISR doesn't fire and I don't know why (disclaimer, a second ISR is working to run the stepper motor timer).  I'm using an arduino to put out a test servo signal and my servo moves with it.  I connect the psoc to the servo signal and nothing.  From a hardware setup standpoint, the TCPWM is supposed to reset and start on a rising edge of the servo pulse and I have count enabled for that as well.  On the falling edge, it is supposed to capture and stop.  The clock is HFCLK / 1 = 24 MHz and it is a 16 bit counter, so at a count rate of 418 ns, it will take 24000 counts to get to 1 ms and 36000 to get to 1.5 ms and 48000 counts to get to 2 ms at which point the signal should be off.  The software side of this is pretty straightforward if the interrupt would trigger.  What did I forget to turn on or miss?

Code snippet:

CY_ISR(ServoRead_Int_Handler){

    ServoRead_ClearInterrupt(ServoRead_INTR_MASK_CC_MATCH);

    Countme = ServoRead_ReadCapture();

    Flag = 1;

}

int main(){

                        /* local variables */

    ServoRead_Int_StartEx(ServoRead_Int_Handler);

    isr_1_StartEx(StepperMove);                         // setup timer interrupt sub-routine

    CyGlobalIntEnable;                                  /* Enable global interrupts. */

...

top design:

pastedImage_4.png

pastedImage_5.png

Thanks for any help or suggestions!

0 Likes
1 Solution
Vison_Zhang
Moderator
Moderator
Moderator
First comment on KBA 750 replies posted 250 sign-ins

Please try connect pwm_in signal just to capture terminal and disable other input terminals, call ServoRead_Start() in main.c to start the PWM module.

View solution in original post

0 Likes
2 Replies
Vison_Zhang
Moderator
Moderator
Moderator
First comment on KBA 750 replies posted 250 sign-ins

Please try connect pwm_in signal just to capture terminal and disable other input terminals, call ServoRead_Start() in main.c to start the PWM module.

0 Likes
Anonymous
Not applicable

I had it set up to reset and start on the rising edge and capture and stop on the falling edge so all were connected to PWM signal in as instructed in the psoc 101 video.

The ServoRead_Start() was not  main(), so that was the thing missing and I had to remove the count.  It works.  Thanks!

0 Likes