How can pwm timers be synchronized

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
blueslow
Posts: 13
Joined: Wed Feb 18, 2015 5:33 pm

How can pwm timers be synchronized

Post by blueslow » Wed Aug 26, 2015 4:22 am

HI

I have two timers as pwm that drive two pins. How can the timers (actually pin output) be synchronised upon start and change of PWM width?

I would like to do this in python, without inline assembler or DMA.

With the attached code below I get the following results.
I can't tell the difference between the timers but I guess it is less than 25µs (sirst comment)
The difference between change of X1 and X2 at pwm width change is approx. 10µs (second comment).

I would like to achieve differences around 1-2 µs.

One thing that have crossed my mind in this case is to connect one pwm timer to both pins, is that possible and how to I accomplish that?

Suggestions?
/Klas

Code: Select all

import pyb

hled = pyb.LED(4)
hled.off()
heat = 0
oldHeat =0

sw=pyb.Switch()

pinh =pyb.Pin('X2',pyb.Pin.OUT_PP) #X2 has timer5, ch2
pinv =pyb.Pin('X1',pyb.Pin.OUT_PP) #X1 has timer2, ch1
trigger = pyb.Pin('X5',pyb.Pin.OUT_PP) #X5  a trigger debug pin for time measurement
trigger.low()
timh = pyb.Timer(5,freq=1000)
timv = pyb.Timer(2,freq=1000)
trigger.high()
# Reset the two timers to get them start at the same time, or at least as good as possible.
timh.counter(0)
timv.counter(0)
# The above solution yields a difference off approximately 7 µs beetween the levelchange two pins, not good enough.
trigger.low()
chh =timh.channel(2, pyb.Timer.PWM,pin=pinh)
chv =timv.channel(1, pyb.Timer.PWM,pin=pinv)
chv.pulse_width_percent(0)
chv.pulse_width_percent(0)


def pressed():
    global heat
    pyb.LED(3).toggle()
    heat = heat + 200
    if 1000 < heat:
        heat = 0

sw.callback(pressed)
while True:
    if oldHeat != heat:
        oldHeat = heat
        pwmheat = heat/10
        trigger.high()
        # Change the pulse width
        chv.pulse_width_percent(pwmheat)   
        chh.pulse_width_percent(pwmheat)  
        # The above solution yields a difference off approximately 7 µs beetween the levelchange two pins, not good enough.
        trigger.low()
        hled.intensity(heat>>2)
        print(heat, heat>>2, pwmheat)
    pyb.delay(100)

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: How can pwm timers be synchronized

Post by dhylands » Wed Aug 26, 2015 5:25 am

If the output are 2 channels from the same timer then they'll automatically be synchronized.

Otherwise there isn't anyway to get them perfectly synchronized. You can get them close by using python assembler and writing 0 to two different channel counters.

blueslow
Posts: 13
Joined: Wed Feb 18, 2015 5:33 pm

Re: How can pwm timers be synchronized

Post by blueslow » Wed Aug 26, 2015 7:12 pm

Thanks.

Lets say that I use one timer.
If the output are 2 channels from the same timer then they'll automatically be synchronized.
How can the above be accomplished?
E.g how do I assign each channel to each pin to one timer?

/Klas

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: How can pwm timers be synchronized

Post by dhylands » Wed Aug 26, 2015 8:10 pm

You can't really control which channels go to which pins, but the mapping is shown here:
http://docs.micropython.org/en/latest/p ... ckref.html (click on the picture for a bigger verision).

For example, TIM2_CH1 is on pin X1, TIM2_CH2 is on X2, TIM2_CH3 is on X3 and TIM2_CH4 is on X4. So those 4 channels are 1 thru 4 on timer 2.

On the STM32s seem to have at most 4 channels for a given timer. The channels with an N after them (i.e. TIM1_CH1N) is channel 1 of timer 1 with a negated output.

blueslow
Posts: 13
Joined: Wed Feb 18, 2015 5:33 pm

