Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Advice on reducing PWM "jitter"

  1. #1
    Junior Member
    Join Date
    Jun 2015
    Posts
    15

    Advice on reducing PWM "jitter"

    Hi Folks,

    I am using a Teensy 3.6 to time PWM pulses from my RC receiver. I've noticed there is about 1 microsecond of "jitter". Is there any way to reduce this? Here is the ISR code I am using. Thank you very much for any advice!

    Code:
    void Receiver::UpdatePWM(uint8_t ch) {
      // Current time in microseconds
      event_t = micros();
    
      if (digitalReadFast(gc->RX_PIN[ch]) == HIGH)
      {
        // Rising edge, store the time
        ch_time_last[ch] = event_t;
      }
      else
      {
        // Falling edge
        if (((event_t - ch_time_last[ch]) >= gc->PWM_HARD_MIN_RC) && ((event_t - ch_time_last[ch]) <= gc->PWM_HARD_MAX_RC)) {
          ch_pwm[ch] = (event_t - ch_time_last[ch]);
        }
      }
    }

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,691
    I may be wrong, but my playing around earlier with receiving RC pulse widths this way you are unlikely to be be able to measure more accurate than 1us... Just do to the nature of using micros().

    That is suppose when you asked for micros it was something like 400.99us and the other edge of the pulse it was 410.01, you get 10us difference versus
    401.01 and 410.01 which give you 9us difference...

    If you need accuracy I would look at using some form of timer input capture. There are some libraries that do this. Maybe something like freqMeasure

  3. #3
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,562
    I don't see the code generating this - KurtE understands R/C specifics/context better ... Paul once posted this on improving Jitter - some of it may apply. I recently used this with IntervalTimer and saw good results:

    Quote Originally Posted by PaulStoffregen View Post
    I did even more experimenting. After observing for longer times, I did see the Systick interrupt cause the waveform to jitter by about 1 microsecond.

    Writing to the SCB_SHPR3 register to lower the Systick priority, and of course IntervalTimer's priority function to make it the highest proirity, solves that.

    ... POST HERE

  4. #4
    Junior Member
    Join Date
    Jun 2015
    Posts
    15
    Thank you very much for the guidance, I have changed my code and it's now much more accurate (no jitter at the microsecond level). This is the new code I am using, posting here perhaps it can help others...

    Code:
    volatile uint32_t cyccnt_t;
    volatile uint32_t last_cyccnt[_RX_NUM_CHANNELS];
    
    Receiver::Receiver(GlobalConfig *gconfig) {
      gc = gconfig;
    
      // Access to CPU cycle counter
      ARM_DEMCR |= ARM_DEMCR_TRCENA;
      ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
    }
    
    // Private ISR processing routine:
    void Receiver::UpdatePWM(uint8_t ch) {
      // Current CPU cycle
      cyccnt_t = ARM_DWT_CYCCNT;
    
      if (digitalReadFast(gc->RX_PIN[ch]) == HIGH)
      {
        // Rising edge, store
        last_cyccnt[ch] = cyccnt_t;
      }
      else
      {
        uint32_t pwm_t;
    
        // Falling edge
        if (cyccnt_t < last_cyccnt[ch]) {
          // Timer wrapped
          pwm_t = ((UINT32_MAX - last_cyccnt[ch]) + cyccnt_t)/(F_CPU/1000000UL);  // Microseconds
        }
        else {
          pwm_t = (cyccnt_t - last_cyccnt[ch])/(F_CPU/1000000UL);  // Microseconds
        }
    
        //  Only update PWM if valid (within hard limits)
        if (pwm_t >= gc->PWM_HARD_MIN_RC && pwm_t <= gc->PWM_HARD_MAX_RC) {
          ch_pwm[ch] = pwm_t;
        }
      }
    }
    Last edited by Zaite12; 02-08-2017 at 09:02 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •