PWM & 08M2

Bill z

Member
Brand new guy here.

Is there a way to gradually increase and decrease LED brightness using a 08M2?

I want to gradually increase a LEDs brightness from zero to its brightest over a 5 second period.

Documentation about PWM says ‘Applies To: All (except 08, 18, 18A, 20M, 28, 28A)’. I'm thinking that means 08M2, but there has to be a way.

Please help.
 

AllyCat

Senior Member
Hi,

Yes, the 08M2 has one PWM output, on pin C.2 . Of course to increase the brightness of a LED as you describe, you will probably need to start with a PWM value of some hundreds (corresponding to the low-current forward voltage drop) and then increment the duty cycle approximately every 10 ms.

Cheers, Alan.
 

erco

Senior Member
PWM is the simplest for sure. Per Alan, 08M2 only has that available on one pin. You can bit-bang PWM (hard code hi/low pulses) on any output pin though, including C.0 (serial out). Here's my video of an 08M2 doing four quick bright/dim cycles. My code is shown on the Youtube page.

 

Bill z

Member
Thanks,

I mistakenly thought 08 was shortened for 08M2.

Please help a new guy again.

PWMOUT has both 'Period' & 'Duty Cycle' . From the definition, I can't tell which one to increase / decrease to brighten or dim the LED. If it is duty cycle, then what would max and minimum range be & what should a good setting for Period be? Or is it the other way around?
 

lbenson

Senior Member
PWMOUT has both 'Period' & 'Duty Cycle' . From the definition, I can't tell which one to increase / decrease to brighten or dim the LED. If it is duty cycle, then what would max and minimum range be & what should a good setting for Period be? Or is it the other way around?
I have found that 1kHz is fine for dimming LEDs, and then you can use PWMDUTY to adjust the brightness.
Here's a little program. I actually used this with a MOSFET to test a 12V LED module, but it would be fine with a regular LED attached to the pin.
Code:
' 08_pwm12v
#picaxe 08M2
'#picaxe 14M2

symbol pLED  = C.2 ' 08M2
'symbol pLED  = B.4  ' 14M2
symbol wDutyCycle=s_w1
symbol wIncrement=s_w2
symbol loopCnt=b27
symbol INCREMENT=100

pwmout pwmdiv4, pLED, 249, 0
pause 3000
pwmout pwmdiv4, pLED, 249, 999
pause 3000
'pwmout pwmdiv4, pLED, 249, 900
'do
'loop
wDutyCycle=$FFFF
wIncrement=INCREMENT

main:
  do
    for loopCnt=1 to 10
      sertxd(#wDutyCycle," ")
      wDutyCycle=wDutyCycle+wIncrement
      pwmduty pLED,wDutyCycle
      pause 2000
    next loopCnt
    wIncrement=0-wIncrement ' toggle between 100 & -100
    sertxd(cr,lf)
  loop
 

Bill z

Member
Thanks so much for the sample code.

Please understand that I'm NOT complaining but attempting to learn. Making some changes to your code to fit my needs, it is difficult to see using the PICAXE Editor 6.1.0.0 because C.2 doesn't turn green when running when C.3 is yellow.

But when running on my 08M2 chip, the LED does brighten and dim except when it is suppose to be maximum dim, then there is a bright flash. The flash is not wanted, just smooth brightening to max then smooth dim to off and back again while C.3 is high. I suppose, I'm assuming something that isn't true.

What am I misunderstanding? what did I miss?

Here is your code with my changes

' 08_pwm12v
#picaxe 08M2

symbol pLED = C.2 ' 08M2
symbol wDutyCycle=s_w1
symbol wIncrement=s_w2
symbol loopCnt=b27
symbol INCREMENT=50

pwmout pwmdiv4, pLED, 249, 0
pause 100
'pwmout pwmdiv4, pLED, 249, 999
'pause 3000

wDutyCycle=$FFFF
wIncrement=INCREMENT

main:

do
if pinC.3=0 then
pwmout pwmdiv4, pLED, 249, 0
endif
do while pinC.3=1
for loopCnt=1 to 10
'sertxd(#wDutyCycle," ")
wDutyCycle=wDutyCycle+wIncrement
if pinC.3=1 then
pwmduty pLED,wDutyCycle
pause 100
endif
next loopCnt
wIncrement=0-wIncrement ' toggle between 100 & -100
' sertxd(cr,lf)
loop
loop
 

lbenson

Senior Member
Remove the comment marker from 'sertxd(#wDutyCycle," ") (and maybe from the subsequent ' sertxd(cr,lf) )

This will allow you to see the full loop output. You might want something like PAUSE 5000 between the two LOOPs so you have a little time to see what is being reported before the next loop starts.

The flash may be because something funky is happening at the end of the loop because of the increment.

