Searching \ for 'How to display 0 - 100% on an LED bar' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/displays.htm?key=led
Search entire site for: 'How to display 0 - 100 on an LED bar'.

Truncated match.
PICList Thread
'How to display 0 - 100% on an LED bar'
1999\02\22@010855 by Eric Oliver

flavicon
face
First of all, I would like to take a moment to thank all of you.  Over the
last few weeks I have ask several questions and got excellent replies. It's
been several years since I belonged to a group so active and helpful.
Several years ago, I belonged to the Borland C++ forum on CIS. It was
there that I learned to program.  Over time I was able to give back to that
group.  I hope that someday, I'll be competent enough to do the same on
this list.

I would like to pose a question. I'm not really planning to use this
algorithm at this time, but I just bought three LED chips from Radio Shack.
I'm sure most of you know the item.  Each chip consists of ten LEDs in a
bar configuration. You can mount any number of them side by side to form a
chain of bars. I used them to test my PIC hooked up to some 595s.

But I was thinking that they could be used to convey information in the
form of a bar. With values ranging from 0% to 100%. For instance, if you
chained three chips, the first green, the next yellow and the last one was
red. Say you were monitoring spindle load on a machine.  As the load
progresses from 0% to ~33% the green LEDs would light in succession, as it
moved past 33% through ~66% the yellow LEDs would begin to light and so on.

So what I can't figure out is how to translate the load ( in the previous
example ) to the bit representation needed to shift to the 595s.  Just as
an example, let's say the spindle load is measured and the result would be
between 0 and 65535.  Now, we would need 30 bits to control all 30 LEDs.
How would you go about converting the load to the 30 bit number ?

Like I said, I really don't have an application for this at this time, but
since I don't have an answer to the question, I thought I'd ask it. <g>

Eric

1999\02\22@031059 by Gerhard Fiedler

picon face
At 23:41 02/21/99 -0600, Eric Oliver wrote:
> Several years ago, I belonged to the Borland C++ forum on CIS. It was
>there that I learned to program.  Over time I was able to give back to that
>group.

that was really a good forum, many years ago! :)  or is that :( ?

{Quote hidden}

you don't need a 30bit number just because you want to drive a 30led bar :)
all you need is a number from 0 to 30, which boils down to a simple
division, if your representation is linear. 0->0%->no led, 65535->100%->all
(30) leds. that's 30 intervals for 65535, hence each interval
(corresponding to one led more) is 65535/30... you divide your load by this
number, and get the number of leds to switch on.

ge

1999\02\22@032556 by Mark Willis

flavicon
face
For the generic case you can always do it like this, even if it's
non-linear results you want, I'll assume you can figure it out from
here:

 If (Input < threshold_00) return 0x00000000;  //  Light 0 LEDs
 If (Input < threshold_01) return 0x00000001;  //  Light 1 LED
   ...
 If (Input < threshold_29) return 0x1FFFFFFF;  //  Light all but last
 return 0x3FFFFFFF;  //  Light 'em all

 (i.e. you could do a logarithmic response like a VU meter this way.)

 But, you have huge inconvenient 30-bit numbers to return there -
there's a far easier way, return 0 through 30 and use your shift
register to create the 30-bit numbers.

 Also, If it's a linear function, it's really nice if you can do this
using shifts and multiplies (shifts instead of CPU intensive divides.)
So to map 0..65535 to 0..30 LEDs, you want to maybe multiply by 15 then
divide (by right shifting) by 32768, with a little rounding that'll work
out right.  (Makes sense to divide by 256 first, i.e. throw out the low
byte, then do a 16-bit multiply by 15, then add a rounding factor &
finally divide by 128 again, right?)

 Now take your 0..30 number "N" - fill the shift register with an
initial 1 and shift it N-1 times over to the left (initial fill with 0
if your routine returned 0).

 Mark

Eric Oliver wrote:
{Quote hidden}

1999\02\22@041024 by Wagner Lipnharski

picon face
Eric, just a question:
Are those leds electrically isolated in a way you can control
them in a matrix form?  or they have a common polarity pin side?

1) matrix 6 x 5 (11 bits) can be formed to light just one led at time,
  it needs enough pull up at the leds anodes side (source) and
  enough sink current at the catodes side.  There are chips
  available to do it easily.

2) common polarity allow you to use a 74HCT45 for example (bcd to
  decimal decoder - open collector) to select one led from ten,
  sink the catode, using 4 bits combination 0-9 (ignore A-F),
  with other 3 bits you can drive FET transistores that will
  drive which one of the 3 bars of 10 leds will receive power
  (source at anodes).  Again, there are plenty of other chips.

The conversion from 16 bits to matrix selection (65536 -> 5x6)
or (65536 --> 4x3), it is just a common division or logic selection.

