Bit banging PWM

Andrew Cowan

Senior Member
I'm looking to control some RGBY LED modules via serial.

These modules have built in CC drivers, and accept a PWM input of up to 2kHz. However, the inductors buzz/hum at whatever PWM frequency is used, so a 2kHz PWM results in a 2kHz hum.

Through a bit of trial and error, I've found the least annoying frequency to PWM them at is somewhere around 80 to 100Hz - this is as low as you can go without the LEDs stobing visibly. Therefore I want a PWM signal around this frequency. The solution must continuously output a PWM signal, with a duty given by background serial receive.

I've tried bit banging code for four PWM channels on a 20X2, and it can't do it fast enough - even at 64MHz, there is significant flickering. That's using code like:

Code:
#PICAXE20X2

init:
setfreq m64
hsersetup B9600_64, %01001


do
	get PWM levels from scratchpad
	for counter = 0 to 255
		if PWM_level_1 >= counter
			high PWM_output_1
		else
			low PWM_output_1
		endif
		if PWM_level_2 >= counter
			high PWM_output_2
		else
			low PWM_output_2
		endif
		if PWM_level_3 >= counter
			high PWM_output_3
		else
			low PWM_output_3
		endif
		if PWM_level_4 >= counter
			high PWM_output_4
		else
			low PWM_output_4
		endif
		pause PWM_delay
	next counter
loop
My next thought was to use an 08M2 for each channel - so each 08M2 does one colour. I haven't got any 08M2s yet, but I think code like this might just be fast enough (possibly with PWM_delay being 0):

Code:
#PICAXE08M2

init:
setfreq m32
hsersetup B9600_32, %01000

do
	hserin PWM_level
	for counter = 0 to 255
		if PWM_level >= counter
			high PWM_output
		else
			low PWM_output
		endif
		pause PWM_delay
	next counter
loop
However, my maths says that even this may struggle to keep up.

My latest idea is to scrap a 255 long loop, and instead use pulsout - eg:

Code:
#PICAXE08M2

Symbol frequency = 100	'hertz
Symbol period = wb0
Symbol multiplier = w1
Symbol pulsout_unit = 1.25 'microseconds at 32MHz (I know I can't use decimals, this is just example code)

period = 1000 / frequency 'milliseconds
period = period * 1000 'microseconds

multiplier = period / pulsout_unit 'which is 8000 for 100Hz

init:
setfreq m32
hsersetup B9600_32, %01000

do
	hserin PWM_ontime
	PWM_offtime = 255 - PWM_ontime	'so each period is 255 units long
	
	PWM_ontime = PWMontime * multiplier
	PWM_offtime = PWMofftime * multiplier
	
	pulsout PWM_output, PWMontime
	pulsout DummyPin, PWMofftime
loop
This seems a much better idea, and I think it would be much better at keeping up. A 08M2 would certainly be able to do a 100Hz PWM signal like this.

Is four 08M2s each running this pulsout code going to be the best (and cheapest) way of acheiving this? Are there any obvious problems to my code?

Any thought appriciated.

Andrew


Nb - all the above code is not meant to work, is missing symbol definitions, there be be typos, it uses decimals etc. - it's just showing a concept!
 

Dippy

Moderator
Hi Andrew, I've done a similar thing using compiled PIC @20MHz.
I was multiplexing 8 x RGBW channels. The effective PWM fq was about 2kHz with 255 steps. So, I'd guess your effective PWM would be nearer 200Hz?
Also, if you do a byte-by-byte read within the loop you can remove any flicker when new data is processed.
My code also included LED temp checks (ADC) within the loop.

Step number one would be to reduce from 255 to 100. I don't think you'll notice much visual colour change difference but the loop should run faster.
My code was a little bit different but a similar principle. So, yes it works, but you are restricted by processing speed.
 

Andrew Cowan

Senior Member
A genuine "don't know",
but could a 28X2 help in any way?

e
Interesting thought.

The lowest frequency the 28X2 can do is 244Hz at 4MHz.

However, the 28X2 also supports 31kHz, 250kHz, 500kHz , 1MHz and 2MHz. So, running at 1MHz would give a lowest frequency of 61Hz.

I'm not sure if I have any of the new type of 28X2 that support four PWMs, so I'll need a few of them as well as a tube of 08M2s to play with.

With that and Dippy's suggestions, once the chips have arrived, I can start experimenting!
 
Last edited:

hippy

Technical Support
Staff member
These modules have built in CC drivers, and accept a PWM input of up to 2kHz. However, the inductors buzz/hum at whatever PWM frequency is used, so a 2kHz PWM results in a 2kHz hum.
Is there any way to mod the modules so they don't hum ?
 

Andrew Cowan

Senior Member
I might look into replacing the inductors with higher quality ones - I think the humming is just due to low cost poorly wound inductors. Possibly coating the inductors in varnish/enamel/RTV might help - again, it seems I'll have to do some experimenting.
 

westaust55

Moderator
@Andrew

WHat you are observing/hearing is pretty much the same effect as when operating a VSD (VVVF) type motor speed controller at slower carrier frequencies and at low speeds when a hum/whine can be heard from the motor winding (which are equal to your inductors).

Using varish or resin to hold the inductor turn solidly together will minimise that sound whioch comes from winding moving.
In motors and transformers (that hum you hear from big power transformers at 100 Hz) there can also be noise from vibration as the core laminations vibrate as well.
 
Last edited:

John West

Senior Member
Why not add electrolytic caps to the outputs to smooth out the waveform for the LED's? Sometimes a hardware fix is better (easier) than a software one.
 

inglewoodpete

Senior Member
Why not add electrolytic caps to the outputs to smooth out the waveform for the LED's? Sometimes a hardware fix is better (easier) than a software one.
My observation of electrolytic capacitors when used with PWM is that you end up with an average voltage rather than the pulsed full voltage that you want.

Eg a white LED runs at about 4v. It works fine with PWM with no capacitor at all mark/space ratios. If you put an electro across supply to reduce the noise, you find at some point that the peaks stop going over 4v and the LED stops.
 
Top