Sunday, June 10, 2018

Scrolling Text On LCD with Arduino

Introduction

We want to program the Arduino so that it will scroll (possibly very long) text acroos an LCD screen.
The text shall be sent to the Arduino via the serial port
The text transmitted by the PC via the USB link is stored in the Arduino Memory and displayed as a scrolling text on the LCD display.
The major risk is to lose data in case of very long text since the Arduino internal serial port buffer is limited to 64 bytes

The Hardware

The hardware is the classical Interfacing of an Arduino UNO with a 2x16 HD44780 LCD module. Note that for the module I did use did include a current limiting resistor in the circuit backlight. This may not be the case for your module. So be careful. You may destroy the module if you don’t include an external resistance on a module that has no internal limiting resistance.  (see https://electronics.stackexchange.com/questions/212197/is-it-necessary-to-use-resistor-when-connecting-backlight-of-16x2-lcd-display for details).

For the NPN transistor. I did use a BC547 but any similar transistor (BC108, 2N222,…) may be used instead.

The software

The software is made of 2 parts:

The display part

The display part builds a 16 characters string containing the part of the buffer to print (if needed padded with white spaces) and display it with a lcd.print command. This has the advantage of not disturbing the other lines of the display.
Since the Arduino serial port input buffer is very small (64 bytes), the display routine is immediately stopped once bytes are received in the serial port input buffer. (note: the process could probably be optimized using interrupts but tests did show the program was working correctly without using interrupts

The communication Part

This routine simply fills a large (256 bytes) buffer with the data received on the serial port using the method Serial.readBytesUntil('\n',buffer,256);
The handshaking is done via an XON XOFF mechanism.

Full listing

/*
 LCD Serial ScrollPrint

MIT License

Copyright (c) 2018 Pierre Poliakoff

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

 */

// include the library code:
#include <LiquidCrystal.h>

//declare the hardware
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

int pinBacklight=9;

//const
//=====
const byte XOFF=19;
const byte XON=17;
//variables
//=========
char buffer[256];



void LcdPrintAndScroll(char *buffer,int len)
{
int offset =-16;
String screen="                "; //16 chars buffer string
while(Serial.available()==0)
  {
  lcd.setCursor(0,0);
  offset++;
  if(offset>len)
   {
    offset=-16;
   }
 
  for (int i=0; i <16 && Serial.available()==0 ;i++)
    {
      if((i+offset<len)&&(i+offset>=0)&&buffer[i+offset]>31)
       {
        screen[i]=buffer[i+offset];
       }
      else
      {
        screen[i]=' ';
      }
    }
  lcd.print(screen);
  unsigned long now=millis();
  while(millis()-now<250 && Serial.available()==0)
    {
      //do nothing
    }
  }
}

void setup() {
  // initialize Hardware
  pinMode(pinBacklight,OUTPUT);
  digitalWrite(pinBacklight,HIGH);
  Serial.begin(9600);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  lcd.print("Waiting for Data");
  lcd.setCursor(0,1);
  lcd.print("Scroll Text Demonstration");

}
//===========================================
void loop() {
int len;
// receive data
while (Serial.available()==0)
  {
   //Do nothing 
  }
len=Serial.readBytesUntil('\n',buffer,256);
Serial.write(XOFF); // pause the transmission
Serial.flush();
// insert herre any long computation on Buffer
Serial.write(XON);//reactivate the transmission
//Print Data
if (len>0)
  {
    LcdPrintAndScroll(buffer,len);
  }

}

Sending Data from the PC

We do not want to write a specific software on the PC to send the data. We  simply use the Windows Command line features:
On my PC the Arduino is visible as COM4 (check on you PC for the exact value)
We configure the com port communication via the following command

mode COM4 BAUD=9600 xon=on data=8


Note that each time you upload a new firmware version in the Arduino, you must reconfigure the com port with the above command
Then you can send the data to display via a simple copy command

copy mydata.txt com4:

if you prefer to enter the data directly with the keyboard, you can use

copy con: com4:

Press enter to display the text on the Arduino and CTRL-Z to exit.




The Final Result