├── .gitignore ├── LICENSE ├── extras ├── image │ └── 2004.jpg └── doc │ ├── GPIO_MCU_used.txt │ └── CHANGELOG.md ├── library.properties ├── examples ├── HelloWorld │ └── HelloWorld.ino ├── HelloWorldSTM32 │ └── HelloWorldSTM32.ino ├── TestRun16X02 │ └── TestRun16X02.ino └── TestRun20X04 │ └── TestRun20X04.ino ├── keywords.txt ├── README.md └── src ├── HD44780_LCD_PCF8574.h └── HD44780_LCD_PCF8574.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | stuff/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gavinlyonsrepo/HD44780_LCD_PCF8574/HEAD/LICENSE -------------------------------------------------------------------------------- /extras/image/2004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gavinlyonsrepo/HD44780_LCD_PCF8574/HEAD/extras/image/2004.jpg -------------------------------------------------------------------------------- /extras/doc/GPIO_MCU_used.txt: -------------------------------------------------------------------------------- 1 | # GPIO used in testing for I2C 2 | 3 | UNO/NANO I2C 4 | A4 SDA 5 | A5 SCLK 6 | 7 | ESP8266 HARDWARE I2C 8 | D1 GPIO5 20 SCK 9 | D2 GPIO4 19 SDA 10 | 11 | ESP32 HARDWARE I2C 12 | D22 GPIO22 SCK 13 | D21 GPIO21 SDA 14 | 15 | STM32 STM32F103C8T6 "blue pill" I2C 16 | 17 | I2C port 1 18 | PB6 22 42 B6 SCK 19 | PB7 23 43 B7 SDA 20 | 21 | I2C port 2 22 | PB10 21 26 B10 SCL2 23 | PB11 22 27 B11 SDA2 24 | 25 | 26 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=HD44780_LCD_PCF8574 2 | version=1.3.0 3 | author=Gavin Lyons 4 | maintainer=Gavin Lyons 5 | sentence=Library to Support the HD44780 LCD I2C driven by the PCF8574 controller 6 | paragraph=Backlight, scroll, cursor and entrymode control. Custom character support + print class for numerical data. 7 | category=Display 8 | url=https://github.com/gavinlyonsrepo/HD44780_LCD_PCF8574 9 | architectures=* 10 | -------------------------------------------------------------------------------- /extras/doc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | * version 1.0.0 March 2022 4 | * first release. 5 | * version 1.1.0 April 2022 6 | * Tested on 20x04 for first time and github issue 1 closed off. 7 | * Example file added for 20x04 8 | * version 1.2.0 September 2022 9 | * Option added for User to pick I2C port for STM32 bluepill, github issue 2. 10 | * version 1.3.0 April 2023 11 | * Refactor and optimisations, enums are now part of the class 12 | * Added STM32 "hello world" example file 13 | * Added "Doxygen" style comments in order to use "Doxygen" software to automatically 14 | generate a html based software API. 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/HelloWorld/HelloWorld.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | @file HelloWorld.ino 3 | @author Gavin Lyons 4 | @brief 5 | Hello World for HD44780_LCD_PCF8574 arduino library 6 | */ 7 | 8 | // Section: Included library 9 | #include "HD44780_LCD_PCF8574.h" 10 | 11 | // Section: Defines 12 | #define DISPLAY_DELAY_INIT 50 // mS 13 | 14 | HD44780LCD myLCD(2, 16, 0x27, &Wire); // instantiate an object 15 | 16 | // Section: Setup 17 | 18 | void setup() { 19 | delay(DISPLAY_DELAY_INIT); 20 | myLCD.PCF8574_LCDInit(myLCD.LCDCursorTypeOn); 21 | myLCD.PCF8574_LCDClearScreen(); 22 | myLCD.PCF8574_LCDBackLightSet(true); 23 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 24 | } 25 | 26 | // Section: Main Loop 27 | 28 | void loop() { 29 | char testString[] = "Hello World"; 30 | myLCD.PCF8574_LCDSendString(testString); 31 | myLCD.PCF8574_LCDSendChar('!'); // Display a single character 32 | while (true) {}; 33 | } 34 | 35 | // EOF 36 | -------------------------------------------------------------------------------- /examples/HelloWorldSTM32/HelloWorldSTM32.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | @file HelloWorldSTM32.ino 3 | @author Gavin Lyons 4 | @brief 5 | Hello World for HD44780_LCD_PCF8574 arduino library for STM32 "blue pill" 6 | @note Allows testing of both I2C ports 1 and 2 on the STM32 "blue pill" board 7 | */ 8 | 9 | // Section: Included library 10 | #include "HD44780_LCD_PCF8574.h" 11 | 12 | // Section: Defines 13 | #define DISPLAY_DELAY_INIT 50 // mS 14 | #define STM_I2C1_PORT 1 // STM32 I2C port 1 = I2C1 15 | #define STM_I2C2_PORT 2 // STM32 I2C port 2 = I2C2 16 | 17 | // Section: Globals 18 | TwoWire Wire2(STM_I2C1_PORT); // use I2C1 Port 1 19 | HD44780LCD myLCD(2, 16, 0x27, &Wire2); 20 | 21 | // Section: Setup 22 | 23 | void setup() { 24 | delay(DISPLAY_DELAY_INIT); 25 | myLCD.PCF8574_LCDInit(myLCD.LCDCursorTypeOn); 26 | myLCD.PCF8574_LCDClearScreen(); 27 | myLCD.PCF8574_LCDBackLightSet(true); 28 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 29 | } 30 | 31 | // Section: Main Loop 32 | 33 | void loop() { 34 | char testString[] = "Hello World"; 35 | myLCD.PCF8574_LCDSendString(testString); 36 | myLCD.PCF8574_LCDSendChar('!'); // Display a single character 37 | while (true) {}; 38 | } 39 | 40 | // EOF 41 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | # ----------------------------------------- 2 | # Syntax colouring for library 3 | # ----------------------------------------- 4 | 5 | # Datatypes (such as objects) 6 | HD44780LCD KEYWORD1 7 | 8 | #Methods / functions 9 | 10 | PCF8574_LCDInit KEYWORD2 11 | PCF8574_LCDDisplayON KEYWORD2 12 | PCF8574_LCDResetScreen KEYWORD2 13 | PCF8574_LCDBackLightSet KEYWORD2 14 | PCF8574_LCDBackLightGet KEYWORD2 15 | PCF8574_LCD_I2C_ON KEYWORD2 16 | PCF8574_LCDSendString KEYWORD2 17 | PCF8574_LCDSendChar KEYWORD2 18 | PCF8574_LCDCreateCustomChar KEYWORD2 19 | PCF8574_LCDPrintCustomChar KEYWORD2 20 | PCF8574_LCDMoveCursor KEYWORD2 21 | PCF8574_LCDScroll KEYWORD2 22 | PCF8574_LCDGOTO KEYWORD2 23 | PCF8574_LCDClearLine KEYWORD2 24 | PCF8574_LCDClearScreen KEYWORD2 25 | PCF8574_LCDClearScreenCmd KEYWORD2 26 | PCF8574_LCDHome KEYWORD2 27 | PCF8574_LCDChangeEntryMode KEYWORD2 28 | 29 | LCDLineNumber_e KEYWORD2 30 | LCDEntryMode_e KEYWORD2 31 | LCDCursorType_e KEYWORD2 32 | LCDDirectionType_e KEYWORD2 33 | 34 | # Constants 35 | 36 | LCDEntryModeOne LITERAL1 37 | LCDEntryModeTwo LITERAL1 38 | LCDEntryModeThree LITERAL1 39 | LCDEntryModeFour LITERAL1 40 | 41 | LCDCursorTypeOff LITERAL1 42 | LCDCursorTypeBlink LITERAL1 43 | LCDCursorTypeOn LITERAL1 44 | LCDCursorTypeOnBlink LITERAL1 45 | 46 | LCDMoveRight LITERAL1 47 | LCDMoveLeft LITERAL1 48 | 49 | LCDLineNumberOne LITERAL1 50 | LCDLineNumberTwo LITERAL1 51 | LCDLineNumberThree LITERAL1 52 | LCDLineNumberFour LITERAL1 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Website](https://img.shields.io/badge/Website-Link-blue.svg)](https://gavinlyonsrepo.github.io/) [![Rss](https://img.shields.io/badge/Subscribe-RSS-yellow.svg)](https://gavinlyonsrepo.github.io//feed.xml) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/paypalme/whitelight976) 2 | 3 | 4 | ![ lcd image ](https://github.com/gavinlyonsrepo/pic_16F1619_projects/blob/master/images/LCDPCF.jpg) 5 | 6 | # Hd44780_LCD_PCF8574 7 | 8 | Table of contents 9 | --------------------------- 10 | 11 | * [Overview](#overview) 12 | * [Installation](#installation) 13 | * [Software](#software) 14 | * [Output](#output) 15 | * [Tested on](#tested-on) 16 | * [Notes](#notes) 17 | 18 | Overview 19 | -------------------- 20 | * Name : HD44780_LCD_PCF8574 21 | * Description : 22 | 23 | 0. Library to support the HD44780 LCD , (I2C PCF8574 "backpack" interface) 24 | for the Arduino Eco system 25 | 1. C++ library. 26 | 2. Backlight, scroll, cursor and entry-mode control. 27 | 3. Custom character support + print class for numerical data. 28 | 4. Hardware I2C 29 | 5. Tested on size 16x02 + 20x04 (but may work on other sizes eg 16x04 but not tested). 30 | 6. Can support both I2C ports on the STM32, see tested section. 31 | 32 | * Author: Gavin Lyons 33 | 34 | Installation 35 | ------------------------------ 36 | 37 | The library is included in the official Arduino library manger and the optimum way to install it is using the library manager in the Arduino IDE. 38 | 39 | Software 40 | -------------------------- 41 | 42 | **API** 43 | 44 | The API (application programming interface) html documentation is at link. Hosted on github pages and generated by Doxygen software. Here the user will find lots of information on files, functions & data types. 45 | 46 | [Software API Url Link](https://gavinlyonsrepo.github.io/misc/software_docs/HD44780_LCD_PCF8574/index.html) 47 | 48 | Output 49 | --------------------- 50 | 51 | Output of custom character test in testrun example file on 16x02 display. 52 | 53 | ![ pic ](https://github.com/gavinlyonsrepo/HD44780_LCD_RPI/blob/main/extras/image/custom_output.jpg) 54 | 55 | 20x04 display. 56 | 57 | ![ pic2 ](https://github.com/gavinlyonsrepo/HD44780_LCD_PCF8574/blob/main/extras/image/2004.jpg) 58 | 59 | Tested on 60 | ------------------------ 61 | 62 | Tested on following MCUs. 63 | The example files are setup for an UNO/NANO rev 3.0 for the pin connections used 64 | by for other MCU testing see extras/doc folder GPIO_MCU_used.txt file. 65 | 66 | 1. Arduino UNO & NANO v3 67 | 2. ESP8266 68 | 3. ESP32 69 | 4. STM32 "blue pill", Can support both I2C ports , Use STM32 example file. 70 | 5. Arduino UNO R4 minima 71 | 72 | Notes 73 | ------------------------ 74 | 75 | 1. "stm32duino" board manager core used in testing STM32 "blue pill" 76 | 2. For description of entry modes , cursor types, custom characters etc [See]( http://dinceraydin.com/lcd/commands.htm) 77 | 3. 16X04 board not tested as not available but should work! 78 | 4. I2C Debugging can be turned on by commenting in a define in header file. 79 | -------------------------------------------------------------------------------- /src/HD44780_LCD_PCF8574.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @file HD44780_LCD_PCF8574.h 3 | @author Gavin Lyons 4 | @brief HD44780-based character LCD 16x02 I2C(PCF8574) library header file for arduino eco system 5 | URL: https://github.com/gavinlyonsrepo/HD44780_LCD_PCF8574 6 | */ 7 | 8 | 9 | #if ARDUINO >= 100 10 | #include "Arduino.h" 11 | #include "Print.h" 12 | #else 13 | #include "WProgram.h" 14 | #endif 15 | 16 | #include "Wire.h" 17 | 18 | #ifndef LCD_HD44780_H 19 | #define LCD_HD44780_H 20 | 21 | //#define LCD_SERIAL_DEBUG // Comment in for serial debug I2C errors, set baud rate externally. 22 | 23 | /*! 24 | @brief Class for HD44780 LCD 25 | */ 26 | class HD44780LCD : public Print{ 27 | public: 28 | 29 | // public enums 30 | 31 | /*! Backlight Control , Command Byte Code */ 32 | enum LCDBackLight_e : uint8_t{ 33 | LCDBackLightOnMask = 0x0F, /**< XXXX-1111, Turn on Back light */ 34 | LCDBackLightOffMask = 0x07 /**< XXXX-0111, Turn off Back light */ 35 | }; 36 | 37 | /*! Entry mode control set command, Command Byte Code */ 38 | enum LCDEntryMode_e : uint8_t{ 39 | LCDEntryModeOne = 0x04, /**< Display Shift :OFF Decrement Address Counter */ 40 | LCDEntryModeTwo = 0x05, /**< Display Shift :ON Decrement Address Counter */ 41 | LCDEntryModeThree = 0x06, /**< Display Shift :OFF Increment Address Counter, default */ 42 | LCDEntryModeFour = 0x07 /**< Display Shift :ON Increment Address Counter */ 43 | }; 44 | 45 | /*! Cursor mode, Command Byte Code */ 46 | enum LCDCursorType_e : uint8_t { 47 | LCDCursorTypeOff= 0x0C, /**< Make cursor invisible */ 48 | LCDCursorTypeBlink = 0x0D, /**< Turn on blinking-block cursor */ 49 | LCDCursorTypeOn = 0x0E, /**< Turn on visible underline cursor */ 50 | LCDCursorTypeOnBlink = 0x0F /**= 100 95 | virtual size_t write(uint8_t); 96 | #else 97 | virtual void write(uint8_t); 98 | #endif 99 | 100 | private: 101 | 102 | // Private internal enums 103 | 104 | /*! DDRAM address's used to set cursor position Note Private */ 105 | enum LCDAddress_e : uint8_t { 106 | LCDLineAddressOne = 0x80, /**< Line 1 */ 107 | LCDLineAddressTwo = 0xC0, /**< Line 2 */ 108 | LCDLineAddress3Col20 = 0x94, /**< Line 3 20x04 line 3 */ 109 | LCDLineAddress4Col20 = 0xD4, /**< Line 4 20x04 line 4 */ 110 | LCDLineAddress3Col16 = 0x90, /**< Line 3 16x04 untested, no part */ 111 | LCDLineAddress4Col16 = 0xD0 /**< Line 4 16x04 untested, no part */ 112 | }; 113 | 114 | /*! Command Bytes General Note Private */ 115 | enum LCDCmdBytesGeneral_e : uint8_t { 116 | LCDModeFourBit = 0x28, /**< Function set (4-bit interface, 2 lines, 5*7 Pixels) */ 117 | LCDHomePosition = 0x02, /**< Home (move cursor to top/left character position) */ 118 | LCDDisplayOn = 0x0C, /**< Restore the display (with cursor hidden) */ 119 | LCDDisplayOff = 0x08, /**< Blank the display (without clearing) */ 120 | LCDClearScreen = 0x01 /**< clear screen */ 121 | }; 122 | 123 | 124 | enum LCDBackLight_e _LCDBackLight= LCDBackLightOnMask; /**< Enum to store backlight status*/ 125 | 126 | // Private Data 127 | uint8_t _LCDSlaveAddresI2C = 0x27 ; /**< I2C address for I2C module PCF8574 backpack on LCD*/ 128 | uint8_t _NumRowsLCD = 2; /**< Number of rows on LCD */ 129 | uint8_t _NumColsLCD = 16; /**< Number of Cols on LCD */ 130 | TwoWire *wire; /**< I2C wire interface */ 131 | 132 | // private methods 133 | void PCF8574_LCDSendCmd (unsigned char cmd); 134 | void PCF8574_LCDSendData (unsigned char data); 135 | bool PCF8574_LCD_I2C_ON(void); 136 | 137 | }; // end of HD44780LCD class 138 | 139 | #endif // guard header ending 140 | -------------------------------------------------------------------------------- /examples/TestRun16X02/TestRun16X02.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | @file TestRun16X02.ino 3 | @author Gavin Lyons 4 | @brief 5 | This file contains the "main" function for project, a set of test sequence 6 | to test the HD44780_LCD_PCF8574 arduino library. 16X02 display. 7 | @test 8 | -# Test 1 :: Hello world 9 | -# Test 2 :: Move the cursor test 10 | -# Test 3 :: Scroll the display test 11 | -# Test 4 :: Test GOTO method 12 | -# Test 5 :: Test clear a line method 13 | -# Test 6 :: Cursor type (4 off) and screen reset test, Cursor mode is changed with a reset. 14 | -# Test 7 :: Text entry mode (4 off) if screen is reset the entry mode will be reset to default 15 | -# Test 8 :: Print numerical data using print() method 16 | -# Test 9 :: Custom character's from the CGRAM test 17 | -# Test 10 :: Backlight test. 18 | */ 19 | 20 | // Section: Included library 21 | #include "HD44780_LCD_PCF8574.h" 22 | 23 | // Section: Defines 24 | #define DISPLAY_DELAY_1 1000 25 | #define DISPLAY_DELAY_2 2000 26 | #define DISPLAY_DELAY 5000 27 | 28 | // Section: Globals 29 | HD44780LCD myLCD( 2, 16, 0x27, &Wire); // instantiate an object 30 | 31 | // Section: Function Prototypes 32 | 33 | void helloWorld(void); 34 | void cursorMoveTest(void); 35 | void scrollTest(void); 36 | void gotoTest(void); 37 | void clearLineTest(void); 38 | void cursorTest(void); 39 | void entryModeTest(void); 40 | void writeNumTest(void); 41 | void customChar(void); 42 | void backLightTest(void); 43 | void endTest(void); 44 | 45 | // Section: Setup 46 | 47 | void setup() { 48 | delay(50); 49 | myLCD.PCF8574_LCDInit(myLCD.LCDCursorTypeOn); 50 | myLCD.PCF8574_LCDClearScreen(); 51 | myLCD.PCF8574_LCDBackLightSet(true); 52 | 53 | } 54 | 55 | // Section: Main Loop 56 | 57 | void loop() { 58 | 59 | helloWorld(); 60 | cursorMoveTest(); 61 | scrollTest(); 62 | gotoTest(); 63 | clearLineTest(); 64 | cursorTest(); 65 | entryModeTest(); 66 | writeNumTest(); 67 | customChar(); 68 | backLightTest(); 69 | 70 | } // End of Main 71 | 72 | // Section : Functions 73 | 74 | void helloWorld(void) { 75 | char teststr1[] = "Hello"; 76 | char teststr2[] = "World"; 77 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 78 | myLCD.PCF8574_LCDSendString(teststr1); 79 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 0); 80 | myLCD.PCF8574_LCDSendString(teststr2); // Display a string 81 | myLCD.PCF8574_LCDSendChar('!'); // Display a single character 82 | delay(DISPLAY_DELAY_1); 83 | } 84 | 85 | void cursorMoveTest(void) { 86 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); 87 | delay(DISPLAY_DELAY); 88 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveLeft, 2); 89 | } 90 | 91 | void scrollTest(void) { 92 | for (uint8_t i = 0; i < 5; i++) { 93 | myLCD.PCF8574_LCDScroll(myLCD.LCDMoveRight, 1); 94 | delay(DISPLAY_DELAY_2); 95 | } 96 | myLCD.PCF8574_LCDScroll(myLCD.LCDMoveLeft, 5); 97 | delay(DISPLAY_DELAY_2); 98 | } 99 | 100 | void gotoTest(void) { 101 | char teststr3[] = "Line 2"; 102 | myLCD.PCF8574_LCDClearScreen(); 103 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 10); 104 | myLCD.PCF8574_LCDSendChar('A'); 105 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 2); 106 | myLCD.PCF8574_LCDSendString(teststr3); 107 | delay(DISPLAY_DELAY); 108 | } 109 | 110 | void clearLineTest(void) 111 | { 112 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo ); 113 | delay(DISPLAY_DELAY_2); 114 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberOne); 115 | delay(DISPLAY_DELAY_2); 116 | } 117 | 118 | void cursorTest(void) { 119 | char teststr1[] = "Cursor no 4"; 120 | char teststr2[] = "Cursor no 1"; 121 | char teststr3[] = "Cursor no 2"; 122 | char teststr4[] = "Cursor no 3"; 123 | 124 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeOnBlink); //type 4 cursor 125 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 126 | myLCD.PCF8574_LCDSendString(teststr1); 127 | delay(DISPLAY_DELAY_2); 128 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 129 | 130 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeOff); //type 1 cursor 131 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 132 | myLCD.PCF8574_LCDSendString(teststr2); 133 | delay(DISPLAY_DELAY_2); 134 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 135 | 136 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeBlink); //type 2 cursor 137 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 138 | myLCD.PCF8574_LCDSendString(teststr3); 139 | delay(DISPLAY_DELAY_2); 140 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 141 | 142 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeOn); // Back to initial state , type 3 143 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 144 | myLCD.PCF8574_LCDSendString(teststr4); 145 | delay(DISPLAY_DELAY_2); 146 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 147 | } 148 | 149 | void writeNumTest() 150 | { 151 | int numPos = 193; 152 | int numNeg = -8582; 153 | double myPI = 3.1456; 154 | 155 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 156 | myLCD.print(numPos); 157 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 0); 158 | myLCD.print(numNeg); 159 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); 160 | myLCD.print(myPI,3); 161 | 162 | delay(DISPLAY_DELAY); 163 | myLCD.PCF8574_LCDClearScreen(); 164 | 165 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); // 11 166 | myLCD.print(11); 167 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); // 13 168 | myLCD.print(11,OCT); 169 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 0); // B 170 | myLCD.print(11, HEX); 171 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); // 1011 172 | myLCD.print(11,BIN); 173 | 174 | delay(DISPLAY_DELAY); 175 | } 176 | 177 | void customChar(void) { 178 | uint8_t index = 0; // Character generator RAM location ,0-7 ,64 bytes 179 | // custom characters data to test custom character function 180 | uint8_t symbolData[8][8] = { 181 | {0x04, 0x0E, 0x0E, 0x0E, 0x1F, 0x00, 0x04, 0x00}, // bell 182 | {0x02, 0x03, 0x02, 0x0E, 0x1E, 0x0C, 0x00, 0x00}, // Note 183 | {0x00, 0x0E, 0x15, 0x17, 0x11, 0x0E, 0x00, 0x00}, // clock 184 | {0x00, 0x0C, 0x1D, 0x0F, 0x0F, 0x06, 0x00, 0x00}, // duck 185 | {0x00, 0x01, 0x03, 0x16, 0x1C, 0x08, 0x00, 0x00}, // check 186 | {0x00, 0x1B, 0x0E, 0x04, 0x0E, 0x1B, 0x00, 0x00}, // cross 187 | {0x00, 0x0A, 0x1F, 0x1F, 0x0E, 0x04, 0x00, 0x00}, // heart 188 | {0x01, 0x01, 0x05, 0x09, 0x1F, 0x08, 0x04, 0x00} // return arrow 189 | }; 190 | 191 | myLCD.PCF8574_LCDClearScreen(); 192 | 193 | // Load the CGRAM with the data , custom characters 194 | // location argument must be 0 to 7 , load the data into LCD memory 195 | for (uint8_t index = 0; index < 8; index++) { 196 | myLCD.PCF8574_LCDCreateCustomChar(index , symbolData[index]); 197 | } 198 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 199 | 200 | // Print out custom characters from 201 | // CGRAM locations 0-7 , location argument must be 0 to 7 202 | for (index = 0; index < 8; index ++) { 203 | myLCD.PCF8574_LCDPrintCustomChar(index); 204 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 1); 205 | } 206 | 207 | delay(DISPLAY_DELAY); 208 | myLCD.PCF8574_LCDClearScreen(); 209 | } 210 | 211 | void backLightTest(void) 212 | { 213 | char teststr4[] = "Back Light :: "; 214 | 215 | myLCD.PCF8574_LCDBackLightSet(false); // Needs another command/data before it changes Light 216 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 1); 217 | myLCD.PCF8574_LCDSendString(teststr4); 218 | myLCD.print(myLCD.PCF8574_LCDBackLightGet()); // read the backlight variable status 219 | delay(DISPLAY_DELAY); 220 | 221 | myLCD.PCF8574_LCDBackLightSet(true); // Needs another command/data before it changes Light 222 | myLCD.PCF8574_LCDClearScreen(); 223 | } 224 | 225 | void entryModeTest(void) { 226 | 227 | char teststr8[] = "1234"; 228 | 229 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeOne); 230 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 8); 231 | myLCD.PCF8574_LCDSendString(teststr8); // <-C4321 232 | delay(DISPLAY_DELAY_2); 233 | myLCD.PCF8574_LCDClearScreenCmd(); 234 | 235 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeTwo); 236 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 8); 237 | myLCD.PCF8574_LCDSendString(teststr8); // C4321-> 238 | delay(DISPLAY_DELAY_2); 239 | myLCD.PCF8574_LCDClearScreenCmd(); 240 | 241 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeFour); 242 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 8); 243 | myLCD.PCF8574_LCDSendString(teststr8); // <-1234C 244 | delay(DISPLAY_DELAY_2); 245 | myLCD.PCF8574_LCDClearScreenCmd(); 246 | 247 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeThree); // Set back to default entry mode 248 | myLCD.PCF8574_LCDClearScreenCmd(); 249 | delay(DISPLAY_DELAY_1); 250 | } 251 | 252 | // *** EOF *** 253 | -------------------------------------------------------------------------------- /examples/TestRun20X04/TestRun20X04.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | @file TestRun20X04.ino 3 | @author Gavin Lyons 4 | @brief 5 | This file contains the "main" function for project, a set of test sequence 6 | to test the HD44780_LCD_PCF8574 arduino library. 20X04 display. 7 | @test 8 | -# Test 1 :: Hello world 9 | -# Test 2 :: Move the cursor test 10 | -# Test 3 :: Scroll the display test 11 | -# Test 4 :: Test GOTO method 12 | -# Test 5 :: Test clear a line method 13 | -# Test 6 :: Cursor type (4 off) and screen reset test, Cursor mode is changed with a reset. 14 | -# Test 7 :: Text entry mode (4 off) if screen is reset the entry mode will be reset to default 15 | -# Test 8 :: Print numerical data using print() method 16 | -# Test 9 :: Custom character's from the CGRAM test 17 | -# Test 10 :: Backlight test. 18 | */ 19 | 20 | // Section: Included library 21 | #include "HD44780_LCD_PCF8574.h" 22 | 23 | // Section: Defines 24 | #define DISPLAY_DELAY_1 1000 25 | #define DISPLAY_DELAY_2 2000 26 | #define DISPLAY_DELAY 5000 27 | 28 | // Section: Globals 29 | HD44780LCD myLCD( 4, 20, 0x27, &Wire); // instantiate an object 30 | 31 | // Section: Function Prototypes 32 | 33 | void helloWorld(void); 34 | void cursorMoveTest(void); 35 | void scrollTest(void); 36 | void gotoTest(void); 37 | void clearLineTest(void); 38 | void cursorTest(void); 39 | void entryModeTest(void); 40 | void writeNumTest(void); 41 | void customChar(void); 42 | void backLightTest(void); 43 | void endTest(void); 44 | 45 | // Section: Setup 46 | 47 | void setup() { 48 | delay(50); 49 | myLCD.PCF8574_LCDInit(myLCD.LCDCursorTypeOn); 50 | myLCD.PCF8574_LCDClearScreen(); 51 | myLCD.PCF8574_LCDBackLightSet(true); 52 | 53 | } 54 | 55 | // Section: Main Loop 56 | 57 | void loop() { 58 | 59 | helloWorld(); 60 | cursorMoveTest(); 61 | scrollTest(); 62 | gotoTest(); 63 | clearLineTest(); 64 | cursorTest(); 65 | entryModeTest(); 66 | writeNumTest(); 67 | customChar(); 68 | backLightTest(); 69 | 70 | } // End of Main 71 | 72 | // Section : Functions 73 | void helloWorld(void) { 74 | char teststr1[] = "Hello"; 75 | char teststr2[] = "World"; 76 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 77 | myLCD.PCF8574_LCDSendString(teststr1); 78 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberThree , 0); 79 | myLCD.PCF8574_LCDSendString(teststr2); // Display a string 80 | myLCD.PCF8574_LCDSendChar('!'); // Display a single character 81 | delay(DISPLAY_DELAY_1); 82 | } 83 | 84 | void cursorMoveTest(void) { 85 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); 86 | delay(DISPLAY_DELAY); 87 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveLeft, 2); 88 | } 89 | 90 | void scrollTest(void) { 91 | for (uint8_t i = 0; i < 10; i++) { 92 | myLCD.PCF8574_LCDScroll(myLCD.LCDMoveRight, 1); 93 | delay(DISPLAY_DELAY_2); 94 | } 95 | myLCD.PCF8574_LCDScroll(myLCD.LCDMoveLeft, 10); 96 | delay(DISPLAY_DELAY_2); 97 | } 98 | 99 | void gotoTest(void) { 100 | myLCD.PCF8574_LCDClearScreen(); 101 | 102 | char teststr1[] = "Line 1"; 103 | char teststr2[] = "Line 2"; 104 | char teststr3[] = "Line 3"; 105 | char teststr4[] = "Line 4"; 106 | char testchar = '!'; 107 | int columnPos = 0; 108 | 109 | // Print a string to each line 110 | 111 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 112 | myLCD.PCF8574_LCDSendString(teststr1); 113 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 0); 114 | myLCD.PCF8574_LCDSendString(teststr2); 115 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberThree , 0); 116 | myLCD.PCF8574_LCDSendString(teststr3); 117 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberFour , 0); 118 | myLCD.PCF8574_LCDSendString(teststr4); 119 | delay(DISPLAY_DELAY); 120 | 121 | myLCD.PCF8574_LCDClearScreen(); 122 | 123 | // Print out ASCII table one character at a time in every position 124 | // with a unique goto command 125 | for (columnPos = 0 ; columnPos <20 ; columnPos++) 126 | { 127 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, columnPos); 128 | myLCD.PCF8574_LCDSendChar(testchar++); 129 | } //Line 1 130 | delay(DISPLAY_DELAY_1); 131 | 132 | for (columnPos = 0 ; columnPos <20 ; columnPos++) 133 | { 134 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, columnPos); 135 | myLCD.PCF8574_LCDSendChar(testchar++); 136 | } //Line 2 137 | delay(DISPLAY_DELAY_1); 138 | 139 | for (columnPos = 0 ; columnPos <20 ; columnPos++) 140 | { 141 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberThree, columnPos); 142 | myLCD.PCF8574_LCDSendChar(testchar++); 143 | } //Line 3 144 | delay(DISPLAY_DELAY_1); 145 | 146 | for (columnPos = 0 ; columnPos <20 ; columnPos++) 147 | { 148 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberFour, columnPos); 149 | myLCD.PCF8574_LCDSendChar(testchar++); 150 | } // Line 4 151 | delay(DISPLAY_DELAY); 152 | } 153 | 154 | void clearLineTest(void) 155 | { 156 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberOne); 157 | delay(DISPLAY_DELAY_2); 158 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 159 | delay(DISPLAY_DELAY_2); 160 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberThree); 161 | delay(DISPLAY_DELAY_2); 162 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberFour); 163 | delay(DISPLAY_DELAY_2); 164 | } 165 | 166 | void cursorTest(void) { 167 | char teststr1[] = "Cursor no 4"; 168 | char teststr2[] = "Cursor no 1"; 169 | char teststr3[] = "Cursor no 2"; 170 | char teststr4[] = "Cursor no 3"; 171 | 172 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeOnBlink); //type 4 cursor 173 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 174 | myLCD.PCF8574_LCDSendString(teststr1); 175 | delay(DISPLAY_DELAY_2); 176 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 177 | 178 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeOff); //type 1 cursor 179 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 180 | myLCD.PCF8574_LCDSendString(teststr2); 181 | delay(DISPLAY_DELAY_2); 182 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 183 | 184 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeBlink); //type 2 cursor 185 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 186 | myLCD.PCF8574_LCDSendString(teststr3); 187 | delay(DISPLAY_DELAY_2); 188 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 189 | 190 | myLCD.PCF8574_LCDResetScreen(myLCD.LCDCursorTypeOn); // Back to initial state , type 3 191 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 0); 192 | myLCD.PCF8574_LCDSendString(teststr4); 193 | delay(DISPLAY_DELAY_2); 194 | myLCD.PCF8574_LCDClearLine(myLCD.LCDLineNumberTwo); 195 | } 196 | 197 | void writeNumTest() 198 | { 199 | int numPos = 193; 200 | int numNeg = -8582; 201 | double myPI = 3.1456; 202 | 203 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 204 | myLCD.print(numPos); 205 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 0); 206 | myLCD.print(numNeg); 207 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); 208 | myLCD.print(myPI,3); 209 | 210 | delay(DISPLAY_DELAY); 211 | myLCD.PCF8574_LCDClearScreen(); 212 | 213 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); // 11 214 | myLCD.print(11); 215 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); // 13 216 | myLCD.print(11,OCT); 217 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 0); // B 218 | myLCD.print(11, HEX); 219 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 2); // 1011 220 | myLCD.print(11,BIN); 221 | 222 | delay(DISPLAY_DELAY); 223 | } 224 | 225 | void customChar(void) { 226 | 227 | uint8_t index = 0; // Character generator RAM location ,0-7 ,64 bytes 228 | // custom characters data to test custom character function 229 | uint8_t symbolData[8][8] = { 230 | {0x04, 0x0E, 0x0E, 0x0E, 0x1F, 0x00, 0x04, 0x00}, // bell 231 | {0x02, 0x03, 0x02, 0x0E, 0x1E, 0x0C, 0x00, 0x00}, // Note 232 | {0x00, 0x0E, 0x15, 0x17, 0x11, 0x0E, 0x00, 0x00}, // clock 233 | {0x00, 0x0C, 0x1D, 0x0F, 0x0F, 0x06, 0x00, 0x00}, // duck 234 | {0x00, 0x01, 0x03, 0x16, 0x1C, 0x08, 0x00, 0x00}, // check 235 | {0x00, 0x1B, 0x0E, 0x04, 0x0E, 0x1B, 0x00, 0x00}, // cross 236 | {0x00, 0x0A, 0x1F, 0x1F, 0x0E, 0x04, 0x00, 0x00}, // heart 237 | {0x01, 0x01, 0x05, 0x09, 0x1F, 0x08, 0x04, 0x00} // return arrow 238 | }; 239 | 240 | myLCD.PCF8574_LCDClearScreen(); 241 | 242 | // Load the CGRAM with the data , custom characters 243 | // location argument must be 0 to 7 , load the data into LCD memory 244 | for (uint8_t index = 0; index < 8; index++) { 245 | myLCD.PCF8574_LCDCreateCustomChar(index , symbolData[index]); 246 | } 247 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 0); 248 | 249 | // Print out custom characters from 250 | // CGRAM locations 0-7 , location argument must be 0 to 7 251 | for (index = 0; index < 8; index ++) { 252 | myLCD.PCF8574_LCDPrintCustomChar(index); 253 | myLCD.PCF8574_LCDMoveCursor(myLCD.LCDMoveRight, 1); 254 | } 255 | 256 | delay(DISPLAY_DELAY); 257 | myLCD.PCF8574_LCDClearScreen(); 258 | } 259 | 260 | void backLightTest(void) 261 | { 262 | char teststr4[] = "Back Light : "; 263 | 264 | myLCD.PCF8574_LCDBackLightSet(false); // Needs another command/data before it changes Light 265 | 266 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo , 1); 267 | myLCD.PCF8574_LCDSendString(teststr4); 268 | myLCD.print(myLCD.PCF8574_LCDBackLightGet()); // read the backlight variable status 269 | delay(DISPLAY_DELAY); 270 | myLCD.PCF8574_LCDBackLightSet(true); // Needs another command/data before it changes Light 271 | myLCD.PCF8574_LCDClearScreen(); 272 | } 273 | 274 | void entryModeTest(void) { 275 | 276 | char teststr8[] = "1234"; 277 | 278 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeOne); 279 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberOne, 8); 280 | myLCD.PCF8574_LCDSendString(teststr8); // <-C4321 281 | delay(DISPLAY_DELAY_2); 282 | myLCD.PCF8574_LCDClearScreenCmd(); 283 | 284 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeTwo); 285 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 8); 286 | myLCD.PCF8574_LCDSendString(teststr8); // C4321-> 287 | delay(DISPLAY_DELAY_2); 288 | myLCD.PCF8574_LCDClearScreenCmd(); 289 | 290 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeFour); 291 | myLCD.PCF8574_LCDGOTO(myLCD.LCDLineNumberTwo, 8); 292 | myLCD.PCF8574_LCDSendString(teststr8); // <-1234C 293 | delay(DISPLAY_DELAY_2); 294 | myLCD.PCF8574_LCDClearScreenCmd(); 295 | 296 | myLCD.PCF8574_LCDChangeEntryMode(myLCD.LCDEntryModeThree); // Set back to default entry mode 297 | myLCD.PCF8574_LCDClearScreenCmd(); 298 | delay(DISPLAY_DELAY_1); 299 | } 300 | 301 | // *** EOF *** 302 | -------------------------------------------------------------------------------- /src/HD44780_LCD_PCF8574.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | @file HD44780_LCD_PCF8574.cpp 3 | @author Gavin Lyons 4 | @brief HD44780-based character LCD 16x02 I2C(PCF8574) library Source file for arduino eco system 5 | */ 6 | 7 | // Includes 8 | #include "HD44780_LCD_PCF8574.h" 9 | 10 | /*! 11 | @brief Constructor for class HD44780LCD 12 | @param NumRow Number of Rows/Lines in the LCD 13 | @param NumCol Number of Columns in the LCD 14 | @param I2Caddress The PCF8574 I2C address, default is 0x27. 15 | @param twi Pointer to the Wire I2C interface. 16 | */ 17 | HD44780LCD :: HD44780LCD(uint8_t NumRow, uint8_t NumCol, uint8_t I2Caddress, TwoWire *twi) 18 | { 19 | _NumRowsLCD = NumRow; 20 | _NumColsLCD = NumCol; 21 | _LCDSlaveAddresI2C = I2Caddress; 22 | wire = twi; 23 | } 24 | 25 | // Methods 26 | 27 | /*! 28 | @brief Send data byte to LCD via I2C 29 | @param data The data byte to send 30 | @note if LCD_SERIAL_DEBUG is defined , will output data on I2C failures. 31 | */ 32 | void HD44780LCD::PCF8574_LCDSendData(unsigned char data) { 33 | // I2C MASK Byte = DATA-led-en-rw-rs (en=enable rs = reg select)(rw always write) 34 | const uint8_t LCDDataByteOn= 0x0D; //enable=1 and rs =1 1101 DATA-led-en-rw-rs 35 | const uint8_t LCDDataByteOff = 0x09; // enable=0 and rs =1 1001 DATA-led-en-rw-rs 36 | 37 | unsigned char dataNibbleLower, dataNibbleUpper; 38 | uint8_t dataBufferI2C[4]; 39 | uint8_t I2CReturnCode = 0; 40 | 41 | dataNibbleLower = (data << 4)&0xf0; //select lower nibble by moving it to the upper nibble position 42 | dataNibbleUpper = data & 0xf0; //select upper nibble 43 | dataBufferI2C[0] = dataNibbleUpper | (LCDDataByteOn & _LCDBackLight); //enable=1 and rs =1 1101 YYYY-X-en-X-rs 44 | dataBufferI2C[1] = dataNibbleUpper | (LCDDataByteOff & _LCDBackLight); //enable=0 and rs =1 1001 YYYY-X-en-X-rs 45 | dataBufferI2C[2] = dataNibbleLower | (LCDDataByteOn & _LCDBackLight); //enable=1 and rs =1 1101 YYYY-X-en-X-rs 46 | dataBufferI2C[3] = dataNibbleLower | (LCDDataByteOff & _LCDBackLight); //enable=0 and rs =1 1001 YYYY-X-en-X-rs 47 | 48 | wire->beginTransmission(_LCDSlaveAddresI2C); 49 | wire->write(dataBufferI2C, 4) ; 50 | I2CReturnCode = wire->endTransmission(); 51 | if (I2CReturnCode!= 0) 52 | { 53 | #ifdef LCD_SERIAL_DEBUG 54 | Serial.print("1203 : "); 55 | Serial.print("I2C error wire.endTransmission : "); 56 | Serial.print("I2CReturnCode code : "); 57 | Serial.println(I2CReturnCode); 58 | delay(100); 59 | #endif 60 | } 61 | 62 | } 63 | 64 | /*! 65 | @brief Send command byte to lcd 66 | @param cmd command byte 67 | @note if LCD_SERIAL_DEBUG is defined will output data on I2C failures 68 | */ 69 | void HD44780LCD::PCF8574_LCDSendCmd(unsigned char cmd) { 70 | 71 | // I2C MASK Byte = COMD-led-en-rw-rs (en=enable rs = reg select)(rw always write) 72 | const uint8_t LCDCmdByteOn = 0x0C; // enable=1 and rs =0 1100 COMD-led-en-rw-rs 73 | const uint8_t LCDCmdByteOff = 0x08; // enable=0 and rs =0 1000 COMD-led-en-rw-rs 74 | 75 | unsigned char cmdNibbleLower, cmdNibbleUpper; 76 | uint8_t cmdBufferI2C[4]; 77 | uint8_t I2CReturnCode = 0; 78 | 79 | cmdNibbleLower = (cmd << 4)&0xf0; //select lower nibble by moving it to the upper nibble position 80 | cmdNibbleUpper = cmd & 0xf0; //select upper nibble 81 | cmdBufferI2C[0] = cmdNibbleUpper | (LCDCmdByteOn & _LCDBackLight); // YYYY-1100 YYYY-led-en-rw-rs ,enable=1 and rs =0 82 | cmdBufferI2C[1] = cmdNibbleUpper | (LCDCmdByteOff & _LCDBackLight); // YYYY-1000 YYYY-led-en-rw-rs ,enable=0 and rs =0 83 | cmdBufferI2C[2] = cmdNibbleLower | (LCDCmdByteOn & _LCDBackLight); // YYYY-1100 YYYY-led-en-rw-rs ,enable=1 and rs =0 84 | cmdBufferI2C[3] = cmdNibbleLower | (LCDCmdByteOff & _LCDBackLight); // YYYY-1000 YYYY-led-en-rw-rs ,enable=0 and rs =0 85 | 86 | wire->beginTransmission(_LCDSlaveAddresI2C); 87 | wire->write(cmdBufferI2C, 4) ; 88 | I2CReturnCode = wire->endTransmission(); 89 | if (I2CReturnCode != 0) 90 | { 91 | #ifdef LCD_SERIAL_DEBUG 92 | Serial.print("1202 : "); 93 | Serial.print("I2C error wire.endTransmission : "); 94 | Serial.print("I2CReturnCode: "); 95 | Serial.println(I2CReturnCode); 96 | delay(100); 97 | #endif 98 | } 99 | 100 | } 101 | 102 | /*! 103 | @brief Clear a line by writing spaces to every position 104 | @param lineNo LCDLineNumber_e enum lineNo 1-4 105 | */ 106 | void HD44780LCD::PCF8574_LCDClearLine(LCDLineNumber_e lineNo) { 107 | 108 | switch (lineNo) { 109 | case LCDLineNumberOne:PCF8574_LCDSendCmd(LCDLineAddressOne); break; 110 | case LCDLineNumberTwo:PCF8574_LCDSendCmd(LCDLineAddressTwo); break; 111 | case LCDLineNumberThree: 112 | switch (_NumColsLCD) 113 | { 114 | case 16: PCF8574_LCDSendCmd(LCDLineAddress3Col16); break; 115 | case 20: PCF8574_LCDSendCmd(LCDLineAddress3Col20); break; 116 | } 117 | break; 118 | case LCDLineNumberFour: 119 | switch (_NumColsLCD) 120 | { 121 | case 16: PCF8574_LCDSendCmd(LCDLineAddress4Col16); break; 122 | case 20: PCF8574_LCDSendCmd(LCDLineAddress4Col20); break; 123 | } 124 | break; 125 | } 126 | 127 | for (uint8_t i = 0; i < _NumColsLCD; i++) { 128 | PCF8574_LCDSendData(' '); 129 | } 130 | } 131 | 132 | /*! 133 | @brief Clear screen by writing spaces to every position 134 | @note : See also LCDClearScreenCmd for software command clear alternative. 135 | */ 136 | void HD44780LCD::PCF8574_LCDClearScreen(void) { 137 | if (_NumRowsLCD < 1 || _NumRowsLCD >4){return;} 138 | 139 | PCF8574_LCDClearLine(LCDLineNumberOne); 140 | 141 | if (_NumRowsLCD >= 2) 142 | PCF8574_LCDClearLine(LCDLineNumberTwo); 143 | if (_NumRowsLCD >= 3) 144 | PCF8574_LCDClearLine(LCDLineNumberThree); 145 | if (_NumRowsLCD == 4) 146 | PCF8574_LCDClearLine(LCDLineNumberFour); 147 | } 148 | 149 | /*! 150 | @brief Reset screen 151 | @param CursorType LCDCursorType_e enum cursor type, 4 choices 152 | */ 153 | void HD44780LCD::PCF8574_LCDResetScreen(LCDCursorType_e CursorType) { 154 | PCF8574_LCDSendCmd(LCDModeFourBit); 155 | PCF8574_LCDSendCmd(LCDDisplayOn); 156 | PCF8574_LCDSendCmd(CursorType); 157 | PCF8574_LCDSendCmd(LCDClearScreen); 158 | PCF8574_LCDSendCmd(LCDEntryModeThree); 159 | delay(5); 160 | } 161 | 162 | /*! 163 | @brief Turn Screen on and off 164 | @param OnOff True = display on , false = display off 165 | */ 166 | void HD44780LCD::PCF8574_LCDDisplayON(bool OnOff) { 167 | OnOff ? PCF8574_LCDSendCmd(LCDDisplayOn) : PCF8574_LCDSendCmd(LCDDisplayOff); 168 | delay(5); 169 | } 170 | 171 | 172 | /*! 173 | @brief Initialise LCD 174 | @param cursorType 4 choices. 175 | */ 176 | void HD44780LCD::PCF8574_LCDInit(LCDCursorType_e cursorType) { 177 | 178 | if (PCF8574_LCD_I2C_ON() != true) 179 | { 180 | delay(2000); 181 | return; 182 | } 183 | 184 | delay(15); 185 | PCF8574_LCDSendCmd(LCDHomePosition); 186 | delay(5); 187 | PCF8574_LCDSendCmd(LCDHomePosition); 188 | delay(5); 189 | PCF8574_LCDSendCmd(LCDHomePosition); 190 | delay(5); 191 | PCF8574_LCDSendCmd(LCDModeFourBit); 192 | PCF8574_LCDSendCmd(LCDDisplayOn); 193 | PCF8574_LCDSendCmd(cursorType); 194 | PCF8574_LCDSendCmd(LCDEntryModeThree); 195 | PCF8574_LCDSendCmd(LCDClearScreen); 196 | delay(5); 197 | } 198 | 199 | /*! 200 | @brief Send a string to LCD 201 | @param str Pointer to the char array 202 | */ 203 | void HD44780LCD::PCF8574_LCDSendString(char *str) { 204 | while (*str) PCF8574_LCDSendData(*str++); 205 | } 206 | 207 | /*! 208 | @brief Sends a character to screen , simply wraps SendData command. 209 | @param data Character to display 210 | */ 211 | void HD44780LCD::PCF8574_LCDSendChar(char data) { 212 | PCF8574_LCDSendData(data); 213 | } 214 | 215 | /*! 216 | @brief Moves cursor 217 | @param direction enum LCDDirectionType_e left or right 218 | @param moveSize number of spaces to move 219 | */ 220 | void HD44780LCD::PCF8574_LCDMoveCursor(LCDDirectionType_e direction, uint8_t moveSize) { 221 | uint8_t i = 0; 222 | const uint8_t LCDMoveCursorLeft = 0x10; //Command Byte Code: Move cursor one character left 223 | const uint8_t LCDMoveCursorRight = 0x14; // Command Byte Code : Move cursor one character right 224 | switch(direction) 225 | { 226 | case LCDMoveRight: 227 | for (i = 0; i < moveSize; i++) { 228 | PCF8574_LCDSendCmd(LCDMoveCursorRight); 229 | } 230 | break; 231 | case LCDMoveLeft: 232 | for (i = 0; i < moveSize; i++) { 233 | PCF8574_LCDSendCmd(LCDMoveCursorLeft); 234 | } 235 | break; 236 | } 237 | 238 | } 239 | 240 | /*! 241 | @brief Scrolls screen 242 | @param direction left or right 243 | @param ScrollSize number of spaces to scroll 244 | */ 245 | void HD44780LCD::PCF8574_LCDScroll(LCDDirectionType_e direction, uint8_t ScrollSize) { 246 | uint8_t i = 0; 247 | 248 | const uint8_t LCDScrollRight = 0x1E; // Command Byte Code: Scroll display one character right (all lines) 249 | const uint8_t LCDScrollLeft = 0x18; //Command Byte Code: Scroll display one character left (all lines) 250 | 251 | switch(direction) 252 | { 253 | case LCDMoveRight: 254 | for (i = 0; i < ScrollSize; i++) { 255 | PCF8574_LCDSendCmd(LCDScrollRight); 256 | } 257 | break; 258 | case LCDMoveLeft: 259 | for (i = 0; i < ScrollSize; i++) { 260 | PCF8574_LCDSendCmd(LCDScrollLeft); 261 | } 262 | break; 263 | } 264 | } 265 | 266 | /*! 267 | @brief moves cursor to an x , y position on display. 268 | @param line x row 1-4 269 | @param col y column 0-15 or 0-19 270 | */ 271 | void HD44780LCD::PCF8574_LCDGOTO(LCDLineNumber_e line, uint8_t col) { 272 | switch (line) { 273 | case LCDLineNumberOne: PCF8574_LCDSendCmd(LCDLineAddressOne| col); break; 274 | case LCDLineNumberTwo: PCF8574_LCDSendCmd(LCDLineAddressTwo | col); break; 275 | case LCDLineNumberThree: 276 | switch (_NumColsLCD) 277 | { 278 | case 16: PCF8574_LCDSendCmd(LCDLineAddress3Col16 | col); break; 279 | case 20: PCF8574_LCDSendCmd(LCDLineAddress3Col20 + col); break; 280 | } 281 | break; 282 | case LCDLineNumberFour: 283 | switch (_NumColsLCD) 284 | { 285 | case 16: PCF8574_LCDSendCmd(LCDLineAddress4Col16 | col); break; 286 | case 20: PCF8574_LCDSendCmd(LCDLineAddress4Col20+ col); break; 287 | } 288 | break; 289 | } 290 | } 291 | 292 | /*! 293 | @brief Saves a custom character to a location in character generator RAM 64 bytes. 294 | @param location CG_RAM location 0-7, we only have 8 locations 64 bytes 295 | @param charmap An array of 8 bytes representing a custom character data 296 | */ 297 | void HD44780LCD::PCF8574_LCDCreateCustomChar(uint8_t location, uint8_t * charmap) 298 | { 299 | 300 | const uint8_t LCD_CG_RAM = 0x40; // character-generator RAM (CG RAM address) 301 | if (location >= 8) {return;} 302 | 303 | PCF8574_LCDSendCmd(LCD_CG_RAM | (location<<3)); 304 | for (uint8_t i=0; i<8; i++) { 305 | PCF8574_LCDSendData(charmap[i]); 306 | } 307 | } 308 | 309 | /*! 310 | @brief Turn LED backlight on and off 311 | @param OnOff passed bool True = LED on , false = display LED off 312 | @note another data or command must be issued before it takes effect. 313 | */ 314 | void HD44780LCD::PCF8574_LCDBackLightSet(bool OnOff) 315 | { 316 | OnOff ? (_LCDBackLight= LCDBackLightOnMask) : (_LCDBackLight= LCDBackLightOffMask); 317 | } 318 | 319 | /*! 320 | @brief get the backlight flag status 321 | @return the status of backlight on or off , true or false. 322 | */ 323 | bool HD44780LCD::PCF8574_LCDBackLightGet(void) 324 | { 325 | switch(_LCDBackLight){ 326 | case LCDBackLightOnMask : return true; break; 327 | case LCDBackLightOffMask: return false; break; 328 | default : return true ; break ; 329 | } 330 | } 331 | 332 | /*! 333 | @brief Switch on the I2C 334 | @returns false if PCF8574 fails to appear on I2C bus , true if ok 335 | @note if LCD_SERIAL_DEBUG enabled will print I2C error code to screen 336 | wire.endTransmission() return: 337 | 0 : Success 338 | 1 : Data length error 339 | 2 : NACK on transmit of the address. 340 | 3 : NACK on transmit of the data. 341 | 4 : Some other error 342 | */ 343 | bool HD44780LCD::PCF8574_LCD_I2C_ON() 344 | { 345 | uint8_t I2CReturnCode= 0; 346 | 347 | wire->begin(); 348 | wire->beginTransmission(_LCDSlaveAddresI2C); 349 | I2CReturnCode = wire->endTransmission(); 350 | if (I2CReturnCode!= 0) 351 | { 352 | #ifdef LCD_SERIAL_DEBUG 353 | Serial.print("1201 : "); 354 | Serial.print("I2C error wire.endTransmission : "); 355 | Serial.print("I2CReturnCode: "); 356 | Serial.println(I2CReturnCode); 357 | #endif 358 | return false; //Check if the PCF8574 is connected 359 | }else{ 360 | #ifdef LCD_SERIAL_DEBUG 361 | Serial.print("I2C Success Init : "); 362 | #endif 363 | return true; 364 | } 365 | } 366 | 367 | /*! 368 | @brief Print out a customer character from character generator CGRAM 64 bytes 8 characters 369 | @param location CGRAM 0-7 370 | */ 371 | void HD44780LCD::PCF8574_LCDPrintCustomChar(uint8_t location) 372 | { 373 | if (location >= 8) {return;} 374 | PCF8574_LCDSendData(location); 375 | } 376 | 377 | /*! 378 | @brief Called by print class, used to print out numerical data types etc 379 | @param character write a character 380 | @note used internally. Called by the print method using virtual 381 | */ 382 | size_t HD44780LCD::write(uint8_t character) 383 | { 384 | PCF8574_LCDSendChar(character) ; 385 | return 1; 386 | } 387 | 388 | /*! 389 | @brief Clear display using software command , set cursor position to zero 390 | @note See also LCDClearScreen for manual clear 391 | */ 392 | void HD44780LCD::PCF8574_LCDClearScreenCmd(void) { 393 | PCF8574_LCDSendCmd(LCDClearScreen); 394 | delay(3); // Requires a delay 395 | } 396 | 397 | 398 | /*! 399 | @brief Set cursor position to home position . 400 | */ 401 | void HD44780LCD::PCF8574_LCDHome(void) { 402 | PCF8574_LCDSendCmd(LCDHomePosition); 403 | delay(3); // Requires a delay 404 | } 405 | 406 | /*! 407 | @brief Change entry mode 408 | @param newEntryMode 1-4 , 4 choices. 409 | */ 410 | void HD44780LCD::PCF8574_LCDChangeEntryMode(LCDEntryMode_e newEntryMode) 411 | { 412 | PCF8574_LCDSendCmd(newEntryMode); 413 | delay(3); // Requires a delay 414 | } 415 | 416 | // **** EOF **** 417 | --------------------------------------------------------------------------------