# software PWM

#### tumbleweed

##### Active Member
Never knew that // was a comment in basic, thought it was a C thing. In basics I've used it's normally '
Swordfish will accept either style as a comment.

Block comments are a bit different though. There is uses "(*" and "*)" for begin-end comment block.

#### MrDEB

##### Well-Known Member
I think I have hit a very simple loop that changes the led brightness or dimness.
In order to dim you must turn off the led thus the delays. In this simple loop, the delay is varied in accordance with the INDEX
I am using DEKAYMS(XXX) so I can see the rate of flash increase then decrease etc.
post #2 & 5 got me to rethink how to do this simple task which incorporates most all suggestions
Am using INDEX as a LONGWORD to length the transition time between bright and dim.
The flash rate increases then decreases which indicates it is maybe doing as desired. Will try using DELAYUS instead of DELAYMS.

Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2022 [select VIEW...EDITOR OPTIONS]              *
*  Date    : 5/21/2022                                                      *
*  Version : 1.0                                                            *
*  Notes   :  copy n pasted from
Report
rjenkinsgb                                                              *
*          :                                                                *
*****************************************************************************
}
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"
//LEDS
DIM LED1 AS PORTA.0
DIM LED2 AS PORTB.0
DIM LED3 AS PORTC.0
DIM LED4 AS PORTD.0

DIM Time1 AS BYTE
DIM Time2 AS BYTE
DIM Time3 AS BYTE
DIM Time4 AS BYTE
DIM INDEX AS LONGWORD
dim counter as LONGWORD
dim Bright as longword        // a wider range of settings
dim Dimmer as longword

//LEDS ALL OFF AT START OF PROGRAM
led1 = 0
led2 = 0
led3 = 0
led4 = 0

Time1 = 25
Time2 = 50
Time3 = 75
Time4 = 100
//INCREMENT/ DECRIMINATE ON/OFF TIMES

INDEX = 1
//MAKE ALL OUTPUTS
trisa=0
'trisb=0
'trisc=0
'trisd=0

While TRUE

// LED One control
IF INDEX <=10000 THEN
TIME1 = (TIME1 + INDEX)
endif
led1=1
delayMs(Time1)             //INCREMENT THIS FOR BRIGHTER
led1=0
DELAYMS(TIME1)

// LED One control
IF INDEX >=10000 THEN
TIME1 = (TIME1 - INDEX)
endif
led1=1
delayMs(Time1)             // DECRIMENT FOR DIMMER
led1=0
DELAYMS(TIME1)

INDEX = (INDEX +1)    //INCRIMENT INDEX EACH PASS THROUGH LOOP
IF INDEX >= 10000 THEN
INDEX = (INDEX - 1)

End If

Wend

Sigh

#### For The Popcorn

##### Active Member
Nevermind. Suggestions won't be taken anyway.

#### MrDEB

##### Well-Known Member
now this starts out really dim then goes bright really smooth but it won't go from full bright back to dim
Code:
BRIGHT_1 = 1
DIMMER_1 = 25000
BRIGHT_2 = 25000
DIMMER_2 = 1

INDEX = 1
//MAKE ALL OUTPUTS
trisa=0
'trisb=0
'trisc=0
'trisd=0

While TRUE
//this is a real smooth from dim to bright
repeat
led1 = 1
delayus(bright_1)  // 1
led1 = 0                   // dim
delayus (dimmer_1)  //25000
bright_1 = (bright_1 +1)
dimmer_1 = (dimmer_1 - 1)
until
bright_1 = 2500

//this won't go back to dim??
repeat
led1 = 1
delayus(dimmer_2)  // 1
led1 = 0                   // full bright
delayus (bright_2)  //255
bright_2 = (bright_2 -1)
dimmer_2 = (dimmer_2 + 1)
until
dimmer_2 = 2500

wend

#### For The Popcorn

##### Active Member
Since you won't try suggestions that will work, and keep heading down paths that won't work, it's doubtful that anybody will attempt to decipher your code.

#### MrDEB

