From 9490694a34de646583f7844d03008cd0d4b325b5 Mon Sep 17 00:00:00 2001 From: gavin Lyons Date: Wed, 27 Dec 2023 15:55:13 +0000 Subject: [PATCH] v 1.3.2 --- README.md | 22 +++---- examples/Makefile | 1 + examples/src/HELLO_16x02/main.cpp | 6 +- examples/src/TEST_I2C_16x02/main.cpp | 95 ++++++++++++++++++++++++++++ include/HD44780_LCD.hpp | 7 ++ src/HD44780_LCD.cpp | 77 +++++++++++++++++----- 6 files changed, 177 insertions(+), 31 deletions(-) create mode 100644 examples/src/TEST_I2C_16x02/main.cpp diff --git a/README.md b/README.md index 8c83c7f..af78bb5 100644 --- a/README.md +++ b/README.md @@ -34,20 +34,19 @@ * Author: Gavin Lyons * Development Tool chain. 1. Raspberry PI 3 model b - 2. C++, g++ (Raspbian 8.3.0-6+rpi1) 8.3.0 - 3. Raspbian 10 Buster OS, armv7l Linux 5.10.63-v7+ , 32 bit. - 4. bcm2835 Library 1.73 (dependency) + 2. C++, g++ (Debian 12.2.0) + 3. Raspbian , Debian 12 bookworm OS, , 64 bit. + 3. kernel : aarch64 Linux 6.1.0-rpi7-rpi-v8 + 4. bcm2835 Library 1.73 dependency. Provides low level I2C bus, delays and GPIO control. ## Installation -1. Make sure I2C bus is enabled on your raspberry PI -2. Install the dependency bcm2835 Library if not installed (at time of writing latest version is 1.73.) - * The bcm2835 library is a dependency and provides low level I2C bus, delays and GPIO control. +1. Install the dependency bcm2835 Library if not installed (at time of writing latest version is 1.73.) * Install the C libraries of bcm2835, [Installation instructions here](http://www.airspayce.com/mikem/bcm2835/) -3. Download the HD44780_LCD_RPI library +2. Download the HD44780_LCD_RPI library * Open a Terminal in a folder where you want to download,build & test library * Run following command to download from github. @@ -55,7 +54,7 @@ curl -sL https://github.com/gavinlyonsrepo/HD44780_LCD_RPI/archive/1.3.2.tar.gz | tar xz ``` -4. Run "make" to run the makefile in repo base folder to install library, it will be +3. Run "make" to run the makefile in repo base folder to install library, it will be installed to usr/lib and usr/include ```sh @@ -77,7 +76,7 @@ make make run ``` -2. There are 4 examples files. +2. There are 5 examples files. To decide which one the makefile builds simply edit "SRC" variable at top of the makefile in examples folder. in the "User SRC directory Option Section". Pick an example "SRC" directory path and ONE ONLY. Comment out the rest and repeat: make & make run. @@ -88,6 +87,7 @@ Comment out the rest and repeat: make & make run. | src/TEST_16x02 | Carries out test sequence testing features | 16x02 | | src/TEST_20x04 | Carries out test sequence testing features | 20x04 | | src/CLOCK_16x02 | A basic clock Demo | 16x02 | +| src/TEST_I2C_16x02 | Check I2C connection | 16x02 | ## Hardware @@ -130,8 +130,8 @@ User can turn on debug messages with LCDDebugSet method see example file. ### API -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. This API is for the Arduino source port. It is very similar -expect constructor, init and de-init I2C method's will be different. +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. *NOTE :: This API is for the Arduino source port*. It is very similar +expect constructor, I2C method's will be different. [Software API Url Link](https://gavinlyonsrepo.github.io/misc/software_docs/HD44780_LCD_PCF8574/index.html) diff --git a/examples/Makefile b/examples/Makefile index 26f41b4..38cfc33 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -18,6 +18,7 @@ SRC=src/HELLO_16x02 #SRC=src/TEST_16x02 #SRC=src/TEST_20x04 #SRC=src/CLOCK_16x02 +#SRC=src/TEST_I2C_16x02 # ************************************************ diff --git a/examples/src/HELLO_16x02/main.cpp b/examples/src/HELLO_16x02/main.cpp index 338a4cc..ca903db 100644 --- a/examples/src/HELLO_16x02/main.cpp +++ b/examples/src/HELLO_16x02/main.cpp @@ -2,7 +2,7 @@ @file main.cpp @author Gavin Lyons @brief - This file contains the "main" function for project, a set of test sequence + This file contains the "main" function for project, Hello world to test the HD44780_LCD_RPI library @note @@ -17,7 +17,7 @@ // Section: Globals // myLCD(rows , cols , PCF8574 I2C address, I2C speed) -HD44780PCF8574LCD myLCD(2, 16, 0x27, 148); // instantiate an object +HD44780PCF8574LCD myLCD(2, 16, 0x27, 0); // instantiate an object // Section: Function Prototypes bool setup(void); @@ -52,7 +52,7 @@ bool setup(void) { std::cout << "Error 1202: bcm2835_i2c_begin :Cannot start I2C, Running as root?" << std::endl; return false; } - + myLCD.LCDDebugSet(false); myLCD.LCD_I2C_SetSpeed(); myLCD.LCDInit(myLCD.LCDCursorTypeOn); myLCD.LCDClearScreen(); diff --git a/examples/src/TEST_I2C_16x02/main.cpp b/examples/src/TEST_I2C_16x02/main.cpp new file mode 100644 index 0000000..c839a80 --- /dev/null +++ b/examples/src/TEST_I2C_16x02/main.cpp @@ -0,0 +1,95 @@ +/*! + @file main.cpp + @author Gavin Lyons + @brief + This file contains the "main" function for project, I2C test + to test the HD44780_LCD_RPI library + + @note + -# Test 901 :: I2c Test +*/ + +// Section: Included library +#include +#include +#include "HD44780_LCD.hpp" + + +// Section: Globals +// myLCD(rows , cols , PCF8574 I2C address, I2C speed) +HD44780PCF8574LCD myLCD(2, 16, 0x27, 0); // instantiate an object + +// Section: Function Prototypes +bool setup(void); +void helloWorld(void); +void endTest(void); + +// Section: Main Loop +int main(int argc, char **argv) +{ + if (!setup()) return -1; + helloWorld(); + endTest(); + return 0; +} + +// Section : Functions + +bool setup(void) { + std::cout << "LCD Test Begin" << std::endl; + + // Check if Bcm28235 lib installed and print version. + if(!bcm2835_init()) + { + std::cout << "Error 1201: init bcm2835 library , Is it installed ?" << std::endl; + return false; + } + + // Turn on I2C bus (optionally it may already be on) + if (!myLCD.LCD_I2C_ON()) + { + std::cout << "Error 1202: bcm2835_i2c_begin :Cannot start I2C, Running as root?" << std::endl; + return false; + } + + bcm2835_delay(1000); + myLCD.LCDDebugSet(true); // Turn debug messages on + myLCD.LCD_I2C_SetSpeed(); + if (myLCD.LCDCheckConnection() != 0) + { + std::cout << "Error 1203: bcm2835_i2c_begin :LCD not on bus?" << std::endl; + return false; + } + + // print out library versions & flag status( Note optional) + std::cout << "bcm2835 library Version Number :" << bcm2835_version() << std::endl; + std::cout << "HD44780_LCD_RPI lib Version Num :" << myLCD.LCDVerNumGet() << std::endl; + std::cout << "Debug status is : " << (myLCD.LCDDebugGet() ? "On" : "Off") << std::endl ; + std::cout << "Backlight status is : " << (myLCD.LCDBackLightGet() ? "On" : "Off") << std::endl ; + std::cout << "I2C Debug Error : " << myLCD.LCDI2CErrorGet() << std::endl; // Print I2C error flag + std::cout << "I2C Error Timeout mS : " << myLCD.LCDI2CErrorTimeoutGet() << std::endl; // Print I2C Timeout + + myLCD.LCDInit(myLCD.LCDCursorTypeOn); + myLCD.LCDClearScreen(); + return true; +} + +void helloWorld(void) +{ + char testString[] = "I2C Test"; + myLCD.LCDGOTO(myLCD.LCDLineNumberOne, 0); + myLCD.LCDSendString(testString); + bcm2835_delay(5000); +} + + +void endTest() +{ + myLCD.LCDDisplayON(false); //Switch off display + myLCD.LCD_I2C_OFF(); // Switch off I2C , optional. + bcm2835_close(); // Close the library + std::cout << "LCD Test End" << std::endl ; +} + +// *** EOF *** + diff --git a/include/HD44780_LCD.hpp b/include/HD44780_LCD.hpp index 4ac3032..7e6c076 100644 --- a/include/HD44780_LCD.hpp +++ b/include/HD44780_LCD.hpp @@ -76,6 +76,10 @@ class HD44780PCF8574LCD : public Print{ bool LCD_I2C_ON(void); void LCD_I2C_SetSpeed(void); void LCD_I2C_OFF(void); + int16_t LCDCheckConnection(void); + bool LCDI2CErrorGet(void); + uint16_t LCDI2CErrorTimeoutGet(void); + void LCDI2CErrorTimeoutSet(uint16_t); void LCDSendString (char *str); void LCDSendChar (char data); @@ -125,6 +129,9 @@ class HD44780PCF8574LCD : public Print{ const uint8_t LCD_I2C_ADDRESS = 0x27; /**< Default I2C address for I2C module PCF8574 backpack on LCD */ uint8_t _LCDSlaveAddresI2C = LCD_I2C_ADDRESS ; /**< I2C address for I2C module PCF8574 backpack on LCD*/ uint16_t _LCDSpeedI2C = 0x00; /**< I2C speed default 0(100K) or BCM2835_I2C_CLOCK_DIVIDER enum values */ + uint16_t _I2C_ErrorDelay = 100; /**= 3) break; + _I2C_Error = ReasonCodes; + attemptI2Cwrite--; + if (attemptI2Cwrite == 0) break; } + _I2C_Error = ReasonCodes; } /*! @@ -88,9 +89,10 @@ void HD44780PCF8574LCD::LCDSendCmd(unsigned char cmd) { const uint8_t LCDCmdByteOn = 0x0C; // enable=1 and rs =0 1100 COMD-led-en-rw-rs const uint8_t LCDCmdByteOff = 0x08; // enable=0 and rs =0 1000 COMD-led-en-rw-rs + unsigned char cmdNibbleLower, cmdNibbleUpper; char cmdBufferI2C[4]; - uint8_t attemptI2Cwrite = 0; + uint8_t attemptI2Cwrite = 3; cmdNibbleLower = (cmd << 4)&0xf0; //select lower nibble by moving it to the upper nibble position cmdNibbleUpper = cmd & 0xf0; //select upper nibble @@ -101,20 +103,20 @@ void HD44780PCF8574LCD::LCDSendCmd(unsigned char cmd) { // bcm2835I2CReasonCodes, BCM2835_I2C_REASON_OK 0x00 = Success uint8_t ReasonCodes = bcm2835_i2c_write(cmdBufferI2C, 4); - while(ReasonCodes != 0) { if (_DebugON == true) { std::cout << "Error 602: I2C Command bcm2835I2CReasonCodes : " << +ReasonCodes << std::endl; - std::cout << "Attempt : " << +attemptI2Cwrite << std::endl; - bcm2835_delay(100); - attemptI2Cwrite++; + std::cout << "Attempt Count : " << +attemptI2Cwrite << std::endl; } - ReasonCodes = bcm2835_i2c_write(cmdBufferI2C, 4); // retransmit - bcm2835_delay(25); - if (attemptI2Cwrite >= 3) break; + bcm2835_delay(_I2C_ErrorDelay); + ReasonCodes = bcm2835_i2c_write(cmdBufferI2C,4); // retransmit + _I2C_Error = ReasonCodes; + attemptI2Cwrite--; + if (attemptI2Cwrite == 0) break; } + _I2C_Error = ReasonCodes; } /*! @@ -462,7 +464,7 @@ void HD44780PCF8574LCD::LCDChangeEntryMode(LCDEntryMode_e newEntryMode) /*! @brief Turn DEBUG mode on or off setter - @param passed bool True = debug on , false = debug off + @param OnOff passed bool True = debug on , false = debug off @note prints out statements, if ON and if errors occur */ void HD44780PCF8574LCD::LCDDebugSet(bool OnOff) @@ -483,4 +485,45 @@ bool HD44780PCF8574LCD::LCDDebugGet(void) { return _DebugON;} int16_t HD44780PCF8574LCD::LCDVerNumGet(void){return _LibVersionNum;} +/*! + @brief get I2C error Flag + @return I2C error flag = 0x00 no error , > 0 bcm2835I2Creasoncode. +*/ +bool HD44780PCF8574LCD::LCDI2CErrorGet(void) { return _I2C_Error;} + +/*! + @brief Sets the I2C timeout in the event of an I2C write error + @param newTimeOut I2C timeout delay in mS +*/ +void HD44780PCF8574LCD::LCDI2CErrorTimeoutSet(uint16_t newTimeout) +{ + _I2C_ErrorDelay = newTimeout; +} + +/*! + @brief Sets the I2C timeout in the event of an I2C write error + @return I2C timeout delay in mS, _I2C_ErrorDelay +*/ +uint16_t HD44780PCF8574LCD::LCDI2CErrorTimeoutGet(void) +{ + return _I2C_ErrorDelay; +} + +/*! + @brief checks if LCD on I2C bus + @return bcm2835I2CReasonCodes , BCM2835_I2C_REASON_OK 0x00 = Success +*/ +int16_t HD44780PCF8574LCD::LCDCheckConnection(void) +{ + int16_t returnValue; + char rxdata[1]; //buffer to hold return byte + + bcm2835_i2c_setSlaveAddress(_LCDSlaveAddresI2C); // set i2c address + returnValue = bcm2835_i2c_read(rxdata, 1); // returns reason code , 0 success + + _I2C_Error = returnValue; + return returnValue; +} + + // **** EOF ****