Continue to Site

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.

Using PWM on a 18F13K22

Status
Not open for further replies.
Via Hack-A-Day comes an interesting article, Hacking a Candleflicker LED. What? LEDs specifically designed to look like candles costing a few cents ? Wow. Who knew.

The author takes a detailed look at how these work and includes AVR code to implement the algorithm. There is also a link to about half-a-million LED candle projects.

Definitely worth a read.
 
Here's a Swordfish port of the AVR C code from the article.
Code:
//
// Emulates a Candleflicker-LED
// ported from CandeflickerLED.c
//
device = 18F4520
clock = 8

// LED connected to PB0 (set this to match your hardware)
dim LEDPIN as PORTB.0

// main flicker clock = 440*16 Hz
const FLICKER_DELAY as word = ((1000000/440)/16)

//
// 32 Bit maximum length LFSR
// see http://www.ece.cmu.edu/~koopman/lfsr/index.html
// Using inverted values so the LFSR also works with zero initialisiation
//
dim rand_z as longword

function random() as byte
    rand_z = rand_z >> 1

    if (rand_z.bits(0) = 0) then
        rand_z = rand_z xor $7FFFF159
    endif

    result = rand_z.byte0
end function


dim pwm_ctr as byte        // 4 bit-Counter
dim frame_ctr as byte      // 5 bit-Counter
dim pwm_val as byte        // 4 bit-Register
dim nextbright as byte      // 4 bit-Register
dim rand as byte            // 5 bit Signal
dim randflag as boolean    // 1 bit Signal

// initialization
rand_z = 0
pwm_ctr = 0
frame_ctr = 0
pwm_val = 0
nextbright = 0
rand = 0
randflag = false

low(LEDPIN)

while (true)
    delayus(FLICKER_DELAY)

    // PWM
    pwm_ctr = pwm_ctr + 1
    pwm_ctr = pwm_ctr and $0f  // only 4 bit

    if (pwm_ctr <= pwm_val) then
        LEDPIN = 1
    else
        LEDPIN = 0
    endif
  
    // frame
    if (pwm_ctr = 0) then
        frame_ctr = frame_ctr + 1
        frame_ctr = frame_ctr and $1f
      
        // generate a new random number every 8 cycles
        // In reality this is most likely bit serial
        if ((frame_ctr and $07) = 0) then
            rand = random() and $1f
            if ((rand and $0c) <> 0) then
                randflag = true                // only update if valid
            endif
        endif
      
        // new frame
        if (frame_ctr = 0) then
            pwm_val = nextbright        // reload PWM
            randflag = true            // force update at beginning of frame
        endif
          
        if (randflag) then
            if (rand > 15) then
                nextbright = 15
            else
                nextbright = rand
            endif
            randflag = false                // not in original code
        endif
    endif

end while
 
Here's a Swordfish port of the AVR C code from the article.
Code:
//
// Emulates a Candleflicker-LED
// ported from CandeflickerLED.c
//
device = 18F4520
clock = 8

// LED connected to PB0 (set this to match your hardware)
dim LEDPIN as PORTB.0

// main flicker clock = 440*16 Hz
const FLICKER_DELAY as word = ((1000000/440)/16)

//
// 32 Bit maximum length LFSR
// see http://www.ece.cmu.edu/~koopman/lfsr/index.html
// Using inverted values so the LFSR also works with zero initialisiation
//
dim rand_z as longword

function random() as byte
    rand_z = rand_z >> 1

    if (rand_z.bits(0) = 0) then
        rand_z = rand_z xor $7FFFF159
    endif

    result = rand_z.byte0
end function


dim pwm_ctr as byte        // 4 bit-Counter
dim frame_ctr as byte      // 5 bit-Counter
dim pwm_val as byte        // 4 bit-Register
dim nextbright as byte      // 4 bit-Register
dim rand as byte            // 5 bit Signal
dim randflag as boolean    // 1 bit Signal

// initialization
rand_z = 0
pwm_ctr = 0
frame_ctr = 0
pwm_val = 0
nextbright = 0
rand = 0
randflag = false

low(LEDPIN)

while (true)
    delayus(FLICKER_DELAY)

    // PWM
    pwm_ctr = pwm_ctr + 1
    pwm_ctr = pwm_ctr and $0f  // only 4 bit

    if (pwm_ctr <= pwm_val) then
        LEDPIN = 1
    else
        LEDPIN = 0
    endif

    // frame
    if (pwm_ctr = 0) then
        frame_ctr = frame_ctr + 1
        frame_ctr = frame_ctr and $1f
   
        // generate a new random number every 8 cycles
        // In reality this is most likely bit serial
        if ((frame_ctr and $07) = 0) then
            rand = random() and $1f
            if ((rand and $0c) <> 0) then
                randflag = true                // only update if valid
            endif
        endif
   
        // new frame
        if (frame_ctr = 0) then
            pwm_val = nextbright        // reload PWM
            randflag = true            // force update at beginning of frame
        endif
       
        if (randflag) then
            if (rand > 15) then
                nextbright = 15
            else
                nextbright = rand
            endif
            randflag = false                // not in original code
        endif
    endif