##### Well-Known Member
What I did was started from scratch to find out what ratio of LED ON TIME vers OFF TIME
try this and you will see what I am talking about
for a full dim
LED = 1 Delayus(1)
LED = 0 Delayus(25000)
this will dim the LED almost off

Now reverse the combination
LED=1 Delayus(25000)
led=0 Delayus(1)

While watching tv last night I was pondering my code and realized I need to reset the values of bright_1 and bright_2
bright _2 = bright_1 insert before second UNTIL LOOP
dimmer_2 = dimmer_1 insert AFTER THE SECOND until loop
after I finish this post will give it a go
Post 2 & 5 started my rethinking process about how to do a software only PWM simulation so thanks

#### MrDEB

##### Well-Known Member
THIS CODE WORKS PERFECT as desired

A really s m o o t h transition from very dim to very bright. Found a glitch AFTER I added a transition indicator led2
Just that small addition helped locate the issue of a jump from full bright back to full dim
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2022 [select VIEW...EDITOR OPTIONS]              *
*  Date    : 5/21/2022                                                      *
*  Version : 1.0                                                            *
*  Notes   :  WORKS GREAT 5/23/22                                                             *
*          :                                                                *
*****************************************************************************
}
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"
//LEDS
DIM LED1 AS PORTA.0
DIM LED2 AS PORTE.1
DIM LED3 AS PORTC.0
DIM LED4 AS PORTD.0

dim counter as LONGWORD
dim Bright_1 as longword        // a wider range of settings FOR A SMOOTHER TRANSITION
dim Dimmer_1 as longword
dim Bright_2 as longword        // a wider range of settings
dim Dimmer_2 as longword

//LEDS ALL OFF AT START OF PROGRAM
led1 = 0
led2 = 0
led3 = 0
led4 = 0

//INCREMENT/ DECRIMINATE ON/OFF TIMES
BRIGHT_1 = 0
DIMMER_1 = 0
BRIGHT_2 = 0
DIMMER_2 = 0

INDEX = 1
//MAKE ALL OUTPUTS
'trisa=0
'trisb=0
'trisc=0
'trisd=0
OUTPUT (LED1)
OUTPUT(LED2)
//     USING VALUE OF 5000 FOR A S M O O T H TRANSITION.

While TRUE
bright_1 = 1              // bright_1 is ON  time variable
dimmer_1 = 5000           //dimmer_1 is OFF time variable
repeat
led1 = 1
delayus(bright_1)
led1 = 0                   // dim
delayus (dimmer_1)
bright_1 = (bright_1 +1)   // increase ON time BY 1
dimmer_1 = (dimmer_1 - 1)  //decrease OFF time BY 1
until
bright_1 >= 5000            //HIGH BRIGHT

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//reset values
bright_2 = 5000
dimmer_2 = 1
LED2 = 1                    // LED2 COMES ON WHEN LED1 STARTS FROM HIGH BRIGHT TO FULL DIM
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

repeat
led1 = 1
delayus(BRIGHT_2)           // LED is full brightness  FIRST PASS IN LOOP
led1 = 0
delayus(DIMMER_2)           // full dim          FIRST PASS IN LOOP
bright_2 = (bright_2 - 1)
dimmer_2 = (dimmer_2 + 1)
until
bright_2 = 1
//reset valuesxxxxxxxxxxxxxx
bright_2 = 1
dimmer_2 = 5000
LED2 = 0                      // LED2 GOES OFF WHEN LED1 STARTS FROM FULL DIM  TO HIGH BRIGHT
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
wend

