Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 28, 2024, 11:40:28 23:40


Login with username, password and session length


Pages: [1]
Print
Author Topic: Help needed for 16x2 LCD bargraph  (Read 15639 times)
0 Members and 1 Guest are viewing this topic.
leaveme
Junior Member
**
Offline Offline

Posts: 93

Thank You
-Given: 38
-Receive: 15


« on: July 27, 2013, 06:32:52 18:32 »

I have a bargraph in CCS-C with PIC MCU and it works. However it (randomly) leaves some of the bars behind if the value drops very quickly. Anybody faced this problem?

Code:
||||||||||||||||||||||||||||||||||||||||  <--full bar

|||||||      |                     |      <--two bars left behind

Bargraph functions (CCS-C):
Code:
//User defined characters are 5x7 but remember the cursor on 8 
void init_user_chars(void) {
   int8 i;
   //Setup an array of special characters (CGRAM) to form the bars
   const char user_char[32] = {
                          // char 0x00 no bar
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                          // char 0x01 left vertical line of bar
                          0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
                          // char 0x02 two units of bar
                          0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00,
                          // char 0x03 three units of bar (full bar)
                          0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00
                          };

   lcd_send_byte(0,64); // Sets ram address to beginning of CGRAM area

   for (i=0; i<32;i++)  // fill in CGRAM with the data from array above.
      lcd_send_byte(1,user_char[i]);

   lcd_gotoxy(1,1); // Resets address to top line / position 1
}

void bargraph(BYTE percent) {
   int Bars;       //Number of full ||| bars to draw.
   int Balance;    //Balance left after all |||s are drawn.
   int i;          //counting variable
   
   Bars = percent/3;        // how many full bars to print?
   Balance = percent%3;     // are partial bars required?

   lcd_gotoxy(1,2);           // go to beginning of line 2
   for (i=0; i<Bars; i++)
      lcd_send_byte(1,0x03);  // print the bars
   
   switch (Balance) {
      case 0: lcd_send_byte(1, 0x00);
              break;
      case 1: lcd_send_byte(1, 0x01);
              break;
      case 2: lcd_send_byte(1, 0x02);
              break;
   }

}
Logged
pablo2048
Active Member
***
Offline Offline

Posts: 113

Thank You
-Given: 136
-Receive: 86


« Reply #1 on: July 27, 2013, 08:09:54 20:09 »

It seems that the fragments are left only if value drops down - my suggestion is to draw whole bar filling unused elements by 0x20...
Logged
Gallymimu
Hero Member
*****
Offline Offline

Posts: 704

Thank You
-Given: 152
-Receive: 214


« Reply #2 on: July 27, 2013, 09:20:50 21:20 »

It's hard to tell for sure, but I bet you are expecting the program to pass through every draw state of each bar while the value is dropping,  If you value is 100% and then instantaneously drops to 10% does your code write any of the bars in between?  If not, depending on your timing, it is going to skip all the bars in between.

The suggestion to write everything or clear the display might work, or it might add annoying flicker requiring more careful management of cleared areas.  I'm a little surprised you wouldn't have the same problem when changing from a small value to a large on instantly causing blank spots to be left behind.

you only posted the bar functions and without the rest of the program there isn't anyway to know what is really going on.
Logged
towlerg
Senior Member
****
Offline Offline

Posts: 263

Thank You
-Given: 474
-Receive: 104

What is this for?


« Reply #3 on: July 27, 2013, 09:51:31 21:51 »

Hows about, remember the previous value and if its changed by more than one, fill in the missing states.
Logged

Win 7 Ult x64 SP1 on HP2570p
leaveme
Junior Member
**
Offline Offline

Posts: 93

Thank You
-Given: 38
-Receive: 15


« Reply #4 on: July 28, 2013, 06:28:24 06:28 »

@Gallymimu:
Left over problem only occures if the value drops largely and quickly. Bargraph function is used with the flex_lcd driver and calling it very simple.

Code:
while(1) {
   ...
   ...
   level = (int8)(some_dynamic_data/20);   //Calculate full scale for bar   

   if(level < 1) level = 1;       //keep minimum value
   if(level > 51) level = 51;   //protect accidental over value
   delay_ms(20);
   bargraph(level);                   //Print line 2 with the level-bar
}


It seems that the fragments are left only if value drops down - my suggestion is to draw whole bar filling unused elements by 0x20...
Do you mind to explain a bit. I tried filling empty spaces in unused area. Left over problem is away, however the bars have a bluring effect.

Code:
   if(Bars < 16) {
      no_bar = Bars + 1;         //get the 1st position for empty write
      for (j=1; j<Bars; j++) {
         lcd_gotoxy(no_bar,2);      //go to the location of line 2
         lcd_putc(0x00);            //print empty space in unused area
         no_bar++;
      }
   }
Logged
Gallymimu
Hero Member
*****
Offline Offline

Posts: 704

Thank You
-Given: 152
-Receive: 214


« Reply #5 on: July 28, 2013, 07:32:36 07:32 »

okay so yeah I'm pretty sure your problem is what I said.

Think about it, you have a full bar graph at level 51 then you change the input value to 9 instantly, is there anything in your code to clear all the bars between the the two different levels?

It makes complete sense that if you change levels quickly that you'll miss clearing bars.

