External Links

Creative Science Centre



// #include "http://www.byvac.com/mBlib/flb/Library/2016/lib_pwm.bas"

Any timer can be used if the timer is set to give a 6.4uS period and the timebase is a multiple of this, 781 will give 5mS.

The MX3 has the PWM on fixed pins corresponding to RD0 to RD4 but the MX1 can output PWM onto any pin that can output to OCn. This will be designated OC1s, OC2s etc.


*timer() is one of the timers as defined in the timer library e.g. *TIMER2()
channel is the channel number 1 to 4 or 5
pre is the timer prescale
timebase is the PWM width period

This is used to initialise a channel, there are 5 channels 1 through 5, on the MX3 the output is on RD0 to RD4. On the MX1 the output pin is chosen using the PPS facility, see pps library. The timebase will apply to all channels and so setting the timebase for on channel will make it the same for the other channels.


This will set the duty cycle for the specified channel. The channel is fully on when the duty cycle is greater than or equal to the timebase.

Example 1

Use timer 2 and channel 1 on RA0 and set a PWM timebase of 20mS using a prescale value of 7. This will give, according to the table in the timer library a period of 6.4us

1) Initialise the pwm pwm_init(*TIMER2(),1,7,3124) // 3124 gives a 20mS timebase

2) Set the PPS to use OC1 on RA0, look up the table in the pps library and look for OC1s on the output (green) bit of the table, along side this you should see PRA0 for MX170. For MX370 there is no port A so use RPD0  pps_out(*PRA0(),*OC1s()) or pps_out(*RPD0(),*OC1s())

Using these values gives 6.402 uS per count, so if a pulse width of 1mS is required then it would be 1 / 0.006402 or 156 counts.

Example 2 (SERVO)

To use the PWM as a servo driver we can use a more refined output a lower prescale value. The period needs to be 20mS and we must not go over a count of 65,000 in order to use a 16 bit timer so the ideal prescale value is 4 which will give 2500 counts per mS.

1) Initialise the pwm pwm_init(*TIMER2(),1,4,50000) // for 20mS timebase

2) Set pps as above pps_out(*PRA0(),*OC1s())

A standard servo goes from about 0.7mS, mid 1.5mS to 2.8mS. This will correspond to values 1750, 3750 and 7000 giving a very good resolution.

The value of course is placed in the pwm_d() function thus:

pwm_d(1,3750) for midpoint