# LiquidCrystal Module | Since | Origin / Contributor | Maintainer | Source | | :----- | :-------------------- | :---------- | :------ | | 2019-12-01 | [Matsievskiy Sergey](https://github.com/seregaxvm) | [Matsievskiy Sergey](https://github.com/seregaxvm) | [liquidcrystal.lua](../../lua_modules/liquidcrystal/liquidcrystal.lua) [i2c4bit.lua](../../lua_modules/liquidcrystal/lc-i2c4bit.lua) [gpio4bit.lua](../../lua_modules/liquidcrystal/lc-gpio4bit.lua) [gpio8bit.lua](../../lua_modules/liquidcrystal/lc-gpio8bit.lua) | This Lua module provides access to [Hitachi HD44780](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) based LCDs. It supports 4 bit and 8 bit GPIO interface, 4 bit [PCF8574](https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF8574A.pdf) based I²C interface. !!! note This module requires `bit` C module built into firmware. Depending on the interface, `gpio` or `i2c` module is also required. ## Program example In this example LED screen is connected using I²C GPIO expander. Program defines five custom characters and prints text. ```lua backend_meta = require "lc-i2c4bit" lc_meta = require "liquidcrystal" -- create display object lc = lc_meta(backend_meta{sda=1, scl=2}, false, true, 20) backend_meta = nil lc_meta = nil -- define custom characters lc:customChar(0, {0,14,31,31,4,4,5,2}) lc:customChar(1, {4,6,5,5,4,12,28,8}) lc:customChar(2, {14,31,17,17,17,17,17,31}) lc:customChar(3, {14,31,17,17,17,17,31,31}) lc:customChar(4, {14,31,17,17,31,31,31,31}) lc:customChar(5, {14,31,31,31,31,31,31,31}) lc:clear() -- clear display lc:blink(true) -- enable cursor blinking lc:home() -- reset cursor position lc:write("hello", " ", "world") -- write string lc:cursorMove(1, 2) -- move cursor to second line lc:write("umbrella", 0, 32, "note", 1) -- mix text strings and characters lc:cursorMove(1, 3) lc:write("Battery level ", 2, 3, 4, 5) lc:home() lc:blink(false) for i=1,20 do print(lc:read()) end -- read back first line lc:home() for _, d in ipairs(lc:readCustom(0)) do print(d) end -- read back umbrella char for _, d in ipairs(lc:readCustom(1)) do print(d) end -- read back note char ``` ### Require ```lua i2c4bit_meta = require("lc-i2c4bit") gpio4bit_meta = require("lc-gpio4bit") gpio8bit_meta = require("lc-gpio8bit") lc_meta = require("liquidcrystal") ``` ### Release ```lua package.loaded["lc-i2c4bit"] = nil package.loaded["lc-gpio4bit"] = nil package.loaded["lc-gpio8bit"] = nil package.loaded["liquidcrystal"] = nil ``` ## Initialization Liquidcrystal module is initialized using closure, which takes backend object as an argument. ### I²C backend Loading I²C backend module returns initialization closure. It configures I²C backend and returns backend object. #### Syntax `function({[sda=sda_pin] [, scl=scl_pin] [, busid=id] [, busad=address] [, speed = spd] [, rs = rs_pos] [, rw = rw_pos] [, en = en_pos] [, bl = bl_pos] [, d4 = d4_pos] [, d5 = d5_pos] [, d6 = d6_pos] [, d7 = d7_pos]})` !!! note In most cases only `sda` and `scl` parameters are required #### Parameters - `sda`: I²C data pin. If set to `nil`, I²C bus initialization step via [`i2c.setup`](https://nodemcu.readthedocs.io/en/release/modules/i2c/#i2csetup) will be skipped - `scl`: I²C clock pin. If set to `nil`, I²C bus initialization step via [`i2c.setup`](https://nodemcu.readthedocs.io/en/release/modules/i2c/#i2csetup) will be skipped - `busid`: I²C bus ID. Defaults to `0` - `busad`: chip I²C address. Defaults to `0x27` (default PCF8574 address) - `speed`: I²C speed. Defaults to `i2c.SLOW` - `rs`: bit position assigned to `RS` pin in I²C word. Defaults to 0 - `rw`: bit position assigned to `RW` pin in I²C word. Defaults to 1 - `en`: bit position assigned to `EN` pin in I²C word. Defaults to 2 - `bl`: bit position assigned to backlight pin in I²C word. Defaults to 3 - `d4`: bit position assigned to `D4` pin in I²C word. Defaults to 4 - `d5`: bit position assigned to `D5` pin in I²C word. Defaults to 5 - `d6`: bit position assigned to `D6` pin in I²C word. Defaults to 6 - `d7`: bit position assigned to `D7` pin in I²C word. Defaults to 7 #### Returns - backend object #### Example ```lua backend_meta = require "lc-i2c4bit" backend = backend_meta{sda=1, scl=2 ,speed=i2c.FAST} ``` ### GPIO 4 bit backend Loading GPIO 4 bit backend module returns initialization closure. It configures GPIO 4 bit backend and returns backend object. #### Syntax `function({[, rs = rs_pos] [, rw = rw_pos] [, en = en_pos] [, bl = bl_pos] [, d4 = d4_pos] [, d5 = d5_pos] [, d6 = d6_pos] [, d7 = d7_pos]})` #### Parameters - `rs`: GPIO pin connected to `RS` pin. Defaults to 0 - `rw`: GPIO pin connected to `RW` pin. If set to `nil` then `busy`, `position` and `readChar` functions will not be available. Note that `RW` pin must be pulled to the ground if not connected to GPIO - `en`: GPIO pin connected to `EN` pin. Defaults to 1 - `bl`: GPIO pin controlling backlight. It is assumed, that high level turns backlight on, low level turns backlight off. If set to `nil` then backlight function will not be available - `d4`: GPIO pin connected to `D4` pin. Defaults to 2 - `d5`: GPIO pin connected to `D5` pin. Defaults to 3 - `d6`: GPIO pin connected to `D6` pin. Defaults to 4 - `d7`: GPIO pin connected to `D7` pin. Defaults to 5 #### Returns - backend object #### Example ```lua backend_meta = require "lc-gpio4bit" backend = backend_meta{rs=0, rw=1, en=4, d4=5, d5=6, d6=7, d7=8} ``` ### GPIO 8 bit backend Loading GPIO 8 bit backend module returns initialization closure. It configures GPIO 8 bit backend and returns backend object. #### Syntax `function({[, rs = rs_pos] [, rw = rw_pos] [, en = en_pos] [, bl = bl_pos] [, d0 = d0_pos] [, d1 = d1_pos] [, d2 = d2_pos] [, d3 = d3_pos] [, d4 = d4_pos] [, d5 = d5_pos] [, d6 = d6_pos] [, d7 = d7_pos]})` #### Parameters - `rs`: GPIO pin connected to `RS` pin. Defaults to 0 - `rw`: GPIO pin connected to `RW` pin. If set to `nil` then `busy`, `position` and `readChar` functions will not be available. Note that `RW` pin must be pulled to the ground if not connected to GPIO - `en`: GPIO pin connected to `EN` pin. Defaults to 1 - `bl`: GPIO pin controlling backlight. It is assumed, that high level turns backlight on, low level turns backlight off. If set to `nil` then backlight function will not be available - `d0`: GPIO pin connected to `D0` pin. Defaults to 2 - `d1`: GPIO pin connected to `D1` pin. Defaults to 3 - `d2`: GPIO pin connected to `D2` pin. Defaults to 4 - `d3`: GPIO pin connected to `D3` pin. Defaults to 5 - `d4`: GPIO pin connected to `D4` pin. Defaults to 6 - `d5`: GPIO pin connected to `D5` pin. Defaults to 7 - `d6`: GPIO pin connected to `D6` pin. Defaults to 8 - `d7`: GPIO pin connected to `D7` pin. Defaults to 9 #### Returns - backend object #### Example ```lua backend_meta = require "lc-gpio8bit" backend = backend_meta{rs=15, rw=2, en=5, d0=23, d1=13, d2=33, d3=32, d4=18, d5=19, d6=21, d7=22} ``` ### Liquidcrystal initialization Loading Liquidcrystal module returns initialization closure. It requires backend object and returns LCD object. #### Syntax `function(backend, onelinemode, eightdotsmode, column_width)` #### Parameters - `backend`: backend object - `onelinemode`: `true` to use one line mode, `false` to use two line mode - `eightdotsmode`: `true` to use 5x8 dot font, `false` to use 5x10 dot font - `column_width`: number of characters in column. Used for offset calculations in function `cursorMove`. If set to `nil`, functionality of `cursorMove` will be limited. For most displays column width is `20` characters #### Returns screen object #### Example ```lua lc_meta = require "liquidcrystal" lc = lc_meta(backend, true, true, 20) ``` ## liquidcrystal.autoscroll Autoscroll text when printing. When turned off, cursor moves and text stays still, when turned on, vice versa. #### Syntax `liquidcrystal.autoscroll(self, on)` #### Parameters - `self`: `liquidcrystal` instance - `on`: `true` to turn on, `false` to turn off #### Returns - sent data #### Example ```lua liquidcrystal:autoscroll(true) ``` ## liquidcrystal.backlight Control LCDs backlight. When using GPIO backend without `bl` argument specification function does nothing. #### Syntax `liquidcrystal.backlight(self, on)` #### Parameters - `self`: `liquidcrystal` instance - `on`: `true` to turn on, `false` to turn off #### Returns - backlight status #### Example ```lua liquidcrystal:backlight(true) ``` ## liquidcrystal.blink Control cursors blink mode. #### Syntax `liquidcrystal.blink(self, on)` #### Parameters - `self`: `liquidcrystal` instance - `on`: `true` to turn on, `false` to turn off #### Returns - sent data #### Example ```lua liquidcrystal:blink(true) ``` ## liquidcrystal.busy Get busy status of the LCD. When using GPIO backend without `rw` argument specification function does nothing. !!! note At least some HD44780s and/or interfaces have been observed to count polling the busy flag as grounds for incrementing their position in memory. This is mysterious, but software should restore the position after observing that the busy flag is clear. #### Syntax `liquidcrystal.busy(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - `true` if device is busy, `false` if device is ready to receive commands #### Example ```lua while liquidcrystal:busy() do end ``` ## liquidcrystal.clear Clear LCD screen. #### Syntax `liquidcrystal.clear(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:clear() ``` ## liquidcrystal.cursorLeft Move cursor one character to the left. #### Syntax `liquidcrystal.cursorLeft(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:cursorLeft() ``` ## liquidcrystal.cursorMove Move cursor to position. If `row` not specified, move cursor to address `col`. !!! note Note that column and row indexes start with 1. However, when omitting `row` parameter, cursor addresses start with 0. #### Syntax `liquidcrystal.cursorMove(self, col, row)` #### Parameters - `self`: `liquidcrystal` instance - `col`: new cursor position column. If `row` not specified, new cursor position address - `row`: new cursor position row or `nil` #### Returns - sent data #### Example ```lua liquidcrystal:cursorMove(5, 1) liquidcrystal:cursorMove(10, 4) liquidcrystal:cursorMove(21) ``` ## liquidcrystal.cursor Control cursors highlight mode. #### Syntax `liquidcrystal.cursor(self, on)` #### Parameters - `self`: `liquidcrystal` instance - `on`: `true` to turn on, `false` to turn off #### Returns - sent data #### Example ```lua liquidcrystal:cursor(true) ``` ## liquidcrystal.cursorRight Move cursor one character to the right. #### Syntax `liquidcrystal.cursorRight(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:cursorRight() ``` ## liquidcrystal.customChar Define new custom char. Up to 8 custom characters with indexes 0 to 7 may be defined in eight dot mode. They are accessed via `write` function by index. In ten dot mode only 4 custom characters may be used. They are numbered from 0 to 7 with half of them being aliases to each other (0 to 1, 2 to 3 etc). !!! note Upon redefinition of a custom character all its instances will be updated automatically. This function resets cursor position to home if `liquidcrystal.position` function is not available. There are web services ([1](https://omerk.github.io/lcdchargen/), [2](https://www.quinapalus.com/hd44780udg.html)) and [desktop applications](https://pypi.org/project/lcdchargen/) that help create custom characters. #### Syntax `liquidcrystal.customChar(self, index, bytes)` #### Parameters - `self`: `liquidcrystal` instance - `index`: custom char index in range from 0 to 7 - `bytes`: array of 8 bytes in eight bit mode or 11 bytes in ten bit mode (eleventh line is a cursor line that can also be used) that defines new char bitmap line by line #### Returns `nil` #### Example ```lua liquidcrystal:customChar(5, {14,31,31,31,31,31,31,31}) liquidcrystal:write(5) ``` ## liquidcrystal.display Turn display on and off. Does not affect display backlight. Does not clear the display. #### Syntax `liquidcrystal.display(self, on)` #### Parameters - `self`: `liquidcrystal` instance - `on`: `true` to turn on, `false` to turn off #### Returns - sent data #### Example ```lua liquidcrystal:display(true) ``` ## liquidcrystal.home Reset cursor and screen position. #### Syntax `liquidcrystal.home(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:home() ``` ## liquidcrystal.leftToRight Print text left to right (default). #### Syntax `liquidcrystal.leftToRight(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:leftToRight() ``` ## liquidcrystal.position Get current position of the cursor. Position is 0 indexed. When using GPIO backend without `rw` argument specification function does nothing. !!! note At least some HD44780s and/or interfaces have been observed to count reading the position as grounds for incrementing their position in memory. This is mysterious, but software likely intends to restore the position anyway. #### Syntax `liquidcrystal.position(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - 0 indexed position of the cursor #### Example ```lua local pos = liquidcrystal:position() -- save position -- some code liquidcrystal:cursorMove(pos) -- restore position ``` ## liquidcrystal.read Return current character numerical representation. When using GPIO backend without `rw` argument specification function does nothing. #### Syntax `liquidcrystal.read(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - numerical representation of the current character #### Example ```lua liquidcrystal:home() -- goto home local ch = liquidcrystal:read() -- read char liquidcrystal:cursorMove(1, 2) -- move to the second line for i=ch,ch+5 do lc:write(i) end -- print 6 chars starting with ch ``` ## liquidcrystal.readCustom Return custom char byte array. When using GPIO backend without `rw` argument specification function returns zeros. #### Syntax `liquidcrystal.readCustom(self, index)` #### Parameters - `self`: `liquidcrystal` instance - `index`: custom char index in range from 0 to 7 #### Returns - table of size 8 in eight dot mode or 11 in ten dot mode. Each 8 bit number represents a character dot line #### Example ```lua lc:customChar(0, {0,14,31,31,4,4,5,2}) -- define custom character for _, d in ipairs(lc:readCustom(0)) do print(d) end -- read it back ``` ## liquidcrystal.rightToLeft Print text right to left. #### Syntax `liquidcrystal.rightToLeft(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:rightToLeft() ``` ## liquidcrystal.scrollLeft Move text to the left. #### Syntax `liquidcrystal.scrollLeft(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:scrollLeft() ``` ## liquidcrystal.scrollRight Move text to the right. #### Syntax `liquidcrystal.scrollRight(self)` #### Parameters - `self`: `liquidcrystal` instance #### Returns - sent data #### Example ```lua liquidcrystal:scrollRight() ``` ## liquidcrystal.write Print text. #### Syntax `liquidcrystal.write(self, ...)` #### Parameters - `self`: `liquidcrystal` instance - `...`: strings or char codes. For the list of available characters refer to [HD44780 datasheet](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf#page=17) #### Returns `nil` #### Example ```lua liquidcrystal:write("hello world") liquidcrystal:write("hello yourself", "!!!", 243, 244) ```