Go Down

Topic: Smooth LCD bargraph meters. (Read 8413 times) previous topic - next topic

DeFex

Jan 23, 2010, 04:04 am Last Edit: Jan 23, 2010, 04:15 am by DeFex Reason: 1
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

Code: [Select]

// 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;
//CUSTOM LCD CHARACTERS
  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.setCursor(0,0);
 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++) {
        lcd.print(5,BYTE);
        }
        lcd.print(rem2,BYTE);
        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++) {
        lcd.print(5,BYTE);
        }
        lcd.print(rem3,BYTE);
         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++) {
        lcd.print(5,BYTE);
        }
        lcd.print(rem4,BYTE);
        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
{
  delayMicroseconds(T1);
 
  digitalWrite(LEDpin1, HIGH);        

  delayMicroseconds(T1);
 
  digitalWrite(LEDpin2, HIGH);          

  delayMicroseconds(T1);
 
  digitalWrite(LEDpin3, HIGH);  
 
  delayMicroseconds(T1);
   
  digitalWrite(LEDpin4, HIGH);  
   
  delayMicroseconds(T1);
   
  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

}

designer2k2

done already  ;)

check this: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1239996764

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

[media]http://www.youtube.com/watch?v=PuyfSF7vrHQ[/media]

all with LCD4Bit  :)
http://www.designer2k2.at

DeFex

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

NetWorm

It' a test?
Lamdba at 0 isn't a good sign :D

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy