Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

SparkFun SerLCD Interfacing (One Line Functions)

SfLCD2 is a LCD library that makes it easier for you to write programs that display text on the SparkFun SerLCD 16x2 character LCD.

There were several goals with this refactored version of the excellent work that has proceeded me (SparkFunSerLCD).

  • I wanted a version that had less code in the main loop.
  • Wanted it to truncate data that was too long.
  • Wanted one line functions for writing a full page, per line, or per character.
  • Because there appears to be a need for a delay when writing to the SerLCD, I organized the code to minimize places where delays were needed.
  • I moved the serial port to pin 7 because it has no special uses (as far as I can see).
  • Finally, I renamed the functions so that they all contain "SerLCD" in their names so that in a main loop, it will be obvious what they are manipulating.

As suggested previously, obtain and read this documentation from sparkfun: http://www.sparkfun.com/datasheets/LCD/SerLCD_V2_5.PDF

Code

Mostly I've added tons of comments into the code so cut and paste.\:

#include <SoftwareSerial.h>

// Uses the Sparkfun.com Serial Enabled 20x4 LCD 

// Exercises some of the commands available to the SerLCD
// Refactored and added some error checking.
// This builds upon all the excellent examples provided in:
// https://playground.arduino.cc/Learning/SparkFunSerLCD


//SerialLCD Functions

// clearSerLcd clears the screen
// backlightSerLcd sets percentage backlighting
// displaySerLcdScreen treats the entire screen as a page and fills it
// displaySerLcdLine writes to a single line
// displaySerLcdChar writes to a character on a single line

// See the datasheet for all the other commands this thing is capable of
// https://www.sparkfun.com/datasheets/LCD/SerLCD_V2_5.PDF

// Note all three display functions use strlen()
// strlen() is a standard C function to get the length of a string and although
// not mentioned in the Arduino docs, it is available in the programing environment.

//Physical connections
// 5V on SerLCD wired to 5V on Arduino
// GND on SerLCD wired to Gnd on Arduino
// RX on SerLCD wired to pin 7 on Arduino 
//   (appears that only pins 7 and 8 have no superpowers, so am using 7)

// SerialSoftware.h is used so that the "real" serial port on the Arduino is
// available for other functionality. Using SerialSoftware limits the bit rate to 
// 9600 bps which is fine because that is what SerLCD uses as default and
// no human can read at 9600 bps.

#define txPin 7

SoftwareSerial LCD = SoftwareSerial(0, txPin);
// since the LCD does not send data back to the Arduino, we should only define the txPin

void setup()
{
  pinMode(txPin, OUTPUT);
  LCD.begin(9600);
}


// delays in loop() are just there for demonstration purposes. 
// In real life you can remove them.
// The delays in the prints to the SerLCD appear to be needed. 

void loop() {
  // Example usage:
  clearSerLcd();
  backlightSerLcd(100);
  displaySerLcdLine(1, "Backlighting at 100%");
  delay(1000); 

  //Print text on each line
  displaySerLcdLine(1, "Line 1 is truncated because it is too long");
  delay(1000);
  displaySerLcdLine(2, "Line two");
  delay(1000);
  displaySerLcdLine(3, "Line three");
  delay(1000);
  displaySerLcdLine(4, "Line four");
  delay(1000);

  //print a character at the end of each line:
  displaySerLcdChar(1,20,'*');
  delay(1000);
  displaySerLcdChar(2,17,'-');
  displaySerLcdChar(2,18,'-');
  displaySerLcdChar(2,19,'>');
  displaySerLcdChar(2,20,'*');
  delay(1000);
  displaySerLcdChar(3,20,'*');
  delay(1000);
  displaySerLcdChar(4,20,'*');
  delay(1000);

  // alter the backlighting
  backlightSerLcd(50);
  displaySerLcdLine(1, "Backlighting at 50%");
  delay(2000);
  backlightSerLcd(0);
  displaySerLcdLine(1, "Backlighting off");
  delay(3000);

  // print full screen
  backlightSerLcd(50);
  displaySerLcdScreen("Haiku:              You've been watchingthe Serial LCD      perform many tricks.");
  delay(4000);
}


//SerialLCD Functions

// NOTE, None of the following functions use each other. If all you need is one function,
// like for example, writing lines (displaySerLcdLine), you can delete all the other 
// functions listed below to reduce the size of the code. They are not interdependent.

// displaySerLcdScreen("text for the entire screen")
// overwrites the entire screen, wraps the text as needed
// truncates after 80 characters
void displaySerLcdScreen(char *theText){
  int delayTime = 50;
  LCD.print(0xFE, BYTE);   // command flag
  delay(delayTime);
  LCD.print(128, BYTE);    // start position for line 1
  if (strlen(theText) < 80) {
    // less than 80 characters, print then and then 
    LCD.print(theText);
    // pad the rest of the line with spaces
    for (int i = strlen(theText); i < 80; i++) {
      LCD.print(" ");
    } 
  } 
  else {  
    // 80 or more characters, just print the first 80
    for (int i = 0; i < 80; i++) {
      LCD.print(theText[i]);
    }
  }
  delay(delayTime);
}


