Skip to content

Commit 426468c

Browse files
authored
Merge pull request #27 from uutzinger/master
Enable using non-default i2c port. New example.
2 parents d628d76 + 4016ab0 commit 426468c

File tree

3 files changed

+94
-20
lines changed

3 files changed

+94
-20
lines changed

examples/LCD_Burnin/LCD_Burnin.ino

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// LCD with i2c backpack test
2+
// This replaces the contents of an LCD screen with the contents of a buffer
3+
// Urs Utzinger, 2020
4+
5+
#include "LiquidCrystal_PCF8574.h"
6+
#include <Wire.h>
7+
8+
TwoWire Wire_1 = TwoWire();
9+
10+
LiquidCrystal_PCF8574 lcd(0x27); // set the LCD address to 0x27
11+
char lcdDisplay[4][20]; // 4 lines of 20 character buffer
12+
13+
void setup()
14+
{
15+
Wire_1.begin(D1, D2); // custom i2c port on ESP
16+
Wire_1.setClock(100000); // standard 100kHz speed
17+
Wire_1.setClockStretchLimit(200000); // some devices might need clock stretching
18+
lcd.begin(20,4, Wire_1);
19+
lcd.setBacklight(255);
20+
}
21+
22+
void loop()
23+
{
24+
char lcdbuf[21];
25+
const char someLine[] = "0123456789ABCDEF1234"; // 20 chars
26+
27+
// fill the screen buffer
28+
strncpy(&lcdDisplay[0][0], someLine , 20);
29+
strncpy(&lcdDisplay[1][0], someLine , 20);
30+
strncpy(&lcdDisplay[2][0], someLine , 20);
31+
strncpy(&lcdDisplay[3][0], someLine , 20);
32+
// prepare screen
33+
lcd.home();
34+
lcd.clear();
35+
lcd.setCursor(0, 0);
36+
// copy the buffer to the screen
37+
// 1st line continues at 3d line
38+
// 2nd line continues at 4th line
39+
strncpy(lcdbuf, &lcdDisplay[0][0], 20); lcdbuf[20] = '\0'; // create a termineted text line
40+
lcd.print(lcdbuf); // print the line to screen
41+
strncpy(lcdbuf, &lcdDisplay[2][0], 20); lcdbuf[20] = '\0';
42+
lcd.print(lcdbuf);
43+
strncpy(lcdbuf, &lcdDisplay[1][0], 20); lcdbuf[20] = '\0';
44+
lcd.print(lcdbuf);
45+
strncpy(lcdbuf, &lcdDisplay[3][0], 20); lcdbuf[20] = '\0';
46+
lcd.print(lcdbuf);
47+
48+
delay(50); // keep artifically short to test if screen corrupts with frequent writes
49+
}

src/LiquidCrystal_PCF8574.cpp

+16-14
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ void LiquidCrystal_PCF8574::init(uint8_t i2cAddr, uint8_t rs, uint8_t rw, uint8_
5656
} // init()
5757

5858

59-
void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines)
59+
void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines, TwoWire &wirePort)
6060
{
61+
_i2cPort = &wirePort; //Grab which port the user wants us to use
62+
6163
_cols = min(cols, (uint8_t)80);
6264
_lines = min(lines, (uint8_t)4);
6365

@@ -73,7 +75,7 @@ void LiquidCrystal_PCF8574::begin(uint8_t cols, uint8_t lines)
7375
}
7476

7577
// initializing the display
76-
Wire.begin();
78+
_i2cPort->begin();
7779
_write2Wire(0x00, LOW, false);
7880
delayMicroseconds(50000);
7981

@@ -245,7 +247,7 @@ void LiquidCrystal_PCF8574::setBacklight(uint8_t brightness)
245247

246248
// Allows us to fill the first 8 CGRAM locations
247249
// with custom characters
248-
void LiquidCrystal_PCF8574::createChar(uint8_t location, byte charmap[])
250+
void LiquidCrystal_PCF8574::createChar(uint8_t location, uint8_t charmap[])
249251
{
250252
location &= 0x7; // we only have 8 locations 0-7
251253
// Set CGRAM address
@@ -259,12 +261,12 @@ void LiquidCrystal_PCF8574::createChar(uint8_t location, byte charmap[])
259261
#ifdef __AVR__
260262
// Allows us to fill the first 8 CGRAM locations
261263
// with custom characters stored in PROGMEM
262-
void LiquidCrystal_PCF8574::createChar_P(uint8_t location, const byte *charmap) {
264+
void LiquidCrystal_PCF8574::createChar_P(uint8_t location, const uint8_t *charmap) {
263265
PGM_P p = reinterpret_cast<PGM_P>(charmap);
264266
location &= 0x7; // we only have 8 locations 0-7
265267
_send(0x40 | (location << 3));
266268
for (int i = 0; i < 8; i++) {
267-
byte c = pgm_read_byte(p++);
269+
uint8_t c = pgm_read_byte(p++);
268270
write(c);
269271
}
270272
} // createChar_P()
@@ -285,12 +287,12 @@ void LiquidCrystal_PCF8574::_send(uint8_t value, bool isData)
285287
// An I2C transmission has a significant overhead of ~10+1 I2C clock
286288
// cycles. We consequently only perform it only once per _send().
287289

288-
Wire.beginTransmission(_i2cAddr);
290+
_i2cPort->beginTransmission(_i2cAddr);
289291
// write high 4 bits
290292
_writeNibble((value >> 4 & 0x0F), isData);
291293
// write low 4 bits
292294
_writeNibble((value & 0x0F), isData);
293-
Wire.endTransmission();
295+
_i2cPort->endTransmission();
294296
} // _send()
295297

296298

@@ -317,19 +319,19 @@ void LiquidCrystal_PCF8574::_writeNibble(uint8_t halfByte, bool isData)
317319
// when the I2C bus is operated beyond the chip's spec in fast mode
318320
// at 400 kHz.
319321

320-
Wire.write(data | _enable_mask);
322+
_i2cPort->write(data | _enable_mask);
321323
// delayMicroseconds(1); // enable pulse must be >450ns
322-
Wire.write(data);
324+
_i2cPort->write(data);
323325
// delayMicroseconds(37); // commands need > 37us to settle
324326
} // _writeNibble
325327

326328

327329
// write a nibble / halfByte with handshake
328330
void LiquidCrystal_PCF8574::_sendNibble(uint8_t halfByte, bool isData)
329331
{
330-
Wire.beginTransmission(_i2cAddr);
332+
_i2cPort->beginTransmission(_i2cAddr);
331333
_writeNibble(halfByte, isData);
332-
Wire.endTransmission();
334+
_i2cPort->endTransmission();
333335
} // _sendNibble
334336

335337

@@ -344,9 +346,9 @@ void LiquidCrystal_PCF8574::_write2Wire(uint8_t data, bool isData, bool enable)
344346
if (_backlight > 0)
345347
data |= _backlight_mask;
346348

347-
Wire.beginTransmission(_i2cAddr);
348-
Wire.write(data);
349-
Wire.endTransmission();
349+
_i2cPort->beginTransmission(_i2cAddr);
350+
_i2cPort->write(data);
351+
_i2cPort->endTransmission();
350352
} // write2Wire
351353

352354
// The End.

src/LiquidCrystal_PCF8574.h

+29-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define LiquidCrystal_PCF8574_h
2828

2929
#include "Arduino.h"
30+
#include <Wire.h>
3031
#include "Print.h"
3132
#include <stddef.h>
3233
#include <stdint.h>
@@ -37,8 +38,27 @@ class LiquidCrystal_PCF8574 : public Print
3738
public:
3839
LiquidCrystal_PCF8574(uint8_t i2cAddr);
3940
// note:
40-
// There is no sda and scl parameter for i2c in any api.
41-
// The Wire library has standard settings that can be overwritten by using Wire.begin(int sda, int scl) before calling LiquidCrystal_PCF8574::begin();
41+
//
42+
// When using multiple I2C ports one can initialize with
43+
// LiquidCrystal_PCF8574 lcd(0x27); // create lcd
44+
// TwoWire myWire = TwoWire(); // create new wire instance
45+
// myWire.begin(sdaPin, sclPin); // define SDA and SCL pins
46+
// myWire.setClock(100000); // I2C speed 100kHz
47+
// myWire.setClockStretchLimit(200000); // I2C clock stretch to 200ms for slow devices
48+
// lcd_port = &myWire; // Keep address to wire instance
49+
// lcd.begin(clos, rows, *lcd_port); // Initialize lcd
50+
//
51+
// and in the main program one updates display with
52+
// # if defined(ESP8266)
53+
// ESP8266 is special case because there is only one wire structure available
54+
// Although we can created multiple wire interfaces we still need to specify SDA and SCL
55+
// before each transmission:
56+
// lcd_port->begin(sdaPin, sclPin);
57+
// lcd_port->setClock(100000);
58+
// lcd_port->setClockStretchLimit(200000); // 200ms, for slow devices
59+
// # endif
60+
// lcd.setCursor(0, 0);
61+
// lcd.print(lcdbuf);
4262

4363
// constructors, which allow to redefine bit assignments in case your adapter is wired differently
4464
LiquidCrystal_PCF8574(uint8_t i2cAddr, uint8_t rs, uint8_t enable,
@@ -48,7 +68,7 @@ class LiquidCrystal_PCF8574 : public Print
4868

4969
// Functions from reference:
5070

51-
void begin(uint8_t cols, uint8_t rows);
71+
void begin(uint8_t cols, uint8_t rows, TwoWire &wirePort = Wire);
5272

5373
void clear();
5474
void home();
@@ -65,10 +85,10 @@ class LiquidCrystal_PCF8574 : public Print
6585
void noAutoscroll();
6686
void leftToRight();
6787
void rightToLeft();
68-
void createChar(uint8_t, byte[]);
88+
void createChar(uint8_t location, uint8_t charmap[]);
6989
#ifdef __AVR__
70-
void createChar_P(uint8_t, const byte *);
71-
inline void createChar(uint8_t n, const byte *data) {
90+
void createChar_P(uint8_t, const uint8_t *);
91+
inline void createChar(uint8_t n, const uint8_t *data) {
7292
createChar_P(n, data);
7393
};
7494
#endif
@@ -81,6 +101,9 @@ class LiquidCrystal_PCF8574 : public Print
81101
virtual size_t write(uint8_t ch);
82102

83103
private:
104+
105+
TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
106+
84107
// instance variables
85108
uint8_t _i2cAddr; ///< Wire Address of the LCD
86109
uint8_t _backlight; ///< the backlight intensity

0 commit comments

Comments
 (0)