and yeah it's going to cause redraw issues or blurring as you say if you rewrite stuff all the time i.e. writing to the unused space.

it might be wise to write something a little more sophisticated that looks at the current and previous bar position and either clears everything in between OR only allows the draw routine to change up to one bar per redraw.

Posted on: July 28, 2013, 08:22:18 08:22 - Automerged

you really should only draw bars that change.  It will improve the smoothness and avoid blurring issues.

I'd probably only add or remove bars one at a time.  You could look at your level each draw cycle and decide if you need to increment or decrement one bar, if you don't need to increment or decrement a whole bar then draw the appropriate partial bar.  This will give a slower (not likely visible) but smoother update.

or you could just increment/decrement by partial bars which would be super smooth.
Logged
LithiumOverdosE
Senior Member
****
Offline Offline

Posts: 361

Thank You
-Given: 383
-Receive: 588


« Reply #6 on: July 28, 2013, 10:03:10 10:03 »

Had the same problem same time ago.

1. Ensure there is enough delay between bar graph updates in order for LCD to properly execute command. You can experiment with 1 -10 ms as it mostly depends on particular HD44780 version used.

2. You can also use LCD R/W pin to detect state of LCD and update only when it's ready to do accept new update. In this way you can maximise you bar graph refresh rate without risking blurring or weird effects. This works only if you use LCD lib or procedures that watch state of pin R/W pin on LCD (Ready / Busy flag).
  
3. Also make sure that you draw entire bar with every update. Gallymimu is correct in suggesting that you really should fill empty spaces to the max value of bar. While it does prevents stray characters from being displayed it also adds additional time necessary for drawing of entire bar.

Consider that with 16 character LCD worst case means 16 * 10 ms = 160 ms between entire bar updates (if bar uses entire width of LCD, if not it is even better). That's ~7 Hz refreshing rate which is quite good because with the higher update rate it becomes harder for human to read it properly if there are fast changes. You could use more reasonable (lower) refresh rate by averaging of samples and present them on the screen or by calculating peak (holder) value and represent it on the screen with a single bar or some other symbol. Changing only final one or two character blocks will of course allow for faster updates but refresh frequency will vary with the bigger changes of represented values which means bar graph will look confusing and its behaviour erratic. Drawing entire bar every time provides for controlled and stable refresh rate which directly translated to readability and thus usability.

For the sake of readability one should calculate in the empty spaces between character blocks as well and treat them like one bar graph step although it presents ambiguity in the sense of readability.
 
Highest resolution and accuracy of bar graph I saw was implementation of ELM-ChaN (same guy that programmed FatFS and Petite FatFS). He basically recalculates shape of block character every time so it can intuitively show values in between two character blocks on LCD. The algorithm is fast and IMO elegant. I also tried this procedure and it works quite well in XC8 and MikroC. Although such bar graph upper value slanted edge seems weird at first(slanted) it does solve problem of representing values between two character blocks of LCD.


Hope this helps. Wink
 
« Last Edit: July 28, 2013, 10:15:25 10:15 by LithiumOverdosE » Logged
leaveme
Junior Member
**
Offline Offline

Posts: 93

Thank You
-Given: 38
-Receive: 15


« Reply #7 on: July 28, 2013, 12:46:32 12:46 »

Thanks buddy.

@ LithiumOverdosE:

By any chance do you remember ELM-ChaN's project or do you mind to share your XC8 or MikroC code?
It may be a great  help.
Logged
towlerg
Senior Member
****
Offline Offline

Posts: 263

Thank You
-Given: 474
-Receive: 104

What is this for?


« Reply #8 on: July 28, 2013, 02:37:05 14:37 »

@leaveme

Gallymimu nailed it.
Quote
I'd probably only add or remove bars one at a time.  You could look at your level each draw cycle and decide if you need to increment or decrement one bar, if you don't need to increment or decrement a whole bar then draw the appropriate partial bar.  This will give a slower (not likely visible) but smoother update.
Logged

Win 7 Ult x64 SP1 on HP2570p
LithiumOverdosE
Senior Member
****
Offline Offline

Posts: 361

Thank You
-Given: 383
-Receive: 588


« Reply #9 on: July 28, 2013, 07:41:23 19:41 »

By any chance do you remember ELM-ChaN's project or do you mind to share your XC8 or MikroC code?

I don't have my code readily available at this location. In a few weeks I should be back and will take a look at it if I remember. 

As for Elm-chan one example (IIRC he used same procedure in several projects) is here. There is source in C that can be easily ported to other compilers.
http://elm-chan.org/works/ddm/report_e.html
Logged
leaveme
Junior Member
**
Offline Offline

Posts: 93

Thank You
-Given: 38
-Receive: 15


« Reply #10 on: July 29, 2013, 06:24:12 06:24 »

Thanks guys for all your help. I finally got it working.

What I did is, I draw the total bars (including solid and partial) at 1st step and remember the number. At 2nd step, I draw the spaces in unused cell (only) if the number remains same. It worked and no bluring!  Grin
Logged
LithiumOverdosE
Senior Member
****
Offline Offline

Posts: 361

Thank You
-Given: 383
-Receive: 588


« Reply #11 on: July 29, 2013, 10:26:19 10:26 »

At 2nd step, I draw the spaces in unused cell (only) if the number remains same.

I must admit I don't really understand your description...  Huh
Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC