FYI about using PWM 13-16 with interrupts

Here’s what I posted to Innovation FIRST and their answer.

Question:
In the original default code, for the v2.2 compiler, PWMs 13-16 use a generate function to control the PWMs. How does this function work and what exactly does it do? How are PWMs 13-16 different from PWMs 1-12? I am asking this because yesterday we were testing our modified default code using optical encoders connected to the digital I/O pins. The wierd thing that happened was that as the encoders were rotated faster (about 900rpm attached to a cordless drill) the drive wheels started rotating. I looked through the code and did not see any other function other than the generate function that calls pwms 13-16. For now we just changed our drive wheels to operate off of PWM 9-12 and the wheels do not turn by themselves when the encoders are rotated really fast.

Also, is there a reason why the default code used with the camera uses pwm 11 and 12 while the default code without the camera uses pwms 13-16? Is this similar to the issue I am having now?

Answer:
The PWM outputs 1 - 12 are handled by the Master microprocessor. PWM outputs 13 - 16 are generated via the user code. All four of these PWMs get generated within 2ms at a 26.2 ms rate. These PWMs are susceptible to interrupt interference. PWM signals have 255 steps and each step is ~5us. Since interrupts have at least a 5us latency, they will stretch a PWM signal up to the amount of time it takes to process the interrupt. So if your user code is processing interrupts at a high rate or your interrupt routines are long, the pwm signals on outputs 13 – 16 could be modified/stretched to create a forward condition on a motor. PWM outputs 13 – 16 should be avoided if user code is interrupt intensive.

My thoughts: I guess that’s why most people don’t use pwm 13-16

Can someone verify this? I believe (though could be wrong) that the generate PWMs function just gives it to the hardware, and that handles it.

If I’m wrong, I guess we have ourselves 4 more digital outputs.

Yes, I noted some general wackyness in PWM13-16 last year and mentioned it in the IR beacon tracking FAQ.

-Kevin

Team 177 also abandoned PWMs 13-16 last year for the same reason.

Note to self: Use PWM16 to power camera!

I am using the default code and it is sending the same value to pwm13 ,. 14 , 15 , and 16. Any ideas on how to fix it? Right know on the test robot I have 2 mootars wired backward to get it to go straight when the joystick is in the forward positon.

PWMs 13-16 appear to be bit-banged. We had trouble with them last year. If an interrupt occurs while the generate_pwms function is running, the pulse width will be lengthend (or shortened, depending on the part of the cycle you’re in) by the amount of time that the uC takes to handle the interrupt. We moved the generate_pwms call to the very last thing that happened each loop - this solved the problem.

The CCP module on the PICs generates a pwm signal that is variable in the duty cycle. The kind that the victors and servos use is variable in the pulse width. (sounds similar, but they are different) So the pwm signal would have to be generated in software, since the hardware isn’t suitable for what we need.

But like you pointed out, nothing that careful programming can’t resolve.