PWM - Frequency and Duty

dandav

New Member
Hi All,
I am trying to change PWM DUTY via a varying voltage on an input
Then CHANGE FREQUENCY from 1000Hz when another input is HIGH --100Hz

I do NOT want the PWM DUTY to change when switched to the alternate frequency

I have applied a formula to the read ADC value but does not appear to work
The output is ramdom Duty but the frequency does change


Does anyone have some constructive thoughts

Thank you
Daniel
Formula.JPG


Code:
' PWM_1.Bas
'Uses 8M2
'


 
PWMOUT C.2, 249, 0 


TOP:

   GoSub Flash			' flash the LED on Out0

	READADC10 C.4, W0       'read the 0-5vdc voltage and put the value into W0 (0 - 255)
	
   	If W0 <= 2 then let W0 = 0 endif
   	
      	
   if pinc.3 = 0 then
   
   	W0 = W0 * 1024/1049     '// Do the math to map the value for 0 - 100 percent duty
   	pwmout pwmdiv4, C.2, 249, W0 ' 1000Hz
	
   else
   	W0 = W0 * 1024/1678     '// Do the math to map the value for 0 - 100 percent duty
	pwmout pwmdiv64, C.2, 155, W0 ' 100Hz
		
	
   endif		

  	
   GoTo TOP				' continually loop

	Flash:			' flash LED on Out0
			
   High C.1
     Pause 5
   Low C.1
     Pause 45
  Return
 

Attachments

nick12ab

Senior Member
Welcome to the PICAXE Forum.

What do you mean by 'random'?

Every single time the loop restarts, the pwmout command is executed regardless of whether a frequency change is required which causes the PWM timer to be reset, which may cause glitches in the output. You should implement a state machine to choose between pwmout and pwmduty as appropriate.

Also a comment in your code erroneously states that the reading from the readadc10 command is in the range 0-255 when it will actually be a 10-bit reading (0-1023), however the rest of the code seems to be correctly written for 10 bits.

Does the physical circuit match the schematic?
 

AllyCat

Senior Member
Hi Daniel,

W0 = W0 * 1024/1049 '// Do the math to map the value for 0 - 100 percent duty
Welcome to the forum. Because PICaxe calculates from left to right, the intermediate result of w0 * 1024 is probably overflowing a 16-bit value (max 65,536) and giving incorrect results.

One solution is to calculate instead w0 = w0 ** 54058 and w0 = w0 ** 39993 (hint: the ** operator multiplies and then effectively divides by 65,536).

Cheers, Alan.
 

dandav

New Member
Thank you for pointing out the overflowing
That was the problem

I accepted a 1% error and different formula *32/33 and *32/52

Now works and perfectly acceptable
 
Top