Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Four independent PWM signals in software

Status
Not open for further replies.

atferrari

Well-Known Member
Most Helpful Member
18F family - Assembler.

I need four independently-variable duty cycle PWM signals destined to generate each one a stable control voltage with 10 bit resolution.

Chips like 18F4550 have 4 PWM outputs but they are aimed to drive H bridges so cannot be used as I need.

Understand the solution is to do it in software. Have searched but could not find any post directly related to my problem.

I have the feeling that ruling out ANY glitches should be the hardest part to solve, if at all possible.

Ideas anyone?

Gracias.
 
Are you saying that you require PWM or can you use alternative solutions?
I am thinking of two MCP4922. You can control the output voltage via SPI by setting the internal registers of the DACs (this is equivalent to setting the duty cycle of PWM signals with your control variables).
I've used the 4921/22 with good results.
 
Last edited:
Hi Agustín,

Please tell us what is the target PWM period or frequency that you're shooting for? This will help us determine the type of solution that may work best for you.

Regards, Mike
 
Thanks to you all for replying. I go in order:

eng1:
I prefer to use PWM, if at all possible, to keep the parts count low. But eventually could resort to some kind of DAC.

nickelflippr:
It seems (just seems) overkill but, why not?. Should check local availability.

Mike, K8LH:
LTSpice says that 20KHz could be good for me. I do not discard using something slower / faster if software implementation demands. Would use 4 MHz xtal if at all possible.

Gracias again.
 
LTSpice says that 20KHz could be good for me. I do not discard using something slower / faster if software implementation demands. Would use 4 MHz xtal if at all possible.
Even with hardware PWM, you need at least a 20.5 Mhz clock for 20Khz PWM with 10bit resolution.
 
Lower frequency then...

Mr RB:
Changes at the pace imposed by the user and always one output at a time. No worries here. My sole concern is how to generate them.

kchriste:
Yes. Last night, revising the manual of the 18F4550 found that the table shown there is calculated for a 40 MHz xtal. That makes for lower frequencies than I elected at first.

K8LH:
Tested with LTSpice and I would go then with a frequency around 3900Hz.

General comments:

I expect to have the micro focused on generating those four PWM signals, carrying out the ancillary duties (keyboard, display, etc) at ease.

My search in Google did not come with too many concrete things that I could use a starting point. Not too much time here to work out something by myself. Still travelling like a mad. :mad: :mad:

There are moments that I am about to give up and go for the DACs from MCP or even Maxim.

Thanks for your replies.
 
Last edited:
Cutting the Gordian knot

After checking what was available locally, costs and available time I decided to buy the 18F4431 (some 10 USD on the counter). It was the cheapest / most feasible option.

I still think that some limited range PWM could be possible in software if PART of the whole range is used. I would like to try that in the future, just as a proof of concept.

BTW, anyone willing to give ideas about my initial request will be still welcome and heard.

Gracias to all replying!!
 
Last edited:
Ok, if you don't need a fast rate of change of the voltages, you can use a slow PWM freq and larger RC filtering.

Generate each PWM signal in sequence. This limits you to about 0v to 1v range for each voltage output.

1. on TMR1 overflow; set the PWM pin (make / edge)
2. use the capture compare int to see when the pwm period ends, then clear all PWM pins (make \ edge).

Then on the next TMR1 overflow do the next PWM value, so the 4 pwm pulses are made 1 at a time.

This will give you the full 16bit PWM resolution, but the max voltage of each PWM will be about 1.2v.

Does that help?
 
Yes Mr RB,

I think it is a simpler and feasible way to go. Thanks.
 
Last edited:
I don't know if this will help you do what you want but It is possible to run a lot of PWM signals in this manner. I have a sample program here that runs two PWM's using the data it gets from two separate A/D conversions. The way to make more PWM signals is simply add more channels to the "pwm" part of the program. To change the frequency you change the TMRO value or prescaler. To change the period you change the values of the folder period. (also some adjustments might need to be made to your channel values.)

The way it works is TMRO interrupts and adds one to your period value.
Then it adds your channel value to the period value.
If flag tripped turn off that pin.
If flag not tripped turn on that pin.
It goes through the channels and checks them all.
Last, when the period overflows it resets everything and starts counting again.

This allows you to keep all your PWM stuff free from the rest of your program. Also, it gives you pretty good resolution. However, it seems like you need a bit more resolution. I'm sure you can fix that with a tweek to the period counter and the channel values. The problem is it takes 20 to 30 commands every interrupt.
Good luck and I hope this helps in some way.

Code:
;learning to do pwm with tmro 12f675

	list P=12f675
#include <p12f675.inc>
	__config _INTRC_OSC_NOCLKOUT & _BODEN_OFF & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CPD_OFF & _CP_OFF 
	ERRORLEVEL -302
	
	cblock		20h
	pwmcounter, channel1, channel2, period
	endc

	ORG		0000h
	goto	setup
	
	ORG		0004h
	call	pwm
	BCF	INTCON,2
	RETFIE				;reset interrupt
	
setup
	bsf	STATUS,RP0	;bank 1
	movlw	0x3c
	movwf	ANSEL
	movlw	0x3c
	movwf	TRISIO		;set I/O
	movlw	0xd8		
	movwf	OPTION_REG	;set tmr0
	bcf	STATUS,RP0
	movlw	0x07		;turn off comparitors
	movwf	CMCON
	movlw	0xa0
	movwf	INTCON		;set interrupt 

start
	movlw	0x09
	movwf	ADCON0
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1

	bsf	ADCON0,1
	btfsc	ADCON0,1
	goto  $-1
        movf	ADRESH,0
	movwf	channel1

	movlw	0x0d
	movwf	ADCON0
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	goto	$+1
	bsf	ADCON0,1
	btfsc	ADCON0,1
	goto	$-1
	movf	ADRESH,0
	movwf	channel2
	goto	start

pwm
	incf	period,1
	btfss	STATUS,Z
	goto	$+2
	clrf	period
	movf	channel1,0
	addwf	period,0
	btfss	STATUS,C
	goto	$+3
	bsf	GPIO,0
	goto	$+2
	bcf	GPIO,0
	movf	channel2,0
	addwf	period,0
	btfss	STATUS,C
	goto	$+3
	bsf	GPIO,1
	return
	bcf	GPIO,1
	return
					
	end
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top