Go Down

Topic: Best approach for changing PWM in certain time? (Read 950 times) previous topic - next topic

AWOL

For this sort of thing, I often use an 8.24 fixed-point format (32 bit overall), using the top eight bits as the PWM value, and simply accumulate pre-calculated fractions.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Baltasar

Hummm, sorry... AWOL can you detail that or give a code example, I'm too new on this to understand most of what you are saying.
Check all my projects based on Atmel/Arduino -> www.aqualed-light.com

AWOL

Imagine a "long" variable "x" as an array of four "byte"s "xb[4]" (define a union).
Because the Arduino is little-endian, the most significant eight bits of "x" are held in xb[3].
xb[3] will the value written to our PWM device.

Now, if we set "x" to 0x01000000, xb[3] will contain 0x01.
Assume we want to fade x from 1 to 5 in 300 steps, so we take the difference of 5 and 1 (4) and divide by 300, yielding  0.0133.
Now, multiply 0.013333 by 224 (= 16 777 216) to give 223 696 (0x000369D0)
Store this value in a "long" called "inc".
Now, repeatedly add "inc" to "x", but only write xb [3] to your PWM device each time through the loop.

This technique is most useful when you've got a number of LEDs to fade to and from different values, but in a fixed number of steps.

(it comes out a lot easier than I described it!)
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

MarkT

#8
Jul 03, 2011, 01:57 am Last Edit: Jul 03, 2011, 02:01 am by MarkT Reason: 1
You don't need floats for ratiometric things like this.

Say you want to step 255 steps in 317 seconds.  You initialize a variable accum to 0, and every second you do this:

Code: [Select]

 accum += 255 ;
 while (accum >= 317)
 {
    brightness += 1 ;
    analogWrite (pin, brightness) ;
    accum -= 317 ;
 }


After 317 seconds you have incremented the variable by 255 a total of 317 times.  But you have also decremented it by 317 a total of 255 times (and also stepped the brightness 255 steps).

This integer ratio based technique is the mainstay of all graphics promitives (drawing sloped lines) and is variously known as DDA (digital differential analyzer), or Bressenham's algorithm.  And it avoids floats and is ultra-fast.

If you process every millisecond, just use 317000 instead of 317
[ I won't respond to messages, use the forum please ]

Baltasar

MarkT,thanks for the help you solution is almost perfect for me.

Going now to do more tests and see if I reach the perfect result that I need, since apart the need of diming from 0 to 255 I need to show on the LCD the dimming percentage (0% to 100%), converting is easy, but I get again the float values that I can't compare with the integer pwm values. For example 48% represents 122,4 pwm value, if I want to stop during the DIM on a specific value like this 48% there is no way sinve only going to pass on 122 integer.

:smiley-roll:
Check all my projects based on Atmel/Arduino -> www.aqualed-light.com

Go Up