Go Down

Topic: Smooth LCD bargraph meters. (Read 7936 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