As 10 or 30 does not make part of 2^n dimension, it will create
gaps and errors to divide it logicaly using some bits from the
counter to select rows and collumns.  For example, you could use
this logical selection, with errors:  Using the counter high order
first 4 bits (xxxx .... .... ....) to select the bar;

0,1,2,3,4,5 = Green   <--- extra position
6,7,8,9,A   = Yellow (each x800h selects a LED)
B,C,D,E,F   = Red    (each x800h selects a LED)

The Green bar can't share the same idea to use x800h to select a
LED, so it doesn't work well.

Dividing the value 0-65535 by 2184 you will have a result from
0 to 30 (0-1Eh), convert to decimal, use the high nibble to select
the bar (in the common anote or catode posibility), and the low
nibble to select the led (via the 74HCT145 for example).  Here the
error is very small and the most accumulated error will appear at
the last led #30 that will lite earlier 0.023% than expected,
because (2184x30)/65535 = 0.99977, and will hold 16 counts more
than the other LEDS (2184 each one). Considering that each LED
will share 3.33__% of the range, the error is not considered.

In the matrix style, just use a table of 30 bytes size, each one
with the 5x6 bit combination, example, the entry #28 will have
contents 54h, the 5.h converted to binary will select the column
#5 for the source side, while the .4h converted to binary will
select row #4 for the sink (ground), and the LED #28 at the
matrix position 5.4 will light.

For sure you use several other solutions as 4 x 8 bits parallel
registers, or 4 x 8 shift registers when you control to shift up
or down, and other crazy ideas.

-----------------------

Eric Oliver wrote:
{Quote hidden}

1999\02\22@041236 by Wagner Lipnharski

picon face
Eric, just a question:
Are those leds electrically isolated in a way you can control
them in a matrix form?  or they have a common polarity pin side?

1) matrix 6 x 5 (11 bits) can be formed to light just one led at time,
  it needs enough pull up at the leds anodes side (source) and
  enough sink current at the catodes side.  There are chips
  available to do it easily.

2) common polarity allow you to use a 74HCT45 for example (bcd to
  decimal decoder - open collector) to select one led from ten,
  sink the catode, using 4 bits combination 0-9 (ignore A-F),
  with other 3 bits you can drive FET transistors that will
  drive which one of the 3 bars of 10 leds will receive power
  (source at anodes).  Again, there are plenty of other chips.

The conversion from 16 bits to matrix selection (65536 -> 5x6)
or (65536 --> 4x3), it is just a common division or logic selection.

As 10 or 30 does not make part of 2^n dimension, it will create
gaps and errors to divide it logically using some bits from the
counter to select rows and columns.  For example, you could use
this logical selection, with errors:  Using the counter high order
first 4 bits (xxxx .... .... ....) to select the bar;

0,1,2,3,4,5 = Green   <--- extra position
6,7,8,9,A   = Yellow (each x800h selects a LED)
B,C,D,E,F   = Red    (each x800h selects a LED)

The Green bar can't share the same idea to use x800h to select a
LED, so it doesn't work well.

Dividing the value 0-65535 by 2184 you will have a result from
0 to 30 (0-1Eh), convert to decimal, use the high nibble to select
the bar (in the common anode or cathode possibility), and the low
nibble to select the led (via the 74HCT145 for example).  Here the
error is very small and the most accumulated error will appear at
the last led #30 that will light earlier 0.023% than expected,
because (2184x30)/65535 = 0.99977, and will hold 16 counts more
than the other LEDS (2184 each one). Considering that each LED
will share 3.33__% of the range, the error is not considered.

In the matrix style, just use a table of 30 bytes size, each one
with the 5x6 bit combination, example, the entry #28 will have
contents 54h, the 5.h converted to binary will select the column
#5 for the source side, while the .4h converted to binary will
select row #4 for the sink (ground), and the LED #28 at the
matrix position 5.4 will light.

For sure you can use several other solutions as 4 x 8 bits parallel
registers, or 4 x 8 shift registers when you control to shift up
or down, and other crazy ideas.

-------------------
Wagner Lipnharski
http://www.ustr.net
-------------------

Eric Oliver wrote:
{Quote hidden}

1999\02\22@150047 by paulb

flavicon
face
Mark Willis wrote:

> So to map 0..65535 to 0..30 LEDs, you want to maybe multiply by 15
> then divide (by right shifting) by 32768, with a little rounding
> that'll work out right.

> (Makes sense to divide by 256 first, i.e. throw out the low byte, then
> do a 16-bit multiply by 15, then add a rounding factor & finally
> divide by 128 again, right?)

 Well, while this is probably sufficiently accurate, I'd prefer to