// displaySerLcdLine( line number, "text for that line")
// writes to each line separately
// lineNum is an integer for the line number. valid values 1 through 4
// *theText is a string of text and it gets padded at the end with spaces
// to overwrite whatever is already showing on that line. If you send more than
// 20 characters, it truncates the text.
void displaySerLcdLine(int lineNum, char *theText){
  int delayTime = 50;
  int lcdPosition = 0;  // initialize lcdPosition and use to indicate value values

  // based upon the lineNum, set the position on the LCD
  if (lineNum==1){
    lcdPosition = 128;
  }
  else if (lineNum==2){
    lcdPosition = 192;
  }
  else if (lineNum==3){
    lcdPosition = 148;
  }
  else if (lineNum==4){
    lcdPosition = 212;
  }

  // don't write to the LCD if the lineNum value didn't generate a valid position
  if (lcdPosition > 0){
    LCD.print(0xFE, BYTE);   //command flag
    delay(delayTime);
    LCD.print(lcdPosition, BYTE);    //position

    if (strlen(theText) < 20) {
      // less than 20 characters, print then and then 
      LCD.print(theText);
      // pad the rest of the line with spaces
      for (int i = strlen(theText); i < 20; i++) {
        LCD.print(" ");
      } 
    } 
    else {  
      // 20 or more characters, just print the first 20
      for (int i = 0; i < 20; i++) {
        LCD.print(theText[i]);
      }
    }
    delay(delayTime);
  }
}


// displaySerLcdChar(LCD line, position on line, 'the character to display')
// LCD line: integer 1 through 4
// position on line: integer 1 through 20
// character to display: a single character in single quotes
void displaySerLcdChar(int lineNum, int charNum, char theChar){
  int delayTime = 50;
  int lcdPosition = 0;  // initialize lcdPosition and use to indicate value values

  // charNum has to be within 1 to 20, 
  // lineNum has to be within 1 to 4
  if (charNum > 0 && charNum < 21) {
    if (lineNum==1){
      lcdPosition = 128;
    }
    else if (lineNum==2){
      lcdPosition = 192;
    }
    else if (lineNum==3){
      lcdPosition = 148;
    }
    else if (lineNum==4){
      lcdPosition = 212;
    }
  }

  // don't write to the LCD if the lineNum and charNum values were not within range
  if (lcdPosition > 0){
    // add to start of line position to get the position to write to
    lcdPosition = lcdPosition + charNum - 1;

    LCD.print(0xFE, BYTE);   //command flag
    delay(delayTime);
    LCD.print(lcdPosition, BYTE);    //position
    LCD.print(theChar);
    delay(delayTime);
  }
}



void clearSerLcd(){
  LCD.print(0xFE, BYTE);   //command flag
  LCD.print(0x01, BYTE);   //clear command.
  delay(50);
}

void backlightSerLcd(int thePercentage){  //turns on the backlight
  LCD.print(0x7C, BYTE);   //command flag for backlight stuff
  int theValue = map(thePercentage, 0,100,128,157); // maps percentage to what SerLCD wants to see
  LCD.print(theValue, BYTE);    //light level.
  delay(50);  
}

Notes

This needs to be updated for 1.0 (write->print, no BYTE)

Also, I modified some of the code to match the standard LCS library (such as set cursor) below. Also I didn't find that the delay needed to be more than 5 ms, if that.

I'm using this on a Mega 2560 and plugged it into one of the additional hardware serial ports. If I have time, I'll derive the lcd library from Serial, not Print and adapt the functions to look the same.

void lcdClear() {

  lcd.write(0xFE);   //command flag
  lcd.write(0x01);   //clear command.
  delay(serialLCDDelay);

}

void lcdSetCursor(int charNum, int lineNum){

 int delayTime = 10;
  int lcdPosition = 0;  // initialize lcdPosition and use to indicate value values

  // charNum has to be within 1 to 20, 
  // lineNum has to be within 1 to 4  
  if (charNum >= 0 && charNum < 20) {
    if (lineNum==0){
      lcdPosition = 128;
    }
    else if (lineNum==1){
      lcdPosition = 192;
    }
    else if (lineNum==2){
      lcdPosition = 148;
    }
    else if (lineNum==3){
      lcdPosition = 212;
    }
  }

  // don't write to the LCD if the lineNum and charNum values were not within range
  if (lcdPosition >= 0){
    // add to start of line position to get the position to write to
    lcdPosition = lcdPosition + charNum;

    lcd.write(0xFE);   //command flag
    delay(serialLCDDelay);
    lcd.write(lcdPosition);    //position
    delay(serialLCDDelay);
  }

}