Weird little problem.

Shafto

Senior Member
Having a very strange issue. I've narrowed it down the the PWMout command, but I can't figure out what's going on.

With just a basic download circuit and an 08M2, using a PWMout C.2, 221, 500 command, the PWM output will work properly putting out 4500hz up to around a supply of 3.3V, above that it goes completely wonky and puts out around 11hz. I also hooked up an LED to visualize it.

If I bring the duty cycle up past ~800 or so then C.2 just goes completely high, with supply above 3.3V.

I've tried with 3 different chips and exact same thing with each. I also tried with battery power supply to rule out mine malfunctioning.

It's late and I must be doing something terrible stupid, but for the life of me I can't figure out this simple little issue. Anybody else have this problem before?
 

Technical

Technical Support
Staff member
Having a very strange issue. I've narrowed it down the the PWMout command, but I can't figure out what's going on.

With just a basic download circuit and an 08M2, using a PWMout C.2, 221, 500 command, the PWM output will work properly putting out 4500hz up to around a supply of 3.3V, above that it goes completely wonky and puts out around 11hz. I also hooked up an LED to visualize it.

If I bring the duty cycle up past ~800 or so then C.2 just goes completely high, with supply above 3.3V.
www.picaxe.com/commands/pwmout

2) Duty cycle is a 10 bit value (0 to 1023). The maximum duty cycle value must not be set greater than 4x the period, as the mark 'on time' would then be longer than the total PWM period (see equations above)! Setting above this value will cause erratic behaviour.
 

Goeytex

Senior Member
As Technical indicated, you are using a duty value that is out of range for a given a frequency value of "221". The highest legitimate duty value for a freq value if 221 would be 889 (according to the Pwmout Wizzard).

So the question is, what are you attempting to accomplish ?

If you are using ADC10 to control the duty, then the ADC value must be mathematically scaled or "mapped" for the duty cycle of the PWM so that 0 - 1023 maps to 0 to max duty. So to scale the ADC10 for 0 to 889 ....
Code:
pwmout c.2, 221, 0  '// PWM on @ 0%

do
     readADC10, pin, w0
     w0 = w0 * 60 / 69   '// do the math.... 
     pwmduty,c.2,w0
     pause 100
loop
Or.... you can use a frequency value so that 100 percent duty = 1023. (1023 / 4 = 255) So that would be a frequency of 3010 Hz. Pwmout c.2,255,512 would give 50% duty and pwmout c.2,255,1023 would give 100 percent duty cycle.
 

Shafto

Senior Member
Thanks, I think the issue was a my breadboard. I made an identical circuit on another breadboard and it's working ok now. Using a duty higher than 4X the period just causes it to go 100% duty, but I'm glad for being made aware of that, I'll do it properly anyway.

Unfortunately even with everything "working" there's a nasty amount of flicker if you just make the output what you read on the ADC. I've tried a bunch of different ways to deal with it and this is the only code I've come up with so far that works. The different adjustment points are to make the brightness change look even to the human eye, like using a log pot rather than a linear one.

Code:
init: 

Symbol currentADC = w0
Symbol Out = w2
Symbol posihyst = w3
symbol negahyst = w4
ReadADC10 c.4, Out
pwmout c.2, 221, Out				;start PWM

main:

posihyst = out + 20				;hysteresis to ignore noisy ADC
negahyst = out - 20

ReadADC10 C.4, CurrentADC


If	CurrentADC > posihyst Then
	If Out < 200 Then
    Out= Out + 4
    ElseIf Out < 400 Then
    Out= Out + 8
    ElseIf Out < 800 Then
    Out= Out +14
    Else Out= Out + 22 MAX 884
    EndIf

elseif CurrentADC < negahyst Then
	If Out > 800 Then
    Out= Out - 22
    ElseIf Out > 400 Then
    Out= Out - 14
    ElseIf Out > 200 Then
    Out= Out - 8
    Else Out= Out - 4 MIN 20
    EndIf

else
pause 200
endif

PWMDuty C.2, Out 

sertxd (#CurrentADC, #OUT, 13, 10)

goto main
I don't get any flicker this way but the brightness level "chases" the set point. It's kind of a neat effect but is there a way to make it work like bellow but without any flicker?

Code:
init: 

Symbol Out = w0
ReadADC10 c.4, Out
pwmout c.2, 221, Out	 Max 884			;start PWM

main:

ReadADC10, Out

PWMduty C.2, Out Max 884

pause 100

goto main
Thanks!
 

Shafto

Senior Member
I was still getting some flicker with the code posted on top! I'm using battery power with a 100uf and a 0.1uf cap and even with the hysteresis on the ADC set to 50 it would still flicker a bit, I needed to go all the way up to 100 to get it to stop, at which point it's useless for adjustment. That's some serious noise on the ADC. Seems like something else is wrong to create that but I dunno what.

Anyway I played around some more and came up with some code that works pretty well. The setpoint chasing is reduced to being almost unnoticeable as the output is adjusted. A little bit is actually desirable and looks good. It can be virtually eliminated by turning up the clock speed now, to the point you can't visually notice it.

There's also, finally, zero flicker. I can't believe what it took to adjust the brightness of an LED with a pot without flicker! I had to use hysteresis and also count a few ADC inputs over the hysteresis point before the code finally starts adjusting the brightness. If there are other, possibly more elegant approaches to this I'd be interested to learn about them, please share.

P.s. the code is rough-written.

Code:
init: 
setfreq m4
Symbol currentADC = w0
Symbol Out = w2
Symbol posihyst = w3
symbol negahyst = w4
symbol brightcounter = b27
symbol dimcounter = b26
brightcounter = 1
dimcounter = 1
ReadADC10 c.4, Out
pwmout c.2, 221, Out				;start PWM

main:

posihyst = out + 20				;hysteresis to ignore noisy ADC
negahyst = out - 20

ReadADC10 C.4, CurrentADC


If	CurrentADC > posihyst Then
inc brightcounter
elseif CurrentADC < negahyst Then
inc dimcounter
else pause 100
brightcounter = 1
dimcounter = 1
goto main
end if

If brightcounter = 10 then
brightcounter = 1
goto brighter
elseif dimcounter = 10 Then
dimcounter = 1
goto dimmer
else pause 10
goto main
end if

brighter:
	
If Out < 200 Then
Out= Out + 4
ElseIf Out < 400 Then
Out= Out + 8
ElseIf Out < 800 Then
Out= Out +14
Else Out= Out + 22 MAX 884
EndIf

pwmduty c.2, Out

ReadADC10 c.4, currentADC

If CurrentADC > Out then
goto brighter
else
goto main
endif


dimmer:
 
If Out > 800 Then
Out= Out - 22
ElseIf Out > 400 Then
Out= Out - 14
ElseIf Out > 200 Then
Out= Out - 8
Else Out= Out - 4 MIN 5
EndIf

pwmduty c.2, Out

ReadADC10 c.4, currentADC

If CurrentADC < Out then
goto dimmer
else
goto main
endif
 

Goeytex

Senior Member
An led will not "flicker" when the PWM frequency is 4500 Hz, unless something is causing the PWM to shut off intermittently.
Is there something else attached that you are not telling us about ? ]

Flicker is when the ADC is steady and there is visible pulsing of the LED. If this is caused by an unstable ADC, then you need to troubleshoot the physical ADC circuit and related components. ADC10 should be stable to within 2 units, which should not cause any noticeable flicker. If you are not touching the pot there should be no flicker at all.

Where is the Pot located? How far is it from the Picaxe? Is the pot over 10K? Are the Pot & Picaxe grounds tied together at the same point?

Are there wires snaking about all over the board making it look like a bowl of spaghetti?. If so then make them neat and as short as possible.

How is the LED being driven?. Directly from a Picaxe Pin, with a transistor ? What size resistor are you using ?

The second bit of code you posted in post #5 will not pass syntax check, so you could not have actually used it, but with correction it will work fine.

Here is something similar to try, but DON'T CHANGE IT until you see the results. There should be zero "flicker". If there is any flicker then troubleshoot the ADC wiring and post a schematic and a clear photo of you breadboard so that we can see whats going on.

Code:
#picaxe 08M2
#no_data

symbol duty = w0
pwmout c.2, 221, duty  		

main:

   do     
         ReadADC10 C.4,duty 
         duty = duty * 60 / 69 max 1023
         pwmduty C.2, duty 
                  
        '// Any pause here over a few ms will cause adjustment to be jumpy instead of smooth  
  loop
 
Last edited:

Shafto

Senior Member
There's nothing else attached, just the pot and the LED. The pot is 10K. Not a bunch of snaking about or anything like that. Doesn't matter if I drive a transistor for a larger LED or directly drive a smaller one from the output pin, exact same flicker on each with the code you posted, which is the same thing I was referring to in my second bit of code with the syntax error. The flicker is much less pronounced on the smaller LED though, and might go unnoticed. It changes in severity as the brightness is adjusted. It doesn't matter what power supply I use, I get the same flicker. I've done many other little circuits on breadboards checking voltage against the FVR, or reading temp from a thermistor/resistor divider, never had a problem with a bouncy ADC before, I don't know why there'd be any excess noise all of a sudden.

Putting different caps across V+ and GND changes the flickering but doesn't eliminate it. The last bit of code I wrote though will completely eliminate any flickering and adjust nice and smooth.

If I debug the ADC I can see it dropping by 10-15 every once in a while, I assume this is where the flicker is coming from, maybe something to do with reading the ADC right as a PWM pulse is initiated in the background?
 
Last edited:

Goeytex

Senior Member
@shafto

If I debug the ADC I can see it dropping by 10-15 every once in a while, I assume this is where the flicker is coming from, maybe something to do with reading the ADC right as a PWM pulse is initiated in the background?
I would not assume that at all. I prefer to test & take measurements rather than guessing. But your guess may could be correct.

My guess is that the grounding or supply wiring is not good. Breadboards can have bad contacts that cause problems. Move the Picaxe & pot to a different part of the breadboard if necessary.

But first ...... run a jumper wire directly from the Pot ground to the Picaxe ground pin. And then another jumper wire directly from the Pot positive to the Picaxe +V pin ... and then see what happens. Also remove the AXE027 if connected and remove any lines of code that use debug or serial.

There is no reason that I can think of other than poor grounding or poor supply connections that would cause this as I slapped the circuit together on a breadboard here and have no flicker at all. None.

Since you did not say what size LED or what size current limit resistor you are using, make sure that the resistor in series with the LED is 330 ohms or greater. You do have a series resistor ?

Is it possible that the Picaxe is resetting? As a test only , you can add < disablebod > and <Disconnect> commands at the beginning of the code in the rare chance that it will tell you something.

Also eliminate the possibility of external noise by turning off any devices plugged in to the same outlet/ strip as the power supply.

@inglewoodpete

You are correct, it should be "max 887" or left off completely since it doesn't really do anything.
 
Top