"Phase Locked" Waveform: fix significant jitter, that stresses servos and is clearly audible in Tone output by dok-net · Pull Request #7022 · esp8266/Arduino

@Tech-TX Otherwise, I've found a bug and commited a fix to this PR. I am sorry, I am bit overwhelmed by your signal traces, but what I grasp pointed to a timing error and that bug would cause the transitions from duty to off cycle to happen at rather random times. I can only ask you to re-test, thanks for the great support.

No worries! If this was easy, it'd be called 'playtime'. 😄 I'm having some more strange issues here, so I'm going to do another complete wipe and then pull your latest changes. I suddenly don't trust anything on the PC as git isn't tracking when I make changes to files any longer, or at least it's not doing what it used to.

The scope is set for 'infinite persistence', so that it shows a history over about a minute's time. I'm triggered on the rising edge of the CH1 PWM, then I've moved out into the middle of the cycle so that the edges or steps in PWM change should be roughly even. The granularity of the current master is 1us, so at 977KHz PWM = 1 the pin is high for 1us, then low for 1023us. The next step PWM = 2 the pin is high for 2us. On your PR as of yesterday, that 1us step size was 7.76us, so you have/had roughly 1/8th as many steps between 0 and 1023 as the master has. Since the scope is set to STORE, it captures all of the edges as the PWM increases or decreases, showing the PWM step size.

@dok-net Dirk, here's a short video showing what it looks like. First it's zoomed out on infinite persistence to show the whole waveform (I'm triggering on the bottom channel) and then zoomed in to show the edges near the end-points of (PWM = 1 / 1022). I didn't let it go to zero or 1023 so that the phase would stay constant. I have it set for 20ms at each PWM step, slowly going up and then down. Every place you see a line on the scope, the signal spent enough time at that level for the scope to record it. In this case, 20ms on each discrete PWM edge as it moves through time.

Here's what I've seen so far, working back and forth between the current master and this 7022 PR:

  1. Neither master nor PR actually change the PWM frequency until the duty cycle is changed (minor)

  2. Above 977Hz PWM duty cycle 1 = low / disabled (no output) due to 1us granularity of time (master)

  3. Duty cycle steps generally only change in integer multiples of 1us increments (1us, 2us, 3us, etc) so there are missing steps at any frequency not a multiple of 1us * 1023, max 977Hz. Above that it gets progressively worse as the 1us step size is the minimum increment. At 9.8KHz there are only ~ 100 discrete steps, at 40KHz there are only ~26 steps. All 1022 PWM steps are available at 977Hz, 488Hz, 325Hz, 244Hz, 195Hz, 162Hz, 139Hz, 122Hz, 108Hz, 97Hz, 88Hz, 81Hz, 75Hz, etc. Calculation = truncate(1/(1E-6 * 1023)) for the PWM frequencies with all (or most) discrete PWM steps. (master)

  4. Current master: minor error in timing 9 > duty cycle > 1013 (wider steps & missing steps)

  5. Up to 7us jitter on any output if other edges are walking past it (master), PR is/was worse. It's unavoidable when the time to the next edge is less than ~ 5 to 6us due to the calculations required.

  6. PWM = 0 the pin is low, PWM = 1023 the pin is high, so the range is 1-1022 for actual PWM; the other two states (0 and 1023) the PWM isn't running and the pins are fixed level.

  7. Many analog servos today work better at 200Hz frequency (faster response), default 50Hz is fixed in servo.h (should be user-configurable without modifying a core header file) (future enhancement)

  8. Tone output only seems to go up to 5KHz maximum (master)

Please understand that I haven't used PWM on the ESP8266 before, so some of those observations may be "well, of course it does that" to the rest of you. ;-)