Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.arch.embedded > #29137
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Newsgroups | comp.arch.embedded |
| Subject | Re: Poor man's PWM |
| Date | 2020-01-28 11:29 +0100 |
| Organization | A noiseless patient Spider |
| Message-ID | <r0p2ea$h28$1@dont-email.me> (permalink) |
| References | <r0o0mu$c6l$1@dont-email.me> |
On 28/01/2020 01:53, Don Y wrote:
> With "few" intensity levels desired, I plan to drive LED
> with a crude PWM signal directly from an IRQ (i.e., push
> bits out a hardware port at each IRQ).
>
> But, instead of having N different times at which the IRQ
> might be signalled (for the N+1 different duty cycles) in
> each refresh interval, I plan on having log2(N) times, each
> delimiting an period "twice" as long as the previous. This
> keeps the hardware cheaper than dirt and minimizes the
> real-time load on the processor.
>
> [There are (refresh_rate * log2(N)) IRQs each second instead
> of (refresh_rate * N) IRQs -- though the *instantaneous* IRQ
> rate varies considerably]
>
> Then, at the level above the driver, build a schedule for which
> intervals to activate the LED.
>
> E.g., for each level: turn the LED on in intervals:
> 0 None
> 1 1
> 2 2
> 3 1&2
> 4 4
> 5 1&4
> 6 2&4
> ...
> N All
>
> What problems might I encounter with this approach? (I'm
> mainly worrying about visual artifacts)
It sounds doable, but complicated. I think you'd need a good many
different intensity levels before this would pay off - the overhead of
tracking and setting the different time intervals won't make sense until
you are using a huge number of levels. And if you wanted a huge number
of levels, you'd be using a better quality method of generating the PWM
signal that doesn't have as much jitter.
As far as processor load goes, there are two key points. One is the
worst case rate of the IRQs - and that is determined by the lowest
digit, and will be the same for a regular pulse or for this complex
scheme. The other is the amount of processor work done in each IRQ, and
that will be massively more than with a simple system, outweighing it in
total work until you have a huge number of levels.
Let me guess some numbers - and you can correct them if they are
inappropriate.
Pick a refresh frequency of 100 Hz, which is fast enough that you won't
see blinking even if you move your eyes quickly. We'll have 16 levels,
which is more than enough for normal circumstances.
That puts your timer interrupt at 1600 Hz - not an onerous burden for
most systems. And being a regular timer interrupt, you can use the same
tick for other purposes, unlike your specialised one.
Below is a simple example. It can easily be modified to have different
pattern types (minimise switching, or spread the on/off time evenly
within the cycle), different mapping between logical levels and total
duty cycle (to better suit the visual brightness impression), multiple
leds, etc.
#include <stdint.h>
enum { levels = 16 };
_Static_assert(levels <= 16, "Pattern type needs to suit levels");
typedef uint16_t pattern_t;
static const pattern_t patterns[levels + 1] = {
0x0000,
0x0001, 0x0101, 0x0841, 0x1111, 0x2491, 0x4949, 0x54a9, 0x5555,
0xab55, 0xb5b5, 0xdb6d, 0xdddd, 0xf7bd, 0xfdfd, 0xfffd, 0xffff
};
static int ledLevel;
void setLedLevel(int level) {
if (level < 0) level = 0;
if (level >= levels) level = levels;
ledLevel = level;
}
extern void ledOn(void);
extern void ledOff(void);
static pattern_t stepper = 1;
static const pattern_t last_step = (1u << (levels - 1));
void ledTimerInterrupt(void) {
pattern_t pattern = patterns[ledLevel];
if (pattern & stepper) {
ledOn();
} else {
ledOff();
}
if (stepper == last_step) {
stepper = 1;
} else {
stepper = stepper << 1;
}
}
Back to comp.arch.embedded | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-27 17:53 -0700
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-27 19:29 -0800
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-28 20:11 -0700
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-28 20:11 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-28 11:29 +0100
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-28 20:34 -0700
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-28 20:32 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-29 12:53 +0100
Re: Poor man's PWM Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2020-01-28 14:43 +0100
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-28 12:03 -0800
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-28 20:54 -0700
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-28 21:54 -0800
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-29 00:17 -0700
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-28 23:40 -0800
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-29 00:54 -0700
Re: Poor man's PWM Paul Rubin <no.email@nospam.invalid> - 2020-01-29 00:04 -0800
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-29 02:17 -0700
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-29 13:21 +0100
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-29 09:51 -0800
Re: Poor man's PWM Paul Rubin <no.email@nospam.invalid> - 2020-01-29 10:07 -0800
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-29 10:14 -0800
Re: Poor man's PWM Paul Rubin <no.email@nospam.invalid> - 2020-01-29 10:28 -0800
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-29 11:40 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-30 10:25 +0100
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-30 08:06 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-30 21:21 +0100
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-30 15:08 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-31 01:17 +0100
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-30 17:21 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-31 10:59 +0100
Re: Poor man's PWM Rick C <gnuarm.deletethisbit@gmail.com> - 2020-02-01 10:18 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-30 10:20 +0100
Re: Poor man's PWM Tom Gardner <spamjunk@blueyonder.co.uk> - 2020-01-30 10:13 +0000
Re: Poor man's PWM Paul Rubin <no.email@nospam.invalid> - 2020-01-29 09:57 -0800
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-30 10:29 +0100
Re: Poor man's PWM Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2020-01-29 16:34 +0100
Re: Poor man's PWM Dimiter_Popoff <dp@tgi-sci.com> - 2020-01-28 17:39 +0200
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-28 19:58 -0700
Re: Poor man's PWM Dimiter_Popoff <dp@tgi-sci.com> - 2020-01-29 18:54 +0200
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-01-29 00:17 -0700
Re: Poor man's PWM David Brown <david.brown@hesbynett.no> - 2020-01-29 13:39 +0100
Re: Poor man's PWM Paul Rubin <no.email@nospam.invalid> - 2020-01-29 10:08 -0800
Re: Poor man's PWM Don Y <blockedofcourse@foo.invalid> - 2020-04-27 20:13 -0700
csiph-web