LCD voltmeter

A simple and nice to use LCD voltmeter with resetable min max function.


/*
single channel voltmeter
range 0 to 5 Volts in 1023 steps
min max recorder resetable with pushbutton
LCD display driven in "4 bits" mode 
R/W operation is not used; LCD pin 5 must be connected to ground
Reset button (optional) between Arduino's digital port 6 and ground
Analog signal shall be connected to Arduino's analog port 0

no need for additional libraries

no rights, no warranty, no claim just fun
didier longueville, december 2007
*/
// hardware related constants
#define analogPin 0
#define resetPin 6
#define ledPin 13
// lcd related constants
#define nbrCharPerLine 16 // update depending on LCD
                          // must be  at least 16 characters per line
#define nbrLines 2 // must be 2 lines at least
#define left 0
#define right 1
#define invisible 0
#define visible 1

// declare variables
int RS = 7; // registry select LCD pin 4
int EN = 8; // enable LCD pin 6
int DB[] = {9,10,11,12}; // data bits LCD pins 11, 12, 13 and 14
char stringBuffer[nbrCharPerLine + 1]; // this is the working string buffer
int analogValueMax = 0;
int analogValueMin = 1023;

void setup (void) {
  // Serial.begin(9600);
  for (int i = 7;i <= 13;i++) {
    pinMode(i,OUTPUT);
    digitalWrite(i,LOW);
  }
  pinMode(resetPin,INPUT); // define reset pin
  digitalWrite(resetPin, HIGH); // turn on pullup resistor
  LcdInitialize(); // Initialize lcd
  LcdUnderlineCursor(invisible); // hide underline cursor
}

void loop (void) {
  // check if the reset button has been pushed (quick and dirty)
  if(digitalRead(resetPin) == LOW) {
     // reset variables
    analogValueMin = 1023;
    analogValueMax = 0;
    // display status
    BufferClear(); // clear buffer
    //                       1234567890123456
    BufferInsertStringValue("min   now   max ",1);
    LcdSendString(1); 
    BufferClear(); // clear buffer
    //                       1234567890123456
    BufferInsertStringValue("-.--  -.--  -.--",1);
    LcdSendString(2); 
    delay (1000); // time to read
  }
  int analogValue=analogRead(analogPin);
  analogValueMin = min(analogValue,analogValueMin); // record min value
  analogValueMax = max(analogValue,analogValueMax); // record max value
  BufferClear(); // clear buffer
  //                       1234567890123456
  BufferInsertStringValue("min   now   max ",1);
  LcdSendString(1); // display converted value on line 1
  BufferClear(); // clear buffer
  //                       1234567890123456
  BufferInsertStringValue(" .     .     .  ",1);
  BufferInsertNumValue(analogValueMin,5,2,2);
  BufferInsertNumValue(analogValue,5,2,8);
  BufferInsertNumValue(analogValueMax,5,2,14);
  LcdSendString(2); // display converted value on line 2
  // blink status led   
  LedSendPulse(500); 
}

/*
Lcd related functions:
  LcdClearScreen
  LcdCursorHome
  LcdDisplay
  LcdInitialize
  LcdMoveCursor
  LcdScrollDisplay
  LcdSendBits
  LcdSendByte
  LcdSetLine
  LcdUnderlineCursor
*/

void LcdClearScreen() {
  LcdSendCommand(B00000001,8); // 0x01
}

void LcdCursorHome() {
  LcdSendCommand(B00000010,8); // 0x02
}

void LcdDisplay(boolean status) {
  if (status) {
    LcdSendCommand(B00001100,8); // 0x0C Restore the display (with cursor hidden) 
  }
  else {
    LcdSendCommand(B00001000,8); // 0x08 Blank the display (without clearing)    
  }
}

void LcdInitialize() {
  delay(40); // specification says > 30ms after power on
  // function set
  LcdSendCommand(B0010,4); // 0x2
  LcdSendCommand(B00101000,8); // 0x28
  delayMicroseconds(50); // specification says > 39�s 
  // display on/off control
  LcdSendCommand(B00001110,8); // 0x0E
  delayMicroseconds(50); // specification says > 39�s 
  // clear display
  LcdSendCommand(B00000001,8); // 0x01
  delay(2); // specification says > 1.53ms 
  // entry mode set
  LcdSendCommand(B00000110,8); // 0x06
  delay(2); //  
}

void LcdMoveCursor(boolean dir, int steps) {
  for (int j = 1;j <= steps;j++) {
    if (dir) {
      LcdSendCommand(B00010100,8); // 0x14
    }
    else {
      LcdSendCommand(B00010000,8);  // 0x10  
    }
  }
}

