PWM Frequency 'on the fly' on 18m2

AndyGadget

Senior Member
For an audio project on an 18m2, I'm trying to change the PWM frequency without issuing a new PWMOUT command. This is to avoid a reset of the PWM timers which causes the audio output to be distorted.

This was easy on the 08m - Poking the PR2 register for the frequency and CCPR1L and CCP1CON registers for the duty cycle worked a treat.

Code:
#picaxe 08m
'#no_data
'#no_table
setfreq m4

data (15,21,29,41,58,81)

symbol piezo 	= 2
symbol LED		= 0
symbol sw1 		= pin3

symbol rnd	= w6
symbol rndh	= b13
symbol rndl	= b12
		
symbol W	= w5
symbol Wh	= b11
symbol Wl	= b10

symbol Wx	 	= w4

symbol F	 	= b0
symbol R	 	= b1
symbol t1	 	= b2
symbol t2   	= b3
symbol adc		= b4
symbol adcx		= b5

symbol hi = 1
symbol lo = 0
symbol true = 255
symbol false = 0
symbol arpst = $80

f = 128
w = 255

pwmout pwmdiv4, piezo,f,w

do
		readadc 4,adc
		adc = adc / 40
		
		if adc <> adcx  and adc <> 6 then	
			high led	
			read adc,f				
			adcx = adc
			w = f * 2
			pwmout pwmdiv16, piezo,f,w
			pause 100
			low led
		end if
		
		if adc = 6 then 
		adcx = adc
		end if

		f = f * 32 / 30
		poke $92,f

		w = w * 31 / 32
		wx = w / 4
		poke $13,wx

		wx = w AND %00000011 * 16 OR %00001100
		poke $15,wx

		pause 10
loop
On to the 18M2 - The PIC16F1826/27 datasheet states that Timers 2, 4 and 6 are associated with the PWM function. Changing the PR2 (period) register after a PWMOUT command (using POKESFR $1B) has no effect on the output frequency of either pin B.3 or B.6 so I'm trying to do the same with the PR4 and PR6 registers.

PR2 is easy as it's in register bank 0 and accessible with the POKESFR command, but PR4 and PR6 are registers $16 and $1D in bank 8 which is not.

So the question is, is there a way or writing to these registers other than using the POKESFR command, and if there is, is changing these likely to give the result I'm after?
 
Last edited:

Technical

Technical Support
Staff member
All you need is the 'pwmduty' command!
Also try the pwmout command anyway, you may well find it works better than it did on the 08M as the command has been re-engineered.
 
Last edited:

AndyGadget

Senior Member
PWMDUTY only changes the duty cycle - I'm doing that quite happily.

It's the frequency I'm having trouble with. I've tried using the PWMOUT command but as I found on the 08m before I poked the registers directly, it resets the whole PWM function and the output is distorted if you try to modulate it at any rate.

Code:
#picaxe 18m2
#no_data

symbol pz1		= b.3
symbol duty 	= w12
symbol freq		= b5

do

	for freq = 200 to 100 step -1
	
		duty = freq * 2
		pwmout pwmdiv16, pz1,freq,duty
		pause 5

	next freq
	
	for freq = 100 to 200
	
		duty = freq * 2
		pwmout pwmdiv16, pz1,freq,duty
		pause 5

	next freq
	
loop
I know I'm using PWM in a way it's not intended for, but what I'm doing works fine on an 08m and I wanted to extend the same idea to the 2 PWM outputs of the 18m2.

Using PWMOUT on the 18m2 does sound a lot better than the equivalent on the 08m, but still with an attendant 'popping' to the sound. Using the POKE method on the 08m produces a perfectly clean sound. The application for this is a simple keyboard synthesizer - Not a million miles away from a Stylophone.
 
Last edited:

Technical

Technical Support
Staff member
PR4 and PR6 are not accessible on the 18M2, so it is not possible to poke them directly.
 
Top