Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

software PWM

MrDEB

Well-Known Member
WANT TO CONTROL 35 l:edS USING pwm (WANT TO DIM THEN BRIGHTEN DIFFERENT COMBOS)
Basically PWM is turn on then turn off crating a dimming effect.
here is where I started using Swordfish. It kinda works but needs LOTS of work. Using only one led to experiment with.
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2022 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 1/18/2022                                                      *
*  Version : 1.0                                                            *
*  Notes   :  software PWM                                                              *
*          :                                                                *
*****************************************************************************
}
Device = 18F43K22
Clock = 4

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

Include "convert.bas"
Dim led1 As PORTC.0
Dim led2 As PORTC.1
Dim LED3 As PORTC.2
Dim LED4 As PORTC.3
Dim cOUNTER As Word
Dim TIME1 As Byte     //ON TIME
Dim TIME2 As Byte     //OFF TIME
TRISC=0  //ALL OUTPUTS ON PORTC

led1=0
led2=0
LED3=0
LED4=0
TIME1=10
TIME2 = 100
cOUNTER = 255
While TRUE
    
    Toggle(led1)
    DelayUS(TIME1)
    Toggle (led1)
    DelayUS(TIME2 - cOUNTER)
    cOUNTER = (cOUNTER - 100)
    If cOUNTER = 0 Then
    cOUNTER = 255
    End If
    Wend
 

rjenkinsgb

Well-Known Member
Most Helpful Member
Use a single counter that is incremented every pass through the main program and is reset to zero when it passes 255.

Within the program loop, compare each LED PWM set value to the counter and turn the output on if the LED value is higher, or off if the LED value is lower than the counter.

Do not use any delays or wait for anything within the loop, other than possibly a short delay at the very start of the loop, if it is too fast.

Put counter increment and check, and all the LED PWM fade increments or decrements at the end of the loop, and only do those when the counter reaches 256 and you reset it to zero.

ps. If it's too slow and there is flicker, use a lower maximum count, eg. 0-100 rather than 0-255.
 

MrDEB

Well-Known Member
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2022 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 1/18/2022                                                      *
*  Version : 1.0                                                            *
*  Notes   :  software PWM                                                              *
*          :                                                                *
*****************************************************************************
}
Device = 18F43K22
Clock = 8

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

Include "convert.bas"
Dim led1 As PORTC.0
Dim led2 As PORTC.1
Dim LED3 As PORTC.2
Dim LED4 As PORTC.3
Dim cOUNTER As Word
Dim TIME1 As Byte     //ON TIME
Dim TIME2 As Byte     //OFF TIME
TRISC=0  //ALL OUTPUTS ON PORTC

led1=0
led2=0
LED3=0
LED4=0
TIME1=10
TIME2 = 10
cOUNTER = 0
While TRUE
   if (time1 > counter)
   then
   led1=1
   endif
   if (time1 < counter)
   then
   led1=0
   endif
   counter = (counter + 50)
   if counter = 100 then
   counter=0
   endif
  
  {
    
    Toggle(led1)
    DelayMS(TIME1)
    Toggle (led1)
    DelayUS(cOUNTER - TIME2)
    cOUNTER = (cOUNTER - 100)
    If cOUNTER = 0 Then
    cOUNTER = 255
    End If
    }
    Wend
I think I have the math wrong but ir is kinda working. Just need to configure the math correctly
 

rjenkinsgb

Well-Known Member
Most Helpful Member
Hmmm...

Code:
Device = 18F43K22
Clock = 8

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

Include "convert.bas"

led1 = 0
led2 = 0
led3 = 0
led4 = 0

Time1 = 10
Time2 = 25
Time3 = 50
Time4 = 75

cOUNTER = 0

While TRUE

   // LED One control
   if (Time1 > counter) then
   led1=1
   else
   led1=0
   endif

   // LED Two control
   if (Time2 > counter) then
   led2=1
   else
   led2=0
   endif
 
   // LED Three control
   if (Time3 > counter) then
   led3=1
   else
   led3=0
   endif

 // Other LEDs here.
 

// Increment PWM cycle counter  every loop
   cOUNTER = (cOUNTER + 1)

// Check for overflow
   If cOUNTER > 255 Then
   cOUNTER = 0

// Add the fades etc. here.

   End If
 
 Wend

// note NO DELAY INSTRUCTIONS ANYWHERE!!!!!!

I use C not basic so I cannot test it.

Edit; variables tidied.
 
Last edited:

MrDEB

Well-Known Member
been experimenting with Rjenkinsgb suggestion and it dawned on me that it has the possibility of too much current draw unless I multiplex the leds.
This code os going to be used controlling 35 leds. Experimenting with just 24 but only have portc enabled.
Plan is to use 330 ohm resistors instead of the 150 ohm but still keep an eye on the current draw. Max is 25ma.
need to check data sheet if thats per port or the current for the entire PIC?
 

sagor1

Active Member
Current per pin is 25mA, sink or source, but you have to watch for total current on all ports. Maximum sinking current is 200mA for entire device (all ports) up to +85C. Maximum source current is 185mA, up to +85C.
Once it gets over +85C, ratings drop by about half.
Rule of thumb is to not use all pins on one port for all source/sink. Even then, with multiple ports, spread the load out and keep the total well below that 200mA/185mA numbers.
All this info is in the datasheet under Electrical Characteristics.
 

tumbleweed

Active Member
330 ohms is going to put you somewhere in the 10mA/LED ballpark, depending on the LED, VDD, etc.

Since you're turning the LEDs on with a high output you're sourcing current, so the 185mA limit sagor1 points out would apply.

That's roughly 18 LEDs on at a time.
 

rjenkinsgb

Well-Known Member
Most Helpful Member
If you need higher current, I'd suggest adding driver transistors or FETs.

eg. The DDTA143TUA-7-F, a "digital transistor" (one with base resistors included) is five cents at JLC and they have plenty in stock.

The input can connect direct to an MCU pin and it can switch up to 100mA, though you will have to have the LED commons to positive rather than ground, as the transistor would switch to ground.
 

Beau Schwabe

Active Member
Stagger the LED's into groups when they turn on .... 35 LED's fits into 5 zones of 7 LEDs or 7 zones of 5 LEDs... Use 2mA LEDs.

At the beginning of each "zone" turn ALL 7 (or 5) LED's ON at the same time and as a counter increments, if it exceeds the value of the corresponding PWM for that LED turn the LED off. Do this for all LED's in the zone and then repeat. It's ok to have zones overlap for turning the LED's OFF, you just want to minimize the surge current by not having ALL 35 of the LED's come ON at the same time.
 

Attachments

  • Software PWM.pdf
    10.9 KB · Views: 39

MrDEB

Well-Known Member
I started rethinking this and I am using blue and white led (forward voltage is 3-3,7 per led)
So will round it off at 3.5volts. using 5volt for Vcc so that equates to about 10ma
10ma x 35 = 3.5 ma total if my math is correct?
don't know where Tumbleweed got 10ma using 330ohm resistor?
 

tumbleweed

Active Member
I didn't realize you were using blue and white leds, so I just assumed a forward voltage drop of 1.8-2V.

Most blue leds I've used will burn your eyes out with more than 1-2mA.
 

tumbleweed

Active Member
So if you increase it to 330ohms that'll still give you about 4mA/LED, and 4mA x 35 leds = 140mA total with all LEDs on. That's under the chip max of 185mA so you should be fine.
 

MrDEB

Well-Known Member
yes I am increasing the resistor value. Thinking of going 680-715?
here is a decent dimming effect that I have been working with.
Maybe add more fade sub routes?
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2022 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 1/19/2022                                                      *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
Device = 18F2221
Clock = 8

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"
Include "convert.bas"

//PORTS
DIM A0 AS PORTA.0
DIM A1 AS PORTA.1
DIM A2 AS PORTA.2
DIM A3 AS PORTA.3
DIM A4 AS PORTA.4
DIM A5 AS PORTA.5
DIM A6 AS PORTA.6
DIM A7 AS PORTA.7

