Possible Audience: Enthusiasts interested in small LCD displays, Cpp programming, creating classes/libraries and inheriting libraries.
Test Hardware: 1602 LCD with I2C interface. Nano microcontroller and Arduino IDE.
Keywords: LCD_1602, Cpp Class/Libraries, Inherited Libraries, Scope Resolution Operator
Inherited library: LiquidCrystal_I2C.
Include file class #include <LCD_1602.h>
Constructor LCD_1602 LCD; -no arguments - defaults to address of 0x27
LCD_1602 LCD(0x27);
Public Methods
void begin( );
void message(int row, char *mess); display a message on a specified row
void message(int row, int res); display integer on a specified row
void message(char *mess); display char at current position
void message(int res); display integer at current position
void message(char *mess1, char *mess2); display message on both rows
void clear_row(int row); clear specified row
void setCursor(int col, int row); set cursor to column and row specified.**
** The methods "message( )" in all its forms are unique to the LCD_1602 class so do not confuse the compiler. However the label setCursor() also occurs in the inherited library so is used used from an educational perspective to demonstrate conflicts with inherited libraries.
---------------------------------------------------------------------
This project was developed to aid debugging during the code development and then as a display in a final project**.
** For example DCC_Yard_Control.
------------------------------------------------------------------------
The design uses the LiquidCrystal_I2C library that assumes the I2C pins A4 and A5 on the Nano are used; That is**:
The final code was also tested using an ESP8266 system and, except for specifying a new target in the Arduino IDE sketch no changes were required..
** The code was initially tested using a project that included an I2C servo driver PCA9685. The two devices were connected in parallel with each device only responding to commands at their own address.
-------------------------------------------------------------------
The first step is to generate a new project LCD_1602. That is in the Arduino IDE select "New" and save the file as LCD_1602. By default it will have the extension *.ino and be stored in a new folder/directory LCD_1602..
In the Arduino IDE select the inverted triangle at the top right to create two new tabs or files. Give these the LCD_1602.cpp (The implementation file) and LCD_1602.h.(Header file).
---------------------------------------
The Liquid Crystal Library: The Header File
One starting point is to populate the header file. For example**
//LCD_1602.h header fileNote this project inherits the LiquidCrystal_I2C class so it must be included as part of the class definition: That is:
#include <LiquidCrystal_I2C.h>
class LCD_1602 : LiquidCrystal_I2C { };
The LCD_1602 constructor gives two options, either no arguments where the implementation file will specify the address (for the LCD it's 0x27), or specify the address as a parameter.
At this point all the possible public methods could be included as part of the class definition. These may be changed as the project progresses. In this example there are multiple message( ) methods the compiler selecting the correct/appropriate one.
The remaining code is typical wrapping for header files to avoid issues if it is included more than once in a project.
**The class contains a number of methods that might be useful. Most are given the label "message" to demonstrate overloading where the compiler selects the appropriate method. The setCursor( ) method uses the same name as an inherited method so must be used with the scope resolution operator ::
--------------------------------------------------------------------------------
With the implementation file it will be necessary to include the header file #include "LCD_1602.h".
The second step is to add all the methods. The actual code will be added in following stages.
The constructor code must include the inherited library LiquidCrystal_I2C**. Further LiquidCrystal_I2C requires 3 parameters - the I2C address (0x27) and the size of the LCD (16 columns by 2 rows). The sample code includes both versions of the constructor - one spelling out the address as 0x27 while in the second the address will be specified when an object/instance of the LCD_1602 is created in the *.ino file.
//LCD_1602.cpp implementation file**In Arduino IDE use sketch --> include library and scroll downn to select Liquid_Crystal_I2C from available libraries.
------------------------------
The test code will basically create one instance/object of the LCD_1602 class/library and include code to (i) initialise the object and (ii) exercise all methods in the object.
Possible code will be:
//Code to test LCD_1602 classThe code creates the object LCD and when the *.cpp code is implemented will initialize the LCD and generate several messages to the display.
------------------------------------------------------
The final implementation code will be:
//LCD_1602.cpp implementation fileNote that all of the methods actually call methods that are part of the LiquidCrystal_I2C library/class. In most cases there is no ambiguity in the names so the compiler knows to use the inherited library LiquidCrystal_I2C. However, with setCursor there is a problem so the scope resolution operator should be used to tell the compiler its the setCursor method that is part of the LiquidCrystal_I2C library. That is use: LiquidCrystal_I2C::setCrystal();
-------------------------------------
Testing.
The code as given worked as expected. While it might appear that the code was all written in one hit in practice it was developed one method at a time with test code included in the *.ino file.
The class was then used as part of other projects. One project involved timing hardware interrupts. There did appear to be a conflict so the code using the LCD was modified to give a complete message rather than build up the display with a number of small messages.**
** One of the issues in using libraries is that the end user has no idea of what goes on inside the library. The LiquidCrystal_I2C library uses the wire library that may use timing circuits which conflict with the interrupt timings.
-------------------------------------------
The library requires the *.cpp and *.h files.
1. Use File Explorer for example to combine the *.cpp and *.h files into a *.zip file. It will have the same name.
2. In the Arduino IDE use the option sketch --> include Library -> Add *.zip Library and select *.zip file of interest
3. In the Arduino work directory there will now be a sub-directory "libraries" and a further subdirectory "This project" that contains the *.cpp and *.h files.
4. To include the library in any project add/include the line #include <This project .h> **
5. To create an object/instance use This_Project Object_Name;
** With quotes the header file will only be found in the same directory/folder as the project. With < > the compiler will look in the libraries folder.
-------------------------------------------------------