How to generate adjustable skipped pulses (PSM) from pwm output signal from Timer1 (Pin9)?

Hi!

I'm using pin 9 from Timer 1 on an Arduino Uno to generate a pwm (Fast_PWM) signal. I could use Pin 10 also.

But I need a way to count some x pwm pulses (or the elapsed time from that number of pulses) from that pin and then disable that pwm output, and then re-enable it after some more pulses or after some elapsed time again, in order to to have some skipped pulses in the pwm output.

I need to be able to get what's in the picture below, taken from a motor driver I have, that I'm trying to emulate.

I saw some posts about counting PWM pulses, but they are not really adapted to my case...

How could this pwm skipped pulses be done?

Do I have to connect the pwm output pin to another digital pin so this other pin can read the pulses? Or from the Timer1 itself it can be done without the need of an extra digital pin?

Another idea I had, that I could implement in hardware is the following, to generate this adjustable PWM pulse skipping idea:

  1. Connecting my pwm output pin (Pin 9) to an Arduino digital INPUT pin, let's say, pin 5, for counting the pwm signals

  2. Connect the same pwm output pin (Pin 9) to the source pin of a P-Mosfet, and the drain of the mosfet to the motor driver pwm INPUT.

  3. The gate of this mosfet would be pulled high (so it's turned off) and connected to an OUTPUT Arduino digital Pin, let's say pin 6.

  4. Then, pin 5 would continuously read and count the pwm pulses from the pwm output Pin 9

  5. And pin 6 would turn off the gate of the P-Mosfet (that "transfers" the pwm signal to the motor driver) as soon as x number of pulses are read from pin 5.

  6. Pin 5 would still be reading the pwm pulses being generated from Pin 9. After more x number of pulses, it would then turn on again the gate of the P-mosfet and allow the pwm signal to keep going to the motor driver...

Is it a correct idea? Feasible? Or the first one, using timers (which I have no experiece at all) is a simpler way?

Anyone could help me implement it in code? I'm not into direct registers/interrupts coding...

Thanks!

Interested question. I don't know the answer and I will be following this topic to see what others suggest.

Are you sure that the gaps are after a certain number of pulses rather than a certain interval? Does it matter? I'd be inclined to see if it's possible gate one timer with another running more slowly. The second, slower timer would gate the faister timer at an appropriate interval.

I stress this is just an idea, I have not investigated its practicality.

Watching for other replies with interest.

You could change the output to an input to skip pulses then back to an output. I do not know if you have enough time to do that but if so no additional hardware.

Thanks! Good!

I can post the full code here, don't know if it's possible due to size... but the parts related to Timer1, i did like this (not my code, it's adapted from a BLDC controller code).

I only set-up the frequency of the Pwm Pin 9 to fast PWM 0-255. I tried slower frequencies but the motor is a lot noisier so I stuck (for now) with fast PWM to 255. But I can change it.

  TCCR1B = 0b00001001;  // fastPWM to 255, no prescalar - 61.5Khz
 // TCCR1B = 0b00000001;  // PWM to 255, no prescalar - 31.5Khz
 // TCCR1B = 0b00001010;  // FastPWM to 255, 1/8 prescalar - 7.68 Khz
 // TCCR1B = 0b00000010;  // PWM to 255, 1/8 prescalar - 3.93 Khz

TCCR1A = 0x81;  // turn pin 9 (OC1A) PWM ON 

And after reading from a potentiometer a value, pwm value is defined:

//    ADCSRA |= 1 << ADSC;    // start conversion
    if (!(ADCSRA & 0x40)) {  // wait for conversion complete
      motor_speed = ADCH;   // read ADC data (8 bits only)
      ADCSRA |= 1 << ADSC;  // start next conversion
      if (motor_speed < PWM_MIN_DUTY) {
        motor_speed = PWM_MIN_DUTY;
      }
      SET_PWM_DUTY(motor_speed);
    }

and set here:

void SET_PWM_DUTY(byte duty) {
  OCR1A = duty;  // set pin 9  PWM duty cycle
}

So in Timer1 I'm only changing the value OCRA1 duty, nothing else, apart from the scalar (which for now is 1) and the pwm-mode setting. (Fast PWM-0-255)

I need to tell that, for the switching of the A,B and C phases of the motor, and send this PWM signal (OCR1A) to each of the phases, there's an interrupt routine (below) that when a zero crossing event happens, it change the active motor phase to make the spin possible. So as long as the motor is spinning, it's being called at each zero-cross event.

// pin change interrupt 2 (PCINT2) ISR
ISR(PCINT2_vect) {
  if ((PIND & PCMSK2) != pin_state)
    return;
  // BEMF debounce
  for (byte i = 0; i < 15; i++) {
    if (bldc_step & 1) {
      if (PIND & PCMSK2) i -= 1;
    } else {
      if (!(PIND & PCMSK2)) i -= 1;
    }
  }

  bldc_move();
  bldc_step++;
  bldc_step %= 6;
}

This interrupt reads signals from Pins 2,3 and 4.

So I wonder if an interrupt to count the pwm pulses could mess with this other interrupt which will be going on at the same time...

Does this help you to figure it out how do do it?? If not, ask me!

Regards, thanks, Rodrigo

Not a solution, just suggestion...

Uno is not the most suitable controller for complex pulse sequences.
For example, on the STM32, you can set the number of pulses in the PWM sequence, after which the timer will stop itself, (optionally generating an interrupt).
The similar features are in some other controllers.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.