P012 - Fix/handle lines exceeding LCD width + allow to clear line b4 print (#852)

* Update Library LiquidCrystal_I2C to the latest version

* Fix LCD command (when message is longer than columns) that get split into the wrong lines - issue #603

* Added a "LCD command mode" parameter to handle how exceeding message would be treated, and if the line should be first padded with space.
This commit is contained in:
soif
2018-02-13 01:03:24 +01:00
committed by DatuX
parent 11b1c8505a
commit b293e8fee0
11 changed files with 153 additions and 101 deletions
+21 -11
View File
@@ -1,11 +1,4 @@
//www.DFRobot.com
//last updated on 21/12/2011
//Tim Starling Fix the reset bug (Thanks Tim)
//wiki doc http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)
//Support Forum: http://www.dfrobot.com/forum/
//Compatible with the Arduino IDE 1.0
//Library version:1.1
// Based on the work by DFRobot
#include "LiquidCrystal_I2C.h"
#include <inttypes.h>
@@ -16,7 +9,7 @@
#define printIIC(args) Wire.write(args)
inline size_t LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
return 0;
return 1;
}
#else
@@ -59,6 +52,11 @@ LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t l
_backlightval = LCD_NOBACKLIGHT;
}
void LiquidCrystal_I2C::oled_init(){
_oled = true;
init_priv();
}
void LiquidCrystal_I2C::init(){
init_priv();
}
@@ -134,6 +132,7 @@ void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
void LiquidCrystal_I2C::clear(){
command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
if (_oled) setCursor(0,0);
}
void LiquidCrystal_I2C::home(){
@@ -221,6 +220,15 @@ void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
}
}
//createChar with PROGMEM input
void LiquidCrystal_I2C::createChar(uint8_t location, const char *charmap) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(pgm_read_byte_near(charmap++));
}
}
// Turn the (optional) backlight off/on
void LiquidCrystal_I2C::noBacklight(void) {
_backlightval=LCD_NOBACKLIGHT;
@@ -309,6 +317,8 @@ void LiquidCrystal_I2C::printstr(const char c[]){
// unsupported API functions
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
void LiquidCrystal_I2C::off(){}
void LiquidCrystal_I2C::on(){}
void LiquidCrystal_I2C::setDelay (int cmdDelay,int charDelay) {}
@@ -318,5 +328,5 @@ uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype){return 0;}
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end){}
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end){}
void LiquidCrystal_I2C::setContrast(uint8_t new_val){}
#pragma GCC diagnostic pop
+7 -2
View File
@@ -1,4 +1,4 @@
//DFRobot.com
//YWROBOT
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h
@@ -77,14 +77,18 @@ public:
void autoscroll();
void noAutoscroll();
void createChar(uint8_t, uint8_t[]);
void createChar(uint8_t location, const char *charmap);
// Example: const char bell[8] PROGMEM = {B00100,B01110,B01110,B01110,B11111,B00000,B00100,B00000};
void setCursor(uint8_t, uint8_t);
#if defined(ARDUINO) && ARDUINO >= 100
#if defined(ARDUINO) && ARDUINO >= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif
void command(uint8_t);
void init();
void oled_init();
////compatibility API function aliases
void blink_on(); // alias for blink()
@@ -118,6 +122,7 @@ private:
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _numlines;
bool _oled = false;
uint8_t _cols;
uint8_t _rows;
uint8_t _backlightval;
+2
View File
@@ -0,0 +1,2 @@
# LiquidCrystal_I2C
LiquidCrystal Arduino library for the DFRobot I2C LCD displays
-69
View File
@@ -1,69 +0,0 @@
1,6c1
< //www.DFRobot.com
< //last updated on 26/11/2010
< //Tim Starling Fix the reset bug (Thanks Tim)
< //wiki doc http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)
< //Support Forum: http://www.dfrobot.com/forum/
<
---
> // LiquidCrystal_I2C V2.0
10d4
< #include "WProgram.h"
12c6
<
---
> #include "Arduino.h"
67c61
< delay(50);
---
> delayMicroseconds(50000);
77,90c71,84
< // we start in 8bit mode, try to set 4 bit mode
< write4bits(0x03 << 4);
< delayMicroseconds(4500); // wait min 4.1ms
<
< // second try
< write4bits(0x03 << 4);
< delayMicroseconds(4500); // wait min 4.1ms
<
< // third go!
< write4bits(0x03 << 4);
< delayMicroseconds(150);
<
< // finally, set to 4-bit interface
< write4bits(0x02 << 4);
---
> // we start in 8bit mode, try to set 4 bit mode
> write4bits(0x03);
> delayMicroseconds(4500); // wait min 4.1ms
>
> // second try
> write4bits(0x03);
> delayMicroseconds(4500); // wait min 4.1ms
>
> // third go!
> write4bits(0x03);
> delayMicroseconds(150);
>
> // finally, set to 4-bit interface
> write4bits(0x02);
225c219
< inline void LiquidCrystal_I2C::write(uint8_t value) {
---
> inline size_t LiquidCrystal_I2C::write(uint8_t value) {
226a221
> return 0;
235,238c230,233
< uint8_t highnib=value&0xf0;
< uint8_t lownib=(value<<4)&0xf0;
< write4bits((highnib)|mode);
< write4bits((lownib)|mode);
---
> uint8_t highnib=value>>4;
> uint8_t lownib=value & 0x0F;
> write4bits((highnib)|mode);
> write4bits((lownib)|mode);
248c243
< Wire.send((int)(_data) | _backlightval);
---
> Wire.write((int)(_data) | _backlightval);
+4 -4
View File
@@ -1,4 +1,4 @@
//DFRobot.com
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
@@ -19,7 +19,7 @@ uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
@@ -52,7 +52,7 @@ void displayKeyCodes(void) {
while (1) {
lcd.clear();
lcd.print("Codes 0x"); lcd.print(i, HEX);
lcd.print("-0x"); lcd.print(i+16, HEX);
lcd.print("-0x"); lcd.print(i+15, HEX);
lcd.setCursor(0, 1);
for (int j=0; j<16; j++) {
lcd.printByte(i+j);
@@ -67,4 +67,4 @@ void loop()
{
}
+11 -3
View File
@@ -1,20 +1,28 @@
//DFRobot.com
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
lcd.init(); // initialize the lcd
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(3,0);
lcd.print("Hello, world!");
lcd.setCursor(2,1);
lcd.print("Ywrobot Arduino!");
lcd.setCursor(0,2);
lcd.print("Arduino LCM IIC 2004");
lcd.setCursor(2,3);
lcd.print("Power By Ec-yuan!");
}
void loop()
{
}
+2 -2
View File
@@ -1,14 +1,14 @@
/*
* Displays text sent over the serial port (e.g. from the Serial Monitor) on
* an attached LCD.
* DFRobot.com
* YWROBOT
*Compatible with the Arduino IDE 1.0
*Library version:1.1
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
View File
+16
View File
@@ -0,0 +1,16 @@
{
"name": "LiquidCrystal_I2C",
"keywords": "LCD, liquidcrystal, I2C",
"description": "A library for DFRobot I2C LCD displays",
"repository":
{
"type": "git",
"url": "https://github.com/marcoschwartz/LiquidCrystal_I2C.git"
},
"frameworks": "arduino",
"platforms":
[
"atmelavr",
"espressif8266"
]
}
+9
View File
@@ -0,0 +1,9 @@
name=LiquidCrystal_I2C
version=1.1.4
author=Frank de Brabander
maintainer=Marco Schwartz <marcolivier.schwartz@gmail.com>
sentence=A library for I2C LCD displays.
paragraph= The library allows to control I2C displays with functions extremely similar to LiquidCrystal library. THIS LIBRARY MIGHT NOT BE COMPATIBLE WITH EXISTING SKETCHES.
category=Display
url=https://github.com/marcoschwartz/LiquidCrystal_I2C
architectures=avr
+81 -10
View File
@@ -68,6 +68,7 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
}
addFormSelectorI2C(string, F("plugin_012_adr"), 16, optionValues, choice);
byte choice2 = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
String options2[2];
options2[0] = F("2 x 16");
@@ -75,6 +76,7 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
int optionValues2[2] = { 1, 2 };
addFormSelector(string, F("Display Size"), F("plugin_012_size"), 2, options2, optionValues2, choice2);
char deviceTemplate[4][80];
LoadCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
for (byte varNr = 0; varNr < 4; varNr++)
@@ -88,14 +90,23 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
string += F("'>");
}
string += F("<TR><TD>Display button:<TD>");
addRowLabel(string, "Display button");
addPinSelect(false, string, "taskdevicepin3", Settings.TaskDevicePin3[event->TaskIndex]);
char tmpString[128];
char tmpString[128];
sprintf_P(tmpString, PSTR("<TR><TD>Display Timeout:<TD><input type='text' name='plugin_12_timer' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
string += tmpString;
String options3[3];
options3[0] = F("Continue to next line (as in v1.4)");
options3[1] = F("Truncate exceeding message");
options3[2] = F("Clear then truncate exceeding message");
int optionValues3[3] = { 0,1,2 };
addFormSelector(string, F("LCD command Mode"), F("plugin_012_mode"), 3, options3, optionValues3, Settings.TaskDevicePluginConfig[event->TaskIndex][3]);
success = true;
break;
}
@@ -105,6 +116,7 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_012_adr"));
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_012_size"));
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_12_timer"));
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = getFormItemInt(F("plugin_012_mode"));
char deviceTemplate[4][80];
for (byte varNr = 0; varNr < 4; varNr++)
@@ -201,29 +213,88 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
case PLUGIN_WRITE:
{
byte rows = 2;
byte cols = 16;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 2){
rows = 4;
cols = 20;
}
String tmpString = string;
int argIndex = tmpString.indexOf(',');
if (argIndex)
tmpString = tmpString.substring(0, argIndex);
if (lcd && tmpString.equalsIgnoreCase(F("LCD")))
{
success = true;
argIndex = string.lastIndexOf(',');
tmpString = string.substring(argIndex + 1);
lcd->setCursor(event->Par2 - 1, event->Par1 - 1);
lcd->print(tmpString.c_str());
int colPos = event->Par2 - 1;
int rowPos = event->Par1 - 1;
//clear line before writing new string
if (Settings.TaskDevicePluginConfig[event->TaskIndex][3] == 2){
lcd->setCursor(colPos, rowPos);
for (byte i = colPos; i < cols; i++) {
lcd->print(F(" "));
}
}
// truncate message exceeding cols
lcd->setCursor(colPos, rowPos);
if(Settings.TaskDevicePluginConfig[event->TaskIndex][3] == 1 || Settings.TaskDevicePluginConfig[event->TaskIndex][3] == 2){
lcd->setCursor(colPos, rowPos);
for (byte i = 0; i < cols - colPos; i++) {
if(tmpString[i]){
lcd->print(tmpString[i]);
}
}
}
// message exceeding cols will continue to next line
else{
// Fix Weird (native) lcd display behaviour that split long string into row 1,3,2,4, instead of 1,2,3,4
boolean stillProcessing = 1;
byte charCount = 1;
while(stillProcessing) {
if (++colPos > cols) { // have we printed 20 characters yet (+1 for the logic)
rowPos += 1;
lcd->setCursor(0,rowPos); // move cursor down
colPos = 1;
}
//dont print if "lower" than the lcd
if(rowPos < rows ){
lcd->print(tmpString[charCount - 1]);
}
if (!tmpString[charCount]) { // no more chars to process?
stillProcessing = 0;
}
charCount += 1;
}
//lcd->print(tmpString.c_str());
// end fix
}
}
if (lcd && tmpString.equalsIgnoreCase(F("LCDCMD")))
{
success = true;
argIndex = string.lastIndexOf(',');
tmpString = string.substring(argIndex + 1);
if (tmpString.equalsIgnoreCase(F("Off")))
lcd->noBacklight();
else if (tmpString.equalsIgnoreCase(F("On")))
lcd->backlight();
else if (tmpString.equalsIgnoreCase(F("Clear")))
lcd->clear();
if (tmpString.equalsIgnoreCase(F("Off"))){
lcd->noBacklight();
}
else if (tmpString.equalsIgnoreCase(F("On"))){
lcd->backlight();
}
else if (tmpString.equalsIgnoreCase(F("Clear"))){
lcd->clear();
}
}
break;
}