start by multiplying by 15/16 in one single operation, keeping at least
12 bits of accuracy.  This is done by dividing by 16 (swapf operations)
and subtracting from the original.  A shift or two and you have your
six-bit index to the LEDs.

Wagner Lipnharski wrote:

> 1) matrix 6 x 5 (11 bits) can be formed to light just one led at time,
>    it needs enough pull up at the leds anodes side (source) and
>    enough sink current at the cathodes side.

 Of course, if you use 8 by 4 (12 bits) the wiring gets a tad more
complex but the software becomes dead easy.  OTOH, these layouts can be
achieved using 6 (6 x 5) and 8 (8 x 4) pins respectively of a PIC by
using each pin for both anode and cathode drive.

 Further, (5 or 4) NPN buffer transistors can be used to provide a
20mA per LED multiplex "bar" rather than "dot" display.

> Dividing the value 0-65535 by 2184 you will have a result from
> 0 to 30 (0-1Eh),

 I'm not even going to think about that calculation!
--
 Cheers,
       Paul B.

1999\02\22@174602 by Regulus Berdin

picon face
Gerhard Fiedler wrote:
> you don't need a 30bit number just because you want to drive a 30led bar :)
> all you need is a number from 0 to 30, which boils down to a simple
> division, if your representation is linear. 0->0%->no led, 65535->100%->all
> (30) leds. that's 30 intervals for 65535, hence each interval
> (corresponding to one led more) is 65535/30... you divide your load by this
> number, and get the number of leds to switch on.


; 1-30 to 30 leds
;input:   bin
;output:  led1,led2,led3,led4

convert:
       clrf    led1
       clrf    led2
       clrf    led3
       clrf    led4
       incf    bin,f
loop:
       decfsz  bin,f           ;do not include 0
        goto   $+2
       return

       decf    bin,f
       setc                    ;turn on led
       rlf     led4,f
       rlf     led3,f
       rlf     led2,f
       rlf     led1,f
       goto    loop


regards,
Reggie

1999\02\22@203314 by Regulus Berdin

picon face
Hi all,

Regulus Berdin wrote:
{Quote hidden}

I have another solution, using the fact that 1-30 bar is equal to 2^y -
1.  This routine is isochronous and faster on some values than the
above.

Here goes (untested):

convert:
       clrf    a1
       clrf    a2
       clrf    a3
       clrf    a4

       movlw   a4              ;2^bin
       btfsc   bin,3
        movlw  a3
       btfsc   bin,4
        movlw  a1
       movwf   FSR

       movlw   B'00000001'
       btfsc   bin,1
        movlw  B'00000100'
       movwf   INDF

       btfsc   bin,0
        addwf  INDF,f

       btfsc   bin,2
        swapf  INDF,f

       movlw   1               ;subtract by 1
       subwf   a4,f
       skpc
        subwf  a3,f
       skpc
        subwf  a2,f
       skpc
        subwf  a1,f

regards,
Reggie

1999\02\23@004820 by Eric Oliver

flavicon
face
Whack !! Ouch !! Gotta stop whacking my forehead like that. Ok, that's
easy. So if my load measurement is say 45000 then I need the first (
65535/30 = ~2184, 45000/2184 = ~21 ) 21 LEDS lit. Shift out 9 zeros then 21
ones. I guess I was making a mountain out of a mole hill !!


Regarding the Borland Forum, I enjoyed being a part of that community and I
missed it when it changed.  The members of this list seem to share the same
spirit and I'm glad to be a part of it.

Eric

{Original Message removed}

1999\02\23@134438 by Wagner Lipnharski

picon face
Eric Oliver wrote:

> Whack !! Ouch !! Gotta stop whacking my forehead like that. Ok, that's
> easy. So if my load measurement is say 45000 then I need the first (
> 65535/30 = ~2184, 45000/2184 = ~21 ) 21 LEDS lit. Shift out 9 zeros then 21
> ones. I guess I was making a mountain out of a mole hill !!

Oh well, that's an easy solution, but shift out to where?

Unless the LED modules have a shift register that accept serial (data/clock)
and with a "borrow" output allowing to cascade several modules.

You can also use a fpga logically programmed to convert 8 bits (the high
order counter byte) into a 5x6 matrix... or 3x10... or something else, and
never needing to use a microcontroller, oscillator, nothing else.

Wagner

1999\02\23@150822 by Marc

flavicon
face
> You can also use a fpga logically programmed to convert 8 bits (the high
> order counter byte) into a 5x6 matrix... or 3x10... or something else, and
> never needing to use a microcontroller, oscillator, nothing else.

And yes, if you're really keen on making it complicated, you can program the FPG
A
to implement a 4 bit microcontroller core with a small program to solve the
problem in "software"..  No need for micros then :-----)

1999\02\23@202928 by Regulus Berdin