end while
Are you, a closet AVR man?:nailbiting::facepalm::joyful:

good work by the way!
Someone will be glad of that in the future
 
Yes i messed up the math's! Let me have one last try to get it right.

OKEY DOKEY

STEP 1. Decide PWM frequency, the lower the frequency the slower the clock can be. But you dont have as much resolution (number of slots in that period), also slower the frequency, the more chance of unwanted type flicker (flashing). So frequency is a trade off of speed V Resolution (smoothness).
I would start at around 100Hz, this should be fast enough for good smoothness, but not so fast the micro cant do other stuff, like update variables. Also 100Hz makes the math's easier (well was meant to :oops:).
SO STEP 1 = 100Hz

STEP 2.
Workout how much time is in 100Hz, so frequency is divided by time. 1 SECOND / 100Hz (they are reciprocal, which i think means you can ignore the S and the Hz) so we get
1/100 =0.01 as we want a time measurement, the 0.01 is in seconds. SO 0.01s =10ms (10 mili seconds)

Now we know the following for timer, Interrupt based smooth PWM we need a PERIOD of 10ms
Or to phrase it another way, if you set a timer to something every 10ms then its frequency is 100Hz
This is magic!! as normally we like to have the DUTY CYCLE Between 1 AND 100 (well 99 as 100 is just fully on or straight DC)

STEP 3.
We know we need to set the timer so it triggers 100 TIMES every 10ms. So now we work out what 10ms is Divided by 100

10ms/100= 0.0001s OR 100us (100 micro seconds)

Quick recap, if we want a PWM frequency of 100Hz and a Duty Cycle between 1 and 100, we set the timer to interrupt our micro every 100 micro seconds. BUT THEN WHAT??

WE ARE NOW INSIDE THE ISR. NOT! THE MAIN CODE

STEP 4. INSIDE the ISR (Interrupt Service Routine) We (actually you!) place a variable, lets call it duty_cycle.

STEP 5. EVERY time the timer fire's the interrupt (Once every 100 us) we check that duty_cycle = < (Less than) 100.
Because, if we want a maximum DUTY CYCLE of 100 (on fully on) then duty_cycle must be less than 100
IF duty_cycle<(Less than) 100 We (you) ADD 1 To duty_cycle

WE ARE NOW OUTSIDE ISR IN MAIN PROGRAM
In your main code you have an array, Lets call it DUTY_CYCLE (i lack imagination this time of night) actually keep these names, it makes the code make more sense to read, now you know that duty_cycle is the Variable inside the ISR, that keeps a count of how many times the 100 us (micro seconds) has passed.

And you also know that DUTY_CYCLE is a array outside the ISR , that in a bit we will put values in ;).
I have named one array to make it simple to follow, I dont know if you know how to set a multi dimensional array?




ACTUALLY before i go on i do need to know that, If you know how to do an array with more than 1 element in swordfish then i will go one way with this, If you dont then we can go another way.
so please answer that QUESTION and i will continue with a step by step break down of what you need to do, I promise at the end of this you will know 2 things, 1 how to do software pwm on ANY chip with timer and 2 make a kick arse NON REDNECK candle :D
 
Last edited:
Mr Deb when you read this, please answer LG's question. What he has put above, is a small part of what verbally, he has told me tonight. His plan should give you 4 RGB leds, per chip!
On top of that, you will be able to pwm each channel, that mean's INDIVIDUAL PWM for each colour on each led, plus as a bonus individual pwm on each anode for brightness and flicker control.
He has offered to walk you through it step by step, and i have to be honest if it works like ha say's it will, the code wont be too bad, and you will get one hell of a display!
 
LG,
Like many forms of BASIC, Swordfish doesn't support multidimensional arrays.

It's not hard to achieve the same thing, but if you have another solution that would probably be better.
 
I wonder what they look like running and if you used more than one on the same power source if they would flash in unison or stay individually random.
I might be able to answer that! on the site i gave you in another thread (signal path), there is a video on this. Apparently some types of these leds have fairly sophisticated chips on the die, they also have a very good algorithm for randomness, so the chances are they will be random.
I watched the video with LG, if i can find it again i will post it. It was pretty interesting like alot of that guy's video's!
I wish LG hadn't seen that HP scope one tho !:banghead::banghead: Guess what he wants for his next 2000 birthday's:facepalm::facepalm::facepalm::facepalm:, i also said jokingly to him.. tell you what son how about i throw in the new Agligent Frequency analyzer as well :facepalm::facepalm::facepalm::facepalm:

He beamed at me and said that would be great DAD :meh::meh: still a promise is a promise, so i have told him if he set's up the ladder, against the money tree for me. I will go climb it and he can have the scope :woot::woot:

Lets hope he hasnt joined a gardening forum asking how to grow money tree's!
 
There are comments on Hack-A-Day that say that the flickering LEDs never sync up with each other.


LG will make good use of the scope and frequency analyzer Ghostman :)
 
There are comments on Hack-A-Day that say that the flickering LEDs never sync up with each other.


LG will make good use of the scope and frequency analyzer Ghostman :)
wont be much good if we dont have a house to put it in! $500,000 for the scope!!! What i dont get tho, is it runs windows7!!! you would have thought LINUX would be much better suited to a instrument! makes you wonder what kind of deal MICRO SH@T did!
 
$500,000???? Wow. Perhaps something a little less expensive will do for now.
 
This method that Little Ghostman presented sounds intriguing. BUT as Tumbleweed pointed out, Swordfish Like many forms of BASIC, doesn't support multidimensional arrays.
YES I have done arrays as some of the code I posted has in them.
Been looking at a lot of other LED Candle projects and most use just a Red LED and Yellow. Some use several LEDs for one candle.
In post #182 Tumbleweed posted a converted code that I tried out after changing the Device etc. The code works but it blinks instead of a smooth flicker. Going to see what can be done with it.
On the LEDs, going to obtain some bi-color RED/YELLOW Leds. I took some frosted looking scotch tape and taped a yellow Led and Red led together and the results are slightly better than using the RGB but most of the candles on the web use multiple Leds so taking the circuit Ghostman posted a link to and reconfiguring using instead of 3 Yellow and 2 Red LEDs , go with one or two Bi color LEDs. As for PCboards, Have done lots of boards in house.
 
WHEN I win the lottery tonight (last I herd it's up to $500mil) I will buy LittleGhostman the scope and deliver it personally in my private jet.
Time to get back to reality.
 
I posted a reply but ??
Yes I can do arrays. Have done several codes using them.
Having looked at other similar projects I see they are using just Yellow and Red LEDS. some use several of each color so I am obtaining several Bi colored RED/ YELLOW Leds with diffused lens (recommended in several projects)
I tried out the code that Tumbleweed posted but it is not a smooth flicker, more of a blinking. Going to tinker with it more.
Plan is to use the Bi Colored Leds and the circuit that Ghostman posted a link to. Started designing PCboards for in house etching. As for code, the video doesn't look very realistic. More of a blink instead of a s m o o t h flicker. I taped a red and yellow Led together and it looks pretty realistic.
 
Mr Deb, do not fear. As i pointed out i stopped at a point where we have two approaches, now i know swordfish cant do one of them, later i will continue on the original post, it just means the next steps will be a different way to what i thought they would be.
It dosnt make any difference with the array thing, we have another option and everything i have posted in that post, is still valid!
I will continue later as that post took two hours to do, so i will do it this evening. Relax once i have walked you through it, you should be able to do the code pretty quickly, and dont go tying this down and that up yet. There is no need to compromise your design, i am showing you a easy way to blow every other candle out the water. Once it's done, read it carefully a couple times. Then together we will take each step and convert them into your code, one by one. ANYTHING you are a bit vague on, SHOUT OUT. I am trying to explain it in as much simple detail as I can, but if needed i can reword some of it in a way you can grasp it (i have to have alot of stuff done like this for me to understand, sometimes changing just the way something is worded makes all the difference, to understanding it). Before someone thinks i am writing it in a belittling way, i am not. I have chosen to spell it out in the most basic detail i can, because even if Mr Deb knows 0.01 ms is 10 mili seconds, one day someone else might read that hasnt got a clue what 0.01s is.
So it's a kind of tutorial but also, if i do it like that it helps me not get lost as i do it
 
With the way i am going to outline you can use the RGB you have, you need nothing more than you already have! no transistor's nothing! you could add transistor's if you wanted but they are not needed.
 
Sigh.... I am so done with this. Apparently MrDEB doesn't even bother to click hyperlinks.

This forum thread is just about to go 11 pages. I'll bet it reaches 17 with nothing to show for it. Keep up the good work guys but recognize the futility of the effort.
 
Status
Not open for further replies.

Latest threads

Back
Top