Re: How can pwm timers be synchronized

Post by blueslow » Thu Aug 27, 2015 6:01 pm

dhylands wrote:You can't really control which channels go to which pins, but the mapping is shown here:
http://docs.micropython.org/en/latest/p ... ckref.html (click on the picture for a bigger verision).

For example, TIM2_CH1 is on pin X1, TIM2_CH2 is on X2, TIM2_CH3 is on X3 and TIM2_CH4 is on X4. So those 4 channels are 1 thru 4 on timer 2.

On the STM32s seem to have at most 4 channels for a given timer. The channels with an N after them (i.e. TIM1_CH1N) is channel 1 of timer 1 with a negated output.
Yes I understand the above.

What I do not understand is how to make the right python calls in order to have timer2 to use both TIM2_CH1 on pin X1 and TIM2_Ch2 on X2 at the same time, so I only have have to make one call to ...pulse_width_percent(), e.g. is this done with multiple calls to

Code: Select all

cch=timh.channel(1,pyb.Timer.PWM, pin=pinv)
cch=timh.channel(2,pyb.Timer.PWM, pin=pinh)
and then a single call to

Code: Select all

cch.pulse_width_percent(xxx)
to change the pulse width settings in timer 2 and consequently change the output at pin X1 and X2 simultaneously, or is this done in some other fashion?

/Klas

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: How can pwm timers be synchronized

Post by dhylands » Thu Aug 27, 2015 7:56 pm

blueslow wrote:
dhylands wrote:You can't really control which channels go to which pins, but the mapping is shown here:
http://docs.micropython.org/en/latest/p ... ckref.html (click on the picture for a bigger verision).

For example, TIM2_CH1 is on pin X1, TIM2_CH2 is on X2, TIM2_CH3 is on X3 and TIM2_CH4 is on X4. So those 4 channels are 1 thru 4 on timer 2.

On the STM32s seem to have at most 4 channels for a given timer. The channels with an N after them (i.e. TIM1_CH1N) is channel 1 of timer 1 with a negated output.
Yes I understand the above.

What I do not understand is how to make the right python calls in order to have timer2 to use both TIM2_CH1 on pin X1 and TIM2_Ch2 on X2 at the same time, so I only have have to make one call to ...pulse_width_percent(), e.g. is this done with multiple calls to

Code: Select all

cch=timh.channel(1,pyb.Timer.PWM, pin=pinv)
cch=timh.channel(2,pyb.Timer.PWM, pin=pinh)
and then a single call to

Code: Select all

cch.pulse_width_percent(xxx)
to change the pulse width settings in timer 2 and consequently change the output at pin X1 and X2 simultaneously, or is this done in some other fashion?

/Klas
That's almost correct.

What you should do is to initialize the timer, and then store each channel in a separate variable. Something like:

Code: Select all

t2 = pyb.Timer(2, prescalar=83, period=19999)
ch_v = t2.channel(1, pyb.Timer.PWM, pin=pinv)
ch_h = t2.channel(2, pyb.Timer.PWM, pin=pinh)
ch_v.pulse_width(1000)
ch_h.pulse_width(2000)
The particular parameters I used above are typical for a servo. Using a prescalar of 83 will give a 1MHz timer clock (so the 1000 on ch1 wil make the pulse be high for 1000 usec). The total width of the pulse is 20msec (so 50Hz).

Both channels will rise at the same time and fall after the appropriate pulse width. You can also use mode=pyb.Timer.CENTER when you initialize the timer which will make the channels have the PWM aligned in the center (which is popular for HBridges so that the FETs don't turn on at the same time).

The example on this page: http://wiki.micropython.org/platforms/b ... r-Examples shows a logic analyzer capture of center-aligned PWM pulses.

blueslow
Posts: 13
Joined: Wed Feb 18, 2015 5:33 pm

Re: How can pwm timers be synchronized

Post by blueslow » Sun Aug 30, 2015 12:13 am

Thanks, I will try it out.

Klas

Post Reply