picon face
Hi all,

I tried to test my code on MPLAB and found a bug on it.

>         btfsc   bin,4
>          movlw  a1       >>>>>> this should be 'addlw -2'
>         movwf   FSR

regards,
Reggie

--
e-mail: spam_OUTrberdinTakeThisOuTspambigfoot.com
ICQ#:   31651436
URL:    http://www.bigfoot.com/~rberdin

1999\02\23@231133 by Wagner Lipnharski

picon face
FPGA's are quite easy to program, it is fully software driven right now.
There are some programs that you enter the algoritm and it just give you the
programming file.  Remember the old PLD's ?  Basically it is the same,
with some more details. :)
Wagner.

Marc wrote:

> > You can also use a fpga logically programmed to convert 8 bits (the high
> > order counter byte) into a 5x6 matrix... or 3x10... or something else, and
> > never needing to use a microcontroller, oscillator, nothing else.
>
> And yes, if you're really keen on making it complicated, you can program the F
PGA
> to implement a 4 bit microcontroller core with a small program to solve the
> problem in "software"..  No need for micros then :-----)

1999\02\23@233621 by Eric Oliver

flavicon
face
Wagner,

In my original question, I referred to using the LED modules with cascaded
595s, but that was just an example.  I ask the question .. well .. because
I didn't know the answer <g>.  I have read every response and was actually
able to follow some of them :).  I have often seen references to FPGAs and
PGAs and wondered about their use.  How are these devices used ? Do you use
some type of programmer to program them to perform a specific function ?

Eric

{Original Message removed}

1999\02\24@003527 by Wagner Lipnharski

picon face
Yes, we used pal's and pld's and then pga's just to reduce board count,
mainly in microprocessor/microcontroller address decoding and device
selection, as well, other simple functions as to substitute the address
demultiplex (373/573) and incorporate few other decodings in the same
package.  By this way we can exchange 3 or 4 chips by only one.

Today's low cost for microcontrollers, made almost obsolete those nice
little hardware pieces, even with the incorporation of Flash code memories.

But they are really fast and highly functional, turning design a piece of cake.

Some softwares around (Xilinx manufacturer) allows you to produce the
programming file in almost no time.

Remember the old DOS Benchmark for electronics?  The one that allow you
to simulate and connect logic gates and attach instruments as scope, logic
analyzer and things for the "digital part"?  It has a module that can convert
your electronic design in an bolean algoritm and vice-versa, very nice to
create the logic for the old PAL devices.

The nice use for those devices are for a complex black box that have several
input and output pins.  There is a logic in between, that follows its
programming,
so you can think that a 74HCT47 (bcd to 7 segment decoder) is a kind of
programmed pal and nobody never knew.

Wagner.

Eric Oliver wrote:

> Wagner,
>
> In my original question, I referred to using the LED modules with cascaded
> 595s, but that was just an example.  I ask the question .. well .. because
> I didn't know the answer <g>.  I have read every response and was actually
> able to follow some of them :).  I have often seen references to FPGAs and
> PGAs and wondered about their use.  How are these devices used ? Do you use
> some type of programmer to program them to perform a specific function ?
> Eric

1999\02\24@032928 by Graeme Smith

flavicon
face
GRAEME SMITH                         email: .....grysmithKILLspamspam@spam@freenet.edmonton.ab.ca
YMCA Edmonton

Address has changed with little warning!
(I moved across the hall! :) )

Email will remain constant... at least for now.


On Tue, 23 Feb 1999, Eric Oliver wrote:

{Quote hidden}

Essentially, all Logic arrays are similar in construction, just like roms
;) you have different technologies to impliment them, but they all consist
of arrays of AND, OR, and NOT logic, implimented in some array that lets
you use one of two different types of coding. (A+B)*(C+D) or (A*B)+(C*D)
demorganizing these formulas converts them between the two types, (these
samples are NOT equivalent, but you can essentially convert between the
two different types at will.

As they get more sophisticated, they add registers, to the mix, to give
you more options, and the newest ones are ISP (In System Programmable)
using serial type busses similar to the pic busses, etc.

The fpga's etc, tend to require a full featured programmer, but
programming can be pretty dirty if you try to do it to a flat pack.

The fine pitch leads, tend to be somewhat difficult to keep in line.

Obviously if you want to impliment a MPU unit in a FPGA you are going
to have to code all the half adders etc, but these days they have macro
code libraries that can make it easier.

You code them using a compiler just like a cpu, except that your
statements are based on logical states, like a state machine.

I have a Lattice ISP kit, but I haven't gotten around to trying to program
one yet.... ;) to busy trying to write a sequencer for the '54....

                       GREY

More... (looser matching)
- Last day of these posts
- In 1999 , 2000 only
- Today
- New search...