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;
//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
}