Dim B0 As PORTB.0
Dim B1 As PORTB.1
Dim B2 As PORTB.2
Dim B3 As PORTB.3
Dim B4 As PORTB.4
Dim B5 As PORTB.5
Dim B6 As PORTB.6
Dim B7 As PORTB.7


Dim C0 As PORTC.0
Dim C1 As PORTC.1
Dim C2 As PORTC.2
Dim C3 As PORTC.3
Dim C4 As PORTC.4
Dim C5 As PORTC.5
Dim C6 As PORTC.6
Dim C7 As PORTC.7


Dim cOUNTER As Word
Dim Group1 As longword     //port A
Dim Group2 As word     //port B
Dim Group3 As word     //port C
Dim Time4 As Byte
Dim x As longWord
dim Index as byte


sub Fade_1()
   group1=1
   group2=1
   group3=2
   end sub
  
sub Fade_2()
   group1=1
   group2=1
   group3=1
   end sub
  
sub Fade_3()
  group1=1
   group2=1
   group3=1
   end sub
  
sub Fade_4()
  group1=1
   group2=1
   group3=60000
   end sub

//turn all ports as outputs
trisa=0                 
trisb=0
TRISC=0 

A0 = 0
A1 = 0
A2 = 0
A3 = 0
A4 = 0
A5 = 0
A6 = 0
A7 = 0

B0 = 0
B1 = 0
B2 = 0
B3 = 0
B4 = 0
B5 = 0
B6 = 0
B7 = 0

C0 = 0
C1 = 0
C2 = 0
C3 = 0
C4 = 0
C5 = 0
C6 = 0
C7 = 0
index=0
GROUP1 = 1         //dim led
GROUP2 = 75
GROUP3 = 75        //bright led
'Group4 = 1        //if using 18f43k22 use this group

cOUNTER =0

While TRUE
  for x = 0 to 1000
   // LED One control
   If (GROUP1 > cOUNTER) Then      //PORT C
   C0=1
   Else
   C0=0
  EndIf
 
   // LED Two control
   If (GROUP2 > cOUNTER) Then
   C1=1
   Else
   C1=0
   EndIf
 
   // LED Three control
   If (GROUP3 > cOUNTER) Then
   C2=1
   Else
   C2=0
   Endif
   {
     // LED four control
   If (GROUP1 > cOUNTER) Then
   C3=1               //leds on portb
   Else
   c3=0
   EndIf
  
     // LED One control
   If (GROUP2 > cOUNTER) Then      //PORT C
   C4=1
   Else
   C4=0
  EndIf
    // LED One control
   If (GROUP3 > cOUNTER) Then      //PORT C
   C5=1
   Else
   C5=0
  EndIf
 
   // LED Two control
   If (GROUP1 > cOUNTER) Then
   C6=1
   Else
   C6=0
   EndIf
 
   // LED Three control
   If (GROUP2 > cOUNTER) Then
   C7=1
   Else
   C7=0
   Endif
   }

 
// Increment PWM cycle counter  every loop
   cOUNTER = (cOUNTER + 10000)

// Check for overflow
   If cOUNTER > 65000 Then
   cOUNTER = 0
   fade_1()
  
   'fade_3()
 endif
 next 
   fade_2()
   fade_3()
   fade_4()
// Add the fades etc. here.

   'End If
 
 Wend
 

MrDEB

Well-Known Member
while waiting for 330ohm resistor arrays from Newark I want to try and program the 18f43k22 using the code posted in post#17.
thinking it already is multiplexing?
 

MrDEB

Well-Known Member
remember I can only source up to 185ma
using blue and white leds, looking at 14ma each?
 

tumbleweed

Active Member
I have no idea what the code in post #17 is doing, but this part of the code will never execute...
Code:
// Check for overflow
   If cOUNTER > 65000 Then
   cOUNTER = 0
   fade_1()
  
   'fade_3()
 endif

Assuming your LEDs have a Vf of about 3.5V, then the 150 R will get you about 10mA/LED.
Just use 2 or 3 ports worth and you'll be fine.
 

Latest threads

New Articles From Engineer's Garage

Top