Photon Hardware PWM - Any Examples?

@mterrill
Some more progress

with the following changes:

    #define PWM_FREQ 30000 // in Hertz (SET YOUR FREQUENCY)  
    ...
    ...
    ...
      //TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned3; // symmetrical PWM
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 
    ....
    ...
    
    
    ...
   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // can't find a decent reference to say whats the diff between PWM1 and PWM2

Both frequency accuracy & duty cycle seem spot on.

PWM1 & PWM 2 seem to invert the signal, based on my observations.

Here is an extract from an application note’
AN4013 General-purpose timer modes

2.5 Timer PWM mode
The timer is able to generate PWM in edge-aligned mode or center-aligned mode independently on each channel, with a frequency determined by the value of the TIMx_ARR register, and a duty cycle determined by the value of the TIMx_CCRx register.
PWM mode 1

  • In up-counting, channelx is active as long as CNT< CCRx, otherwise it is inactive.
  • In down-counting, channelx is inactive as long as CNT> CCRx, otherwise it is active
    PWM mode 2
  • In up-counting, channelx is inactive as long as CNT < CCRx, otherwise it is active.
  • In down-counting, channelx is active as long as CNT > CCRx, otherwise it is inactive.

FYI: Rise times on my scope show as <10ns , Fall times <5ns = pretty fast

A big big thanks to everyone who contributed & made this hardware PWM stuff accessible on the Photon :+1:

see correction below

2 Likes

So, measured as 30Khz with PWM1 and the same period formula?

Yes - with the TIM_CounterMode_Up instead of TIM_CounterMode_CenterAligned3 & PWM1

With PWM2 the signal is inverted so PWM1 @ 30% would give 70% with PWM2 setting.

See correction below!

1 Like

Correction @mterrill

I also had to make the following change to the period formula…:
// period = (uint16_t)(((SystemCoreClock) / PWM_FREQ)-1);
period = (uint16_t)(((SystemCoreClock/2) / PWM_FREQ)-1);

Apologies, my version of the test code had drifted away from yours as I am more interested in IR carriers. So after your last post I decided to reflash your code again with my changes and needed to do the above to get 30kHz.

Summary of changes to your code:

    //TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned3; // symmetrical PWM
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 
...
...
    // period = (uint16_t)(((SystemCoreClock) / PWM_FREQ)-1); 
    period = (uint16_t)(((SystemCoreClock/2) / PWM_FREQ)-1);

From the STM32F20xxx datasheet page 31

TIM4 is 60Mhz, which explains the /2 needed in the formula.

I was playing with TIM1 which is 120MHz(thus no /2 required) - which explains the error/confusion above and the earlier post from @peekay123

@mdma It would be helpful if the :particle: developers would chip in and confirm which timers are reserved for the Photon internals - to avoid potential conflicts in future.

1 Like

@AnalysIR, on the Photon, TIMR1 and 2 are reserved for internal use (eg RGB LED). TIMR3, 4 and 5 are used for various pin functions (PWM, Tone). TIMR6-14 are totally unused though not mapped to any pins with TIMR8 being an advanced timer. The timer-to-pin mapping is shown in the Photon datasheet under the “pin out diagram” section.

https://docs.particle.io/datasheets/photon-datasheet/

1 Like

@peekay123
Yes I had seen the pin mapping.

For PWM it seems TIM2 overlaps with the RGB pens
TIM1 with the Tx/Rx pins
TIM3 with SPI pins & setup button
TIM4 with I2C pins
TIM5 with WKP

PWM/Servo/Tone seem to be on the ADC pin but no Timer is referenced.

etc etc

Other than the functions detailed on the pin map, would the use of the timers above for PWM conflict in any way with the internals of the Photon system firmware. e.g. I understand that using TIM1 for PWM would impact the use of Tx/Rx as UART and so on.

Can this code be used for particle electron?

how do i set the output port and pwm value?