{

//increase brghtness
REPEAT
// LED One control
IF INDEX <=255 THEN
BRIGHT = (INDEX + 1)
endif
led1=1
delayMs(DIMMER)             //INCREMENT THIS FOR BRIGHTER
led1=0
DELAYMS(BRIGHT)
BRIGHT = (BRIGHT + 1)
UNTIL
BRIGHT >= INDEX

// decrease brightness

REPEAT
// LED One control
IF INDEX >= 1 THEN
DIMMER = (INDEX)
endif
led1=1
delayMs(BRIGHT)             // DECRIMENT FOR DIMMER
led1=0
DELAYMS(DIMMER)
UNTIL
DIMMER <= INDEX

IF INDEX <= 255 THEN
BRIGHT = (INDEX + 1)        // increase BRIGHT  until it hits 100000
End If
IF DIMMER >= 100000 THEN   //decrease  DIMMER  until it hits 0
DIMMER = (INDEX - 1)
End If
' if INDEX = 0 then index = (INDEX + 1) end if
'if index = 1000000 then

Wend

#### For The Popcorn

##### Active Member
Awesome.

But the problem is, as you have discovered already in this thread, comes when you try to do this with more LEDs.

#### MrDEB

##### Well-Known Member
that's my next challenge BUT I do have a really good fading in & out snippet that works.
got to start small then go big.

#### MrDEB

##### Well-Known Member
Code:
Sub Fade()

Bright_1 = 1              // bright_1 is ON  time variable
Dimmer_1 = 5000           //dimmer_1 is OFF time variable
Repeat
PORTA = %11100111
DelayUS(Bright_1)
PORTA = %00000000                   // dim
DelayUS (Dimmer_1)
Bright_1 = (Bright_1 +1)   // increase ON time BY 1
Dimmer_1 = (Dimmer_1 - 1)  //decrease OFF time BY 1
Until
Bright_1 >= 5000            //HIGH BRIGHT

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//reset values
Bright_2 = 5000
Dimmer_2 = 1
' LED2 = 1                    // LED2 COMES ON WHEN LED1 STARTS FROM HIGH BRIGHT TO FULL DIM
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Repeat
PORTA = %11100111
DelayUS(Bright_2)           // LED is full brightness  FIRST PASS IN LOOP
PORTA =%00000000
DelayUS(Dimmer_2)           // full dim          FIRST PASS IN LOOP
Bright_2 = (Bright_2 - 1)
Dimmer_2 = (Dimmer_2 + 1)
Until
Bright_2 = 1
//reset valuesxxxxxxxxxxxxxx
Bright_2 = 1
Dimmer_2 = 5000
' LED2 = 0                      // LED2 GOES OFF WHEN LED1 STARTS FROM FULL DIM  TO HIGH BRIGHT
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

#### tumbleweed

##### Active Member
...except that individual delay statements won't work well when you add 53 leds unless you want them all to look the same.

#### MrDEB

##### Well-Known Member
The issue is current draw. I have 14 pairs of white LEDs in parallel with one 330 ohm resistor per pair which should be around 7ma per pair. Same for the 20 pairs of blue
7 x 14 = 98 rounded off to 100 ma.
the pic data sheet says 180ma max so the BLUE and WHITE can't be on at the same time
14 pairs of white and 20 pairs of blue = a total of 68 leds.
IF I decide to have more boards made then a different pattern for the resistor arrays and use 750 ohm resistors
a definite design flaw
One way around it is TOGGLE THE BLUE?

#### For The Popcorn

##### Active Member
Since MrDEB has been silent today, he may have figured out that a whole bunch of serial routines with delay statements aren't going to accomplish what he wants at least not very well.

One way to do what he wants is to base all actions on a loop counter, with at most exactly ONE delay statement. Ok, let's start with the basic program loop.

Code:
Dim Counter as Longword
Counter = 0

While 1 = 1

// some code will go here

Inc (Counter)
If Counter > 4000000000 then
Counter = 0
End If

Wend

What happens in this program loop? The variable Counter counts from 0 to 4,000,000,000. This number can actually be 2^32, but rounding it off won't matter much. The IF statement may not be strictly necessary. The Counter value should automatically wrap back to zero.

Pretty neat, huh? Well, let's work on that. Let's add an LED, say at 50% brightness .

Code:
Dim Counter as Longword
Dim LED1On as Longword
Dim LED1Off as Longword

LED1On  = 0
LED1Off = 0
Counter = 0

While 1 = 1

// some code will go here
If Counter = LED1On then
LED1 = 1
LED1On = Counter + 20
LED1Off = Counter + 10
End If
If Counter = LED1Off then
LED1 = 0
End If

Inc (Counter)
If Counter > 4000000000 then
Counter = 0
End If

Wend

Ok, so what happens here? Led1On starts at 0. When the Counter value equals 0, three things happen:
¤ LED1 is turned on
¤ LED1On is set to 20
¤ LED1Off is set to 10

When the Counter = 10, LED1 will be turned off.

When the Counter = 20, the sequence repeats.

LED1 is on half the time, off half the time, so the brightness is 50%. This is kind of crude; making it a subroutine (do not call this a sub route. That is gibberish.) would be cleaner.

So now let's add a second LED, operating at the same time the first does it's thing.

Code:
Dim Counter as Longword
Dim LED1On as Longword
Dim LED1Off as Longword
Dim LED2On as Longword
Dim LED2Off as Longword

LED1On  = 0
LED1Off = 0
LED2On = 0
LED2Off = 0
Counter = 0

While 1 = 1

// some code will go here
If Counter = LED1On then
LED1 = 1
LED1On = Counter + 20
LED1Off = Counter + 10
End If
If Counter = LED1Off then
LED1 = 0
End If

If Counter = LED2On then
LED2 = 1
LED2Off = 20
LED2On = 500
End If
If Counter = LED2Off then
LED2 = 0
End If

Inc (Counter)
If Counter > 4000000000 then
Counter = 0
End If

Wend

So now, while LED1 is flashing rapidly on and off to be 50% bright, LED2 is flashing very briefly on and then off for a long period, resulting in a twinkling effect. Two LEDs operating independently in the same loop.

This definitely is not polished code, but will show anybody willing to take a few minutes to understand the code how to use this technique. This loop incrementing up to 4,000,000,000 is going to execute very quickly. The on/off Counter times need to be adjusted to suit the effect desired, and a short delay may need to added at the end of the loop. Also, at the end of the loop, initial values will need to be reset to zero.

The picture shows the process. On and off periods might be set to random numbers. But remember, all actions are based on Counter values. Exactly one delay statement might be added. MrDEB's fading routine can also be adapted to this technique.

#### For The Popcorn

##### Active Member
I didn't check timing....I was a little off.

With a 20MHz clock, 1,000,000 cycles takes roughly 3.5 seconds. You can adjust the number of counter cycles to be the length of the pattern you want. Note: a slower clock will take longer to run – an 8MHz clock will take about 9 seconds, so each counter Increment is about 9 uSec.

#### Pommie

##### Well-Known Member
Since MrDEB has been silent today, he may have figured out that a whole bunch of serial routines with delay statements aren't going to accomplish what he wants at least not very well.

One way to do what he wants is to base all actions on a loop counter, with at most exactly ONE delay statement. Ok, let's start with the basic program loop.

Code:
Dim Counter as Longword
Counter = 0

While 1 = 1

// some code will go here

Inc (Counter)
If Counter > 4000000000 then
Counter = 0
End If

Wend

What happens in this program loop? The variable Counter counts from 0 to 4,000,000,000. This number can actually be 2^32, but rounding it off won't matter much. The IF statement may not be strictly necessary. The Counter value should automatically wrap back to zero.

Pretty neat, huh? Well, let's work on that. Let's add an LED, say at 50% brightness .

Code:
Dim Counter as Longword
Dim LED1On as Longword
Dim LED1Off as Longword

LED1On  = 0
LED1Off = 0
Counter = 0

While 1 = 1

// some code will go here
If Counter = LED1On then
LED1 = 1
LED1On = Counter + 20
LED1Off = Counter + 10
End If
If Counter = LED1Off then
LED1 = 0
End If

Inc (Counter)
If Counter > 4000000000 then
Counter = 0
End If

Wend

Ok, so what happens here? Led1On starts at 0. When the Counter value equals 0, three things happen:
¤ LED1 is turned on
¤ LED1On is set to 20
¤ LED1Off is set to 10

When the Counter = 10, LED1 will be turned off.

When the Counter = 20, the sequence repeats.

LED1 is on half the time, off half the time, so the brightness is 50%. This is kind of crude; making it a subroutine (do not call this a sub route. That is gibberish.) would be cleaner.

So now let's add a second LED, operating at the same time the first does it's thing.

Code:
Dim Counter as Longword
Dim LED1On as Longword
Dim LED1Off as Longword
Dim LED2On as Longword
Dim LED2Off as Longword

LED1On  = 0
LED1Off = 0
LED2On = 0
LED2Off = 0
Counter = 0

While 1 = 1

// some code will go here
If Counter = LED1On then
LED1 = 1
LED1On = Counter + 20
LED1Off = Counter + 10
End If
If Counter = LED1Off then
LED1 = 0
End If

If Counter = LED2On then
LED2 = 1
LED2Off = 20
LED2On = 500
End If
If Counter = LED2Off then
LED2 = 0
End If

Inc (Counter)
If Counter > 4000000000 then
Counter = 0
End If

Wend

So now, while LED1 is flashing rapidly on and off to be 50% bright, LED2 is flashing very briefly on and then off for a long period, resulting in a twinkling effect. Two LEDs operating independently in the same loop.

This definitely is not polished code, but will show anybody willing to take a few minutes to understand the code how to use this technique. This loop incrementing up to 4,000,000,000 is going to execute very quickly. The on/off Counter times need to be adjusted to suit the effect desired, and a short delay may need to added at the end of the loop. Also, at the end of the loop, initial values will need to be reset to zero.

The picture shows the process. On and off periods might be set to random numbers. But remember, all actions are based on Counter values. Exactly one delay statement might be added. MrDEB's fading routine can also be adapted to this technique.

View attachment 137243
You put a lot of effort into that explanation let's hope it's not wasted.

Mike.

#### For The Popcorn

##### Active Member
You put a lot of effort into that explanation let's hope it's not wasted.

Mike.

I'm quite sure it's an absolute waste of effort, but I'm a champion of lost causes.

#### MrDEB

##### Well-Known Member
an interesting method to dim an led.
I will give it a try and post the code.
As for yesterday, our internet was on/off all day.

#### For The Popcorn

##### Active Member
Yep. Hit another one clean out of the park! Right over his head!

Got to love baseball season.

#### MrDEB

##### Well-Known Member
hate to tell you this but it dos not dim. The ratio of on time vers off time stays the same post 108 works very well. Give it a try. Thanks
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2022 [select VIEW...EDITOR OPTIONS]              *
*  Date    : 5/25/2022                                                      *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}