void LcdScrollDisplay(boolean dir, int steps,int pause) {
  for (int j = 1;j <= steps;j++) {
    if (dir) {
      LcdSendCommand(B00011110,8); // 0x1E
    }
    else {
      LcdSendCommand(B00011000,8); // 0x18
    }
    delay(pause);
  }
}

// set bits on Lcd and trigger enable pulse
void LcdSendBits(int value){
  digitalWrite(EN,HIGH); 
  delayMicroseconds(5);  // pause 1.4 �s according to datasheet 
  for (int i = 0;i <= 3;i++) {
    digitalWrite(i + 9,value & 01); // set bit value
    value >>= 1; // shift bits
  }
  digitalWrite(EN,LOW); // toggle enable line transfer bits 
  delayMicroseconds(5);  // pause 1.4 �s according to datasheet 
}

// send one byte onto LCD
void LcdSendByte(int value) {
  constrain(value,32,126); // value shall be no less than 32 and no more than 126 (printable characters)
  digitalWrite(RS,HIGH);
  LcdSendBits(value >> 4); // msw
  LcdSendBits(value); // lsw
}

// send command to LCD display
void LcdSendCommand(int value,int nbrBits) {
  digitalWrite(RS,LOW);
  if (nbrBits == 8) {
    LcdSendBits(value >> 4); // msb
  }
  LcdSendBits(value); // lsb
}

void LcdSendString(int lineIndex){
  constrain(lineIndex,1,nbrLines); //line index shall be no less than 1 and no more than nbrLines
  if (lineIndex == 1) {
    LcdSendCommand(B10000000,8); // 0x80
  }
  else if (lineIndex == 2) {
    LcdSendCommand(B11000000,8); // 0xC0
  }
  // write working string buffer content onto LCD
  for (int i = 0;i <= nbrCharPerLine;i++) {
    LcdSendByte(stringBuffer[i]);    
  }
}

void LcdSetLine(int lineIndex){
  constrain(lineIndex,1,nbrLines); //line index shall be no less than 1 and no more than nbrLines
  if (lineIndex == 1) {
    LcdSendCommand(B10000000,8); // 0x80
  }
  else if (lineIndex == 2) {
    LcdSendCommand(B11000000,8); // 0xC0
  }
}

void LcdUnderlineCursor(boolean status) {
  if (status) {
    LcdSendCommand(B00001110,8); // 0x0E  
  }
  else {
    LcdSendCommand(B00001100,8); // 0x0C
  }
}

/* 
led related functions:
  LedSendPulse
*/
// pulseDelay value is equal to the total pulsing time
void LedSendPulse(int pulseDelay){
  digitalWrite(ledPin,HIGH);
  delay(pulseDelay/2);
  digitalWrite(ledPin,LOW);
  delay(pulseDelay/2);  
}

/*
working string buffer functions:
  BufferClear
  BufferInsertNumValue
  BufferInsertStringValue
*/

// clears the content of the working string buffer (global variable)
void BufferClear (){
  for (int i = 1;i <= nbrCharPerLine;i++){
    stringBuffer[i - 1] = 32; // blank buffer content with space characters
  }
}

// insert converted float in the working string buffer (global variable)
void BufferInsertNumValue (int digitalValue,int fullScaleValue,int decimalPlaces,int decimalSeparatorPosition) {
  unsigned long integerValue=((unsigned long)( digitalValue * fullScaleValue) * PowerInteger(10,decimalPlaces)) / 1023;
  int remainder = 0;
  stringBuffer[decimalSeparatorPosition - 1] = 46;
  // decimals
  for (int i = 1;i <= decimalPlaces;i++){
    int asciiCode = (integerValue % 10) + 48;
    stringBuffer[decimalSeparatorPosition + decimalPlaces - i] = asciiCode;
    integerValue/=10;
  }  
  // integers
  int i = 0;
  do {
    i++;
    int asciiCode = (integerValue % 10) + 48;
    stringBuffer[decimalSeparatorPosition - 1 - i] = asciiCode;
    integerValue /= 10;
  } while (integerValue != 0);
}


// update the working string buffer (global variable)
// startingPosition is base 1
void BufferInsertStringValue(char * s,int startingPosition) {
  int stringLength=strlen(s)-1;
  for (int i = 0;i <= stringLength;i++) {
    stringBuffer[startingPosition + i - 1] = s[i];
  }
}

/*
general purpose functions:
  PowerInteger
*/

int PowerInteger(int mantissa,int exponent){
  int result; // declare result variable
  if (exponent == 0) {
    result = 1;
    }
  else {
    result=mantissa;
    for (int i = 2;i <= exponent;i++) {
      result *= mantissa;
    }
  }
  return result;
}

Share