(When you post code, it's better to put it within the forum tags, "[ code]" and "[ /code" (removing the spaces I've put in so that the forum doesn't act on those tags in this post)).
 

AllyCat

Senior Member
Hi,
From the definition, I can't tell which one to increase / decrease to brighten or dim the LED. If it is duty cycle, then what would max and minimum range be & what should a good setting for Period be?
It is the Duty Cycle which (primarily) controls the brightness, but you haven't indicated how the LED is wired, so we can't say whether you need to increase or decrease the Duty Cycle. If the "other" side of the LED is wired to Ground (which is generally easier to understand) then you need to Increase the Duty Cycle (High), if wired to the Supply (which may give higher brightness capability) then you need to Decrease the Duty Cycle, and if using a Driver (inverter) it will probably be different again. ;)

For maximum control range you need to set the Period (byte) to maximum (i.e. 255) which will give the lowest frequency. Normally, a low frequency is better (more efficient), but 60 Hz might be too low (flickering), so using PWMDIV16 (i.e. not PWMDIV64) may be preferable. Note that the period value is always 1/4 of the (maximum) Duty Cycle, so if you are storing the Duty Cycle in only a single byte variable (0 - 255) and not a word (0 - 1023), then you should set a period of 63.

We also need to know the forward voltage drop of the LED (which often depends on its colour) and the supply rail voltage, to predict what range of Duty Cycles are required. But generally I'd expect about 40% --> 100% or 60% --> 0% to increase the brightness (from "dim" up to maximum), depending on how it's wired.

Cheers, Alan.

PS: I haven't looked in detail at your program, since (IMHO) we really need to know what hardware configuration you're using first.
 

lbenson

Senior Member
Ok, it's inelegant, but this should better suit your needs (except for timing and turning on with pinC.3)
Code:
' 08_pwm12v
#picaxe 08M2
'#picaxe 14M2

symbol pLED  = C.2 ' 08M2
'symbol pLED  = B.4  ' 14M2
symbol wDutyCycle=s_w1
symbol wIncrement=s_w2
symbol loopCnt=b27
symbol INCREMENT=100

pwmout pwmdiv4, pLED, 249, 0
pause 3000
pwmout pwmdiv4, pLED, 249, 999
pause 3000
wDutyCycle=0-INCREMENT
wIncrement=INCREMENT

main:
  do
    for loopCnt=1 to 11
      wDutyCycle=wDutyCycle+wIncrement
      if wDutyCycle < 1023 then
        sertxd(#wDutyCycle," ")
        pwmduty pLED,wDutyCycle
        pause 2000
      endif
    next loopCnt
    wIncrement=0-wIncrement ' toggle between 100 & -100
    sertxd(cr,lf)
  loop
It doesn't go to full brightness, since the max dutycycle is 1000 instead of 1023.

(And what Allycat said.)

(Run in simulator, not checked on chip.)
 

Bill z

Member
Yes, this works. Thanks.

Seems the 08M2 is slow enough that I just commented out the 'pause' command and incremented by 10 with 102 loopCnts.

I'm curious about why the 'pwmout pwmdiv4, pLED, 249, 0' with the 'pause 3000' at the top of the program, then right after it the 'pwmout pwmdiv4, pLED, 249, 999' and another 'pause 3000'. Let me rephrase; why the pause? and why the second pwmout?
 

AllyCat

Senior Member
Hi,
Seems the 08M2 is slow enough that I just commented out the 'pause' command and incremented by 10 with 102 loopCnts.
Yes, the PWMDUTY (not the PWMOUT) command is exceptionally "slow" (almost 10 ms IIRC). It's a "pseudo command" (or system Macro) and if you check the program size (using the syntax check), you will find that commenting it out removes around 35 bytes from the program size! PWMDUTY (in place of PWMOUT) is really only needed to avoid "glitches", so generally it's not essential for applications such as LED-dimming.

Basically, you can adjust the INCREMENT value to give the speed of brightness-change (and the smoothness of the brightness transitions) that you want (assuming no other "processing" is required in the program).

You need a PWMOUT command before a PWMDUTY, but I guess the other PWMOUT and PAUSEs were just for demo / testing. Sometimes microcontrollers (even PICaxes) do things too fast to see what's happening. :)

Cheers, Alan.
 

lbenson

Senior Member
I'm curious about why the 'pwmout pwmdiv4, pLED, 249, 0' with the 'pause 3000' at the top of the program, then right after it the 'pwmout pwmdiv4, pLED, 249, 999' and another 'pause 3000'. Let me rephrase; why the pause? and why the second pwmout?
Just testing off and on. The program wasn't intended for use, just for testing turning on and off and dimming and fading a 12V LED.
 

Bill z

Member
Just testing off and on. The program wasn't intended for use, just for testing turning on and off and dimming and fading a 12V LED.
OK. Thanks. I thought that, maybe, some routine had to install and it required 3000.
 
Last edited:
Top