Device = 18F43K22
Clock = 8

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

// hardware
Dim INDEX  As LongWord  //4294967295

Dim m As Byte
Dim w As Byte
Dim x As Byte
Dim y As Byte
Dim z As Byte
Dim Bright_1 As LongWord        // a wider range of settings FOR A SMOOTHER TRANSITION
Dim Dimmer_1 As LongWord
Dim Bright_2 As LongWord        // a wider range of settings
Dim Dimmer_2 As LongWord
Dim Counter As LongWord
Dim LED1On As LongWord
Dim LED1Off As LongWord
dim led1 as porta.0
main:
// init hdw
// LED port - all outputs 2 LEDs per port in parallel 330 ohm resistor
TRISA = 0      // SET ALL PORTS AS OUTPUTS
TRISB = 0
TRISC = 0
TRISD = 0
TRISE = 0
PORTE=%000         //TURN OFF ALL PORTS
PORTD=%00000000
PORTC=%00000000
PORTA=%00000000
PORTB=%00000000

LED1On  = 0
LED1Off = 0
Counter = 0

While 1 = 1

// some code will go here
If Counter = LED1On Then         //first pass led1 = 0
LED1 = 1                    // led1 is on
LED1On = Counter + 20
LED1Off = Counter + 10      //first pas led1 = 10
End If
If Counter = LED1Off Then
LED1 = 0
End If

Inc (Counter)
If Counter > 4000000000 Then  //   4000000000
Counter = 0
End If

Wend

Replies
2
Views
1K
Replies
14
Views
3K
Replies
3
Views
9K
Replies
3
Views
2K
Replies
2
Views
2K