digitalPulse() jitter/offset

Posted on
  • Hello,

    I was evaluating if the digitalPulse() (on ESP32 v2.00) timing would meet the requirements of a project and found that:

    pinMode(D32, 'output');
    setInterval(()=> {
          digitalPulse(D5, 1, 2);
    }, 50);

    Produces pulses from about 2096us to 2160us.

    Being generated by hardware I wonder if it can do any better. Maybe the original espruino does not have the jitter?

    Thank you.

  • Tue 2018.11.06

    Although I'll agree the accuracy isn't specified,­obal_digitalPulse

    the implication is millisecond(s) wide pulses.

    Have you tried using an array of pulse values (see description in link above) and just a single digitalPulse() to rule out whether setInterval() is adding unnecessary (likely) intermittent delay?


    'It uses a hardware timer to produce accurate pulses'

    For a 2msec pulse 4%-8% error is rather odd. . . .

  • I understand that a single call to digitalPulse may have better accuracy between pulses.. but as the application will fire a pulse after another sensor decodes a pattern. The setInterval came from the test code I added to simulate the hardware.

    The question now is if the original espruino does better than the ESP32 port.

  • if the original espruino does better than the ESP32 port.

    Yes - the official boards use an IRQ-based timer. Just tried this on a Pico and it's exactly 2ms to as near as I can measure on my digital scope (so well within 1%)... And if that's not good enough there's some documentation on how to use the timer peripherals in the device itself.

    There was a recent change in ESP8266 courtesy of @MaBe that fixed the issues that has, and it does look like the ESP32 is using IRQs so I'm not sure why there would be the variance.

    I just had a quick look and @JumJum it could be that gettimeofday may be using the normal low-speed RTC, which might explain some timekeeping issues:­b/master/examples/protocols/sntp/README.­md#timekeeping

    While the timer is accurate, it's set using the current time as a base - so if the timekeeping is 'grainy' it can screw things up.

  • We are using both timers as suggested:­dTools/blob/master/esp32/build/app/sdkco­nfig#L200

  • Well... then their timer implementation is not good! I was hoping to see at most 4us jitter.

    The idf has a timer jobs linked list. Does espruino run another one on top of it?

  • Does espruino run another one on top of it?

    Yes, but for something like digitalPulse there's one job queued up, so there is no real overhead involved.

    Espruino's timer implementation could be improved (eg. for digitalPulse there's no need to use the current time at all), but it's reasonably low priority at the moment as it's quite a big change and it works fine on official boards. There's an issue for it here:­ues/1444

    If you really want accurate timing without actually buying an official board it's possible there's some spare timer hardware on ESP32 that you could set up yourself with peek and poke.

  • If you set up a pwn output is the timing for this accurate?

  • analogWrite(D5,0.5, { freq : 3000 } ); is perfectly stable. Can not see jumps down to 5ns per division. Frequency reads 3003hz.

    digitalPulse(D5, 1, 1); // 1.106ms
    digitalPulse(D5, 1, .2); // 0.5ms

  • I think this might be the issue here:­b/9bb8c66015d8b9fa1aaa80a4eaab217e2f308b­e0/targets/esp32/jshardware.c#L623

    If the timer is less than 30 - it's set the 30. @jumjum - can you recall why?

  • As a possible work around - you might be able to use the pwm output and do a setwatch on that - and in the setwatch- use that to drive another pin low then high and low again. You can use a variable flag to say if you want the out put in the output pin.

    Just an idea.

  • So, is the pwm software driven? Or espruino will use hw interrupts for the pwm edges?

  • No - the pwm on the Esp32 is hardware driven.

    Or another thought - you could send an array of o,1,1,1,0 and then adjust the number of 1s to be close to 2us

  • Or maybe:

    analogWrite(D5,0.002, { freq : 1 } );
    setTimeout(function() { digitalWrite(D5,0); }, 500);

    So use the hardware PWM to do the output, then cancel it in software after the first one - leave the duty cycle low enough that any jitter in execution by Espruino won't be an issue.

  • Sorry, no bell is ringing on that.
    Could be in there from beginning by nkolban ?

  • Git blame to the rescue!­mit/1b3f15a1951f5bc3fcb59cfa768abdb8840a­bb36

    I imagine it will break if you don't at least limit it to 1us, but it feels like make 30 was there for a reason :)

  • Looks like the original esp32 port used RMT then changed to the Espruino style. I wonder why.

    @Gordon Can the timer functions be used with or changed to use the floating point delay to achieve sub ms timing?

    Sub millisecond would only make sense in the digitalPulse function, because I see that:

    setInterval(()=> {
      }, 5);

    Gives a high pulse from 3.6 to 7ms.

  • Looks like the original esp32 port used RMT then changed to the Espruino style. I wonder why.

    What do you mean by espruino style?

  • That came from the source code comments!

    The RMT code is commented out... with it and added code from the nrf52, it says.

  • Can the timer functions be used with or changed to use the floating point delay to achieve sub ms timing?

    That won't be your issue. The timer functions are currently using us timing anyway.

    espruino style?

    He's probably referring to it using jstTimer rather than what amounted to a while(getTime()<endTime); loop.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

digitalPulse() jitter/offset

Posted by Avatar for barbiani @barbiani