Pages: [1]   Go Down
Author Topic: Smooth LCD bargraph meters.  (Read 4775 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
Karma: 0
Posts: 107
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well it took a while, But i managed to get arduino to show smooth bargraph meters on a standard hitachi hd44780 LCD module

It was difficult because I managed to read a lot of old information which was out of date. First of all i was using the LCD4bit library which at one time was needed for 4 bit mode, it is not needed any more. the standard LCDlibrary that comes with arduino IDE works with 4 bit mode just fine.

Then there is a bit of confusion about how to do the custom characters for the LCD, the way i have done it works, but there is a better way that does not use "uint8_t" (whatever that is) but it does not affect the speed of the code and it works, so im going to stick with it for now.

This will display 4 readings on analog 0,1,2 and 3 they are split in to 4 bargraphs sections each with a number indicator and a 7 segment bargraph.

The empty space between the characters also counts as a reading, and there is a nub on the leading edge of the bar which appears to go "behind" the empty space. 7 segments gives 41 possible readings for the 1024 possible values on the 10 bit analog to digital inputs.

if you adapted it to use all 16 segments, say for a stereo meter you could get 95 segment resolution.

This code might be too big for a 4k arduino then just get rid of the stuff i have in there for the interrupts (not used for the LCD at all) and i am sure there are plenty of optimizations as well, like using arrays.

This is just part of another project but since i had a bit of trouble finding everything and putting it together i thought i would post it.

It is by no means optimized, but even so the 4 meters move as fast as the LCD module can display. and nice and smooth.

There is also an interrupt triggered by pin 2 you can use that to do what you like if you need one, just dont use delay and millis inside interrupt routine

// include the library code:
 #include <LiquidCrystal.h>

 // these constants won't change.  But you can change the size of
 // your LCD using them:
 const int numRows = 2;
 const int numCols = 16;
 int T1 = 10000; //interrupt delays, not for LCD meter
 const int LEDpin1=3; //Interrupt timed outputs, not for LCD code
const int LEDpin2=4; //
const int LEDpin3=5; //
const int LEDpin4=6; //
const int V1pin=0;
const int V2pin=1;
const int V3pin=2;
const int V4pin=3;
int pin13 = 0; //for the interrupt, not LCD code
 int V1;
 int V2;
 int V3;
 int V4;
 int val1;
 int val2;
 int val3;
 int val4;
   uint8_t custom_0[8] = { 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00}; //blank
   uint8_t custom_1[8] = { 0x10, 0x10, 0x18, 0x18, 0x18, 0x10, 0x10, 0x00}; //1line
   uint8_t custom_2[8] = { 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x00}; //2line
   uint8_t custom_3[8] = { 0x1C, 0x1C, 0x1e, 0x1e, 0x1e, 0x1C, 0x1C, 0x00}; //3line
   uint8_t custom_4[8] = { 0x1E, 0x1E, 0x1f, 0x1f, 0x1f, 0x1E, 0x1E, 0x00}; //4line
   uint8_t custom_5[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00}; //5line
  uint8_t custom_6[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00}; //6line redundant.
 // initialize the library with the numbers of the interface pins
 LiquidCrystal lcd(11, 12, 7, 8, 9, 10); //LCD pins on arduino please see liquidcrystal.h and arduino LCD wiring examples


 void setup() {
    pinMode(LEDpin1, OUTPUT); //Interrupt triggered outputs
    pinMode(LEDpin2, OUTPUT);  //not used in LCD code
    pinMode(LEDpin3, OUTPUT);
    pinMode(LEDpin4, OUTPUT);
   // set up the LCD's number of rows and columns:
   attachInterrupt(0, blink, RISING); //interrupt not used for LCD code
   lcd.begin(numRows, numCols);
     lcd.createChar(0, custom_0); //send the custom characters to the LCD
  lcd.createChar(1, custom_1);
  lcd.createChar(2, custom_2);
  lcd.createChar(3, custom_3);
  lcd.createChar(4, custom_4);
  lcd.createChar(5, custom_5);
  lcd.createChar(6, custom_6);
  //static numbers on LCD changes if you change your meter.
  lcd.print ("1       2");  //for instance "L" for left chan
  lcd.setCursor(0,1) ;
  lcd.print ("3       4");  //and "r" for right chan


 void loop() {
   val1 = analogRead(V1pin); //read analog inputs
   val2 = analogRead(V2pin);
   val3 = analogRead(V3pin);
   val4 = analogRead(V4pin);
   V1 = (val1/25); //change divider depending on how many segments in a meter
   V2 = (val2/25);
   V3 = (val3/25);
   V4 = (val4/25);
      int vom1 = (V1 / 6);  //divide reading for solid blocks
      int rem1 =  (V1 % 6 ); //get modulo for remainder
      int vom2 = (V2 / 6);
      int rem2 =  (V2 % 6 );
      int vom3 = (V3 / 6);
      int rem3 =  (V3 % 6 );
      int vom4 = (V4 / 6);
      int rem4 =  (V4 % 6 );

         lcd.setCursor(1,0);       //move cursor to first meter
         for (int i=0; i<vom1;i++) {
         lcd.print(5,BYTE);  //print solid blocks
         lcd.print(rem1,BYTE); //print the remainder which is meter segments within character
          for (int i=(vom1 + 1); i<7; i ++) {
          lcd.print(" "); //blank spaces after so there is no leftover mess after fast moving meter
           lcd.setCursor(9,0);       //move cursor to second meter
         for (int i=0; i<vom2;i++) {
         for (int i=(vom2 + 1); i<7; i ++) {
          lcd.print(" ");
            lcd.setCursor(1,1);       //move cursor to 3rd meter
         for (int i=0; i<vom3;i++) {
          for (int i=(vom3 + 1); i<7; i ++) {
          lcd.print(" ");
            lcd.setCursor(9,1);     //move cursor to 4th meter  
         for (int i=0; i<vom4;i++) {
         for (int i=(vom4 + 1); i<7; i ++) {
          lcd.print(" ");
         delay(10);  //delay changed to suit your taste, if using rapid interrupt, then delete.
 //interrupt is not used for LCD meter  
void blink()  //needs to be fixed. delays eat all the cycles
   digitalWrite(LEDpin1, HIGH);        
   digitalWrite(LEDpin2, HIGH);          
   digitalWrite(LEDpin3, HIGH);  
   digitalWrite(LEDpin4, HIGH);  
   digitalWrite(LEDpin1, LOW); //drop all to 0
   digitalWrite(LEDpin2, LOW);
   digitalWrite(LEDpin3, LOW);
   digitalWrite(LEDpin4, LOW);  
      digitalWrite(13,pin13 ? HIGH : LOW);
   pin13=!pin13; //temp indicator of interrupt
« Last Edit: January 22, 2010, 10:15:57 pm by DeFex » Logged

Offline Offline
Sr. Member
Karma: 3
Posts: 260
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

done already  smiley-wink

check this:

it can to smooth bars, smooth scrolling bars and big nums:


all with LCD4Bit  smiley

Offline Offline
Full Member
Karma: 0
Posts: 107
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thats excellent. shame i did not find it when searching , would have saved me a bit of work smiley

Offline Offline
Sr. Member
Karma: 0
Posts: 489
Arduino addicted
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It' a test?
Lamdba at 0 isn't a good sign smiley-grin

Pages: [1]   Go Up
Jump to: