IRIN and PWM for dimming the LED

#1
Hello everybody,
I wonder if it is possible to dim the LED with irin and pwm (not pwmout). I can't figure out a code. Could anybody help me? Thank you for an advice.
 
#3
I would like to control RGB led with IR remote and 08M2. So that I could set brightness of each color independently and mix colors. The red led is at the pin c.1, the green led at the pin c.2 and the blue one at the pin c.4.
 

AllyCat

Senior Member
#4
Hi,

The 08M2 has only one PWM channel (on C.2) so I think the simple answer is "No". But perhaps hippy knows better. ;)

It might be possible to devise a tight program loop (<20ms) containing (only) High, Low and Pause commands to generate "software PWM" on the other two pins, with limited resolution (perhaps 16 levels of PWM). It would probably need multiple loop "templates" to handle specific conditions such as B and R leds with the same PWM value, or with very narrow or wide duty cycles, etc.. Generally you can't use Pulsout commands because they are "blocking", and I doubt if multi-tasking (multiple Start:s) would be fast enough.

IRIN is also "blocking" so it would be necessary to use an interrupt, or just possibly a very short timeout (a few ms) in the IRIN command to return to the tight loop. There would be no way to avoid the LEDs "flickering" (probably very badly) when an IR signal is received, particularly because IRIN reduces the clock speed back to 4 MHz.

I did successfully dim the backlight of an ASCII 16 x 2 LCD display having one of the I2C expander backpacks, using similar on/off commands via the I2C bus. But that was only one "PWM" channel and the program coding was not for the faint-hearted.

Cheers, Alan.
 

hippy

Technical Support
Staff member
#5
It is possible to bit-bang PWM three individual LED's on an 08M2 or any PICAXE.

If one were to look for the presence of IR and only then jump to a routine which executes IRIN with a timeout that shoulds work but could be prone to glitching the LED output.

A better way would be one PICAXE controlling the LED's and receiving commands and data using SERIN with another providing that data. There would need to be some handshaking but two 08M2's could feasibly do it.

HSERIN would be even easier but one would have to use charlieplexing for the LED's if using an 08M2 and that limits LED brightness.
 

AllyCat

Senior Member
#7
Hi,

Two 08M2s will give two direct hardware PWM outputs, then you could bit-bang (or even Pulsout) the third LED using one of them and IRIN on the other. But a single 14M2 has 3+ PWM outputs and could be smaller, simpler and cheaper, ;)

Cheers, Alan.

PS: Ah, pipped to the post. :)
 

AllyCat

Senior Member
#10
Hi,
...08M2.... set brightness of each color independently and mix colors. The red led is at the pin c.1, the green led at the pin c.2 and the blue one at the pin c.4.
So what have you decided to do? That sounded like a rather firm specification, which hasn't really been met here.

It's always useful to know what compromise an OP will accept: More (expensive) hardware (14M2 , or 2 x 08M2), more complex software (possible, but not described so far) or a lowered specification (fewer colours or "glitching" brightness during adjustment) ?

Cheers, Alan.
 
Last edited:
#11
I put together this code:

Code:
#rem
remote VIVANCO UR 82
setting for SONY code 107
Up = 24 (start)
Down = 25 (stop all)
Left = 27 (red brightness down)
Right = 26 (red brightness up)
CH+ = 16 (blue brightness up)
CH- = 17 (blue brightness down)
VOL+ = 18 (green brightness up)
VOL- = 19 (green brightness down)
RGB Red LED c.1
RGB Green LED c.2
RGB Blue LED c.4
RGB Common cathode Ground
#endrem

#no_data

main:
setfreq m8

goto red

red:
do

if b0 = 24 then
pwm c.1,b1,1
pwm c.2,b2,1
pwm c.4,b3,1
endif

irin [1],c.3,b10
select case b10
case 24    ;start
    b0 = 24

case 25    ;stop
low c.1
low c.2
low c.4
b0 = 0
b1 = 0
b2 = 0
b3 = 0

case 27
b10 = 0
dec b1
if b1 <1 then
b1 = 1
endif

case 26
b10 = 0
b1 = b1 + 1 MAX 254

case 16
b10 = 0
b3 = b3 + 1 MAX 254

case 17
b10 = 0
dec b3
if b3 <1 then
b3 = 1
endif

case 18
b10 = 0
b2 = b2 + 1 MAX 254

case 19
b10 = 0
dec b2
if b2 <1 then
b2 = 1
endif

endselect

goto red

loop while b0 = 24
I can mix all three colors independently with the remote. Of course it flickers while I push down the button on the remote. But it does not matter for me because I set the color I like and leave it. It is rather a demonstration of what can be achieved with a single 08M2 with all its pros and cons.


EDIT (see below): pwm replaced with pulsout, removed unnecessary pieces of the code, added code that prevents overflowing of variables when pushing the button 24 and immediately the button 27 - used also for the button 17 and 19.

Code:
#rem
remote VIVANCO UR 82
setting for SONY code 107
Up = 24
Down = 25
Left = 27
Right = 26
CH+ = 16
CH- = 17
VOL+ = 18
VOL- = 19
RGB Red LED c.1
RGB Green LED c.2
RGB Blue LED c.4
RGB Common cathode Ground
#endrem


#no_data
setfreq m8

do

if b0 = 24 then
pulsout c.1,w1
pulsout c.2,w2
pulsout c.4,w3
endif

irin [8],c.3,b10
select case b10    ;start RGB
case 24  
b0 = 24
   
case 25        ;stop RGB
pulsout c.1,0
pulsout c.2,0
pulsout c.4,0
b0 = 0
w1 = 0
w2 = 0
w3 = 0

case 27        ;red down  
b10 = 0
;this section if -- endif prevents erratic behaviour
;of the program - variable overflow when pressing
;the button 24 and immediately the button 27
;used also for the button 17 and 19
w1 = w1 - 10 MIN 10
if w1>1000 then
w1=0
endif

case 26        ;red up
b10 = 0
w1 = w1 + 10 MAX 800

case 16        ;blue up
b10 = 0
w3 = w3 + 10 MAX 800

case 17        ;blue down
b10 = 0
w3 = w3 - 10 MIN 10
if w3>1000 then
w3=0
endif

case 18        ;green up
b10 = 0
w2 = w2 + 10 MAX 800

case 19        ;green down
b10 = 0
w2 = w2 - 10 MIN 10
if w2>1000 then
w2=0
endif

endselect

loop
 
Last edited:

AllyCat

Senior Member
#12
Hi,

Thanks, that's interesting and "Elegantly Simple". The main "compromise" (apart from the brightness glitches during IR control) is that the LED brightness cannot be as high as the other methods (because only one LED can be on at a time). You might increase the brightness (particularly of pure / primary colours) by changing the PWM commands to PULSOUT c.1 , b1 etc., perhaps extending the timeout / pause when lower brightness levels are required.

An idea I had in mind for "full" brightness was a loop with about four PINS = bx (or @BPTRINC), or High / Low bx, commands separated by (say) 1 , 2 , 4 and 8 ms, so that each LED could be illuminated for any (integer) duration between 0 and 15 ms. The 8ms pause could accommodate the IRIN command (timeout) and the others some "fine" control for low brightness levels, using individual PWM or Pulsout commands. But much more code would be needed than your solution!

Cheers, Alan.
 

Bill.b

Senior Member
#13
This program will control the three colours of a rgb LED using a 14M2
Remote keys 2, 5 and 8 will increase the brightness while keys 3, 6 and 9 will decrease brightness of the each colour. 0 will turn of
all colours.
Maximum brightness can be set to suit the type of rgb led used.

Code:
'program to test RGB LEDs


#picaxe 14M2
Setfreq M8
symbol infracnt         = b3        'IR variable
symbol RedLevel        = b4
symbol GreenLevel        = b5
symbol BlueLevel        = b6
symbol MaxLevelRed        = b8     'Set maximum brightness level for Red Led
symbol MaxLevelGreen        = b9     'Set maximum brightness level for Green Led
symbol MaxLevelBlue        = b10     'Set maximum brightness level for Blue Led

pwmout b.2,150,0
pwmout b.4,150,0
pwmout c.0,150,0

MaxLevelRed= 100
MaxLevelGreen= 100
MaxLevelBlue = 100
do
    irin c.4,infracnt        ' get input from IR receiver
    select case infracnt
    case 1
        RedLevel = redLevel + 1
        pwmduty b.2,redLevel
        if RedLevel > MaxLevelRed then
            redlevel = 0
        endif
    case 2
        RedLevel = redLevel - 1
        pwmduty b.2,redLevel
        if RedLevel < 0 then
            redlevel = MaxLevelRed
        endif

    case 4
    
        GreenLevel = GreenLevel + 1
        pwmduty b.4,GreenLevel
        if GreenLevel > MaxLevelGreen then
            GreenLevel = 0
        endif
    case 5
        GreenLevel = GreenLevel - 1
        pwmduty b.4,GreenLevel
        if GreenLevel < 0 then
            GreenLevel = MaxLevelGreen
        endif
    case 7
    
        BlueLevel = BlueLevel + 1
        pwmduty c.0,BlueLevel
        if BlueLevel > MaxLevelBlue then
            BlueLevel = 0
    endif
    case 8
        BlueLevel = BlueLevel - 1
        pwmduty c.0,BlueLevel
        if BlueLevel < 0 then
            BlueLevel = MaxLevelBlue
        endif
    case 9
             redLevel = 0
             GreenLevel = 0
              BlueLevel = 0
             pwmduty b.4,redLevel
           pwmduty b.2, GreenLevel
           pwmduty c.0,BlueLevel
    end select

loop
Bill
 
Last edited:

hippy

Technical Support
Staff member
#15
redLevel = redLevel + 1 // MaxLevelRed

would be the quickest way to achieve wrap round. Note that will go from 0 to (MaxlevelRed-1) so MaxLevelRed would need to be 101 to get a 0-100 value in redLevel. It's probably best to use a name other than 'Max' for that 101 constant value.

redLevel = redLevel - 1 Max MaxLevelRed

is equivalent for going down but here MaxLevelRed does need to be 100, so two constants perhaps -

Symbol MaxLevelRed = 100
Symbol MaxLimitRed = MaxLevelRed + 1
redLevel = redLevel + 1 // MaxLimitRed
redLevel = redLevel - 1 Max MaxLevelRed
 
Last edited:
Top