Included LCD Library

This commit is contained in:
Emanuele Trabattoni
2024-06-23 15:15:26 +02:00
parent 1d123f3ff2
commit 6d210c0885
5 changed files with 758 additions and 7 deletions

View File

@@ -0,0 +1,295 @@
// Based on the work by DFRobot upgraded by DVSProductions
#include "LiquidCrystal_I2C.h"
#include <inttypes.h>
/*********** mid level commands, for sending data/cmds */
#define COMMAND(value) send(value, 0)
#define printIIC(args) i2c->write(_Addr, args, 1)
size_t LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
return 1;
}
inline void LiquidCrystal_I2C::command(uint8_t value) {
send(value, 0);
}
// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
// DL = 1; 8-bit interface data
// N = 0; 1-line display
// F = 0; 5x8 dot character font
// 3. Display on/off control:
// D = 0; Display off
// C = 0; Cursor off
// B = 0; Blinking off
// 4. Entry mode set:
// I/D = 1; Increment by 1
// S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
/*!
Creates a new LCD instance
!*/
LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows, PinName sda, PinName scl) {
_Addr = lcd_Addr << 1;
_cols = lcd_cols;
_rows = lcd_rows;
_backlightval = LCD_NOBACKLIGHT;
i2c = new I2C(sda, scl);
i2c->frequency(1000000);
}
void LiquidCrystal_I2C::init() {
init_priv();
}
void LiquidCrystal_I2C::init_priv() {
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin_priv();
}
void LiquidCrystal_I2C::begin_priv(uint8_t dotsize) {
if (_rows > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = _rows;
// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (_rows == 1)) {
_displayfunction |= LCD_5x10DOTS;
}
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Nucleo can turn on way befer 4.5V so we'll wait
// 50
wait_ms(50);
// Now we pull both RS and R/W low to begin commands
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
wait_ms(1000);
// put the LCD into 4 bit mode
// this is according to the hitachi HD44780 datasheet
// figure 24, pg 46
// we start in 8bit mode, try to set 4 bit mode
write4bits(0x03 << 4);
wait_us(4100); // wait min 4.1ms
// second try
write4bits(0x03 << 4);
wait_us(4100); // wait min 4.1ms
// third go!
write4bits(0x03 << 4);
wait_us(150);
// finally, set to 4-bit interface
write4bits(0x02 << 4);
// set # lines, font size, etc.
COMMAND(LCD_FUNCTIONSET | _displayfunction);
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
display();
// clear it off
clear();
// Initialize to default text direction (for roman languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
// set the entry mode
COMMAND(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
home();
}
void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
_cols = cols;
_rows = lines;
begin_priv();
}
/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear() {
COMMAND(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
wait_us(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::home() {
COMMAND(LCD_RETURNHOME); // set cursor position to zero
wait_us(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row) {
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if (row > _numlines)
row = _numlines - 1; // we count rows starting w/0
COMMAND(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
// Turn the display on/off (quickly)
void LiquidCrystal_I2C::noDisplay() {
_displaycontrol &= ~LCD_DISPLAYON;
COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::display() {
_displaycontrol |= LCD_DISPLAYON;
COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void LiquidCrystal_I2C::noCursor() {
_displaycontrol &= ~LCD_CURSORON;
COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::cursor() {
_displaycontrol |= LCD_CURSORON;
COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void LiquidCrystal_I2C::noBlink() {
_displaycontrol &= ~LCD_BLINKON;
COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::blink() {
_displaycontrol |= LCD_BLINKON;
COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void LiquidCrystal_I2C::scrollDisplayLeft(void) {
COMMAND(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void LiquidCrystal_I2C::scrollDisplayRight(void) {
COMMAND(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
// This is for text that flows Left to Right
void LiquidCrystal_I2C::leftToRight(void) {
_displaymode |= LCD_ENTRYLEFT;
COMMAND(LCD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void LiquidCrystal_I2C::rightToLeft(void) {
_displaymode &= ~LCD_ENTRYLEFT;
COMMAND(LCD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void LiquidCrystal_I2C::autoscroll(void) {
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
COMMAND(LCD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void LiquidCrystal_I2C::noAutoscroll(void) {
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
COMMAND(LCD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
COMMAND(LCD_SETCGRAMADDR | (location << 3));
for (uint8_t i = 0; i != 8; i++)
write(charmap[i]);
}
// Turn the (optional) backlight off/on
void LiquidCrystal_I2C::noBacklight(void) {
_backlightval = LCD_NOBACKLIGHT;
expanderWrite(0);
}
void LiquidCrystal_I2C::backlight(void) {
_backlightval = LCD_BACKLIGHT;
expanderWrite(0);
}
/************ low level data pushing commands **********/
// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
uint8_t highnib = value & 0xf0;
uint8_t lownib = (value << 4) & 0xf0;
write4bits((highnib) | mode);
write4bits((lownib) | mode);
}
void LiquidCrystal_I2C::write4bits(uint8_t value) {
expanderWrite(value);
pulseEnable(value);
}
char buff;
inline void LiquidCrystal_I2C::expanderWrite(uint8_t _data) {
buff = (_data) | _backlightval;
printIIC(&buff);
}
void LiquidCrystal_I2C::pulseEnable(uint8_t _data) {
expanderWrite(_data | En); // En high
wait_us(1); // enable pulse must be >450ns
expanderWrite(_data & ~En); // En low
wait_us(10); // commands need > 37us to settle
}
// Alias functions
inline void LiquidCrystal_I2C::cursor_on() {
cursor();
}
inline void LiquidCrystal_I2C::cursor_off() {
noCursor();
}
inline void LiquidCrystal_I2C::blink_on() {
blink();
}
inline void LiquidCrystal_I2C::blink_off() {
noBlink();
}
inline void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows) {
createChar(char_num, rows);
}
void LiquidCrystal_I2C::setBacklight(uint8_t new_val) {
if (new_val)
backlight(); // turn backlight on
else
noBacklight(); // turn backlight off
}
void LiquidCrystal_I2C::printstr(const char c[]) {
// This function is not identical to the function used for "real" I2C displays
// it's here so the use sketch doesn't have to be changed
print(c);
}
// unsupported API functions
void LiquidCrystal_I2C::off() {
noBacklight();
}
void LiquidCrystal_I2C::on() {
begin_priv();
backlight();
}
void LiquidCrystal_I2C::setDelay(int cmdDelay, int charDelay) {}
uint8_t LiquidCrystal_I2C::status() {
return 0;
}
uint8_t LiquidCrystal_I2C::keypad() {
return 0;
}
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) {}

View File

@@ -0,0 +1,127 @@
// YWROBOT
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h
#include "Print.h"
#include "mbed.h"
#include <inttypes.h>
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define En 0B00000100 // Enable bit
#define Rw 0B00000010 // Read/Write bit
#define Rs 0B00000001 // Register select bit
class LiquidCrystal_I2C : public Print {
public:
LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows,
PinName sda, PinName scl);
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
void clear();
void home();
void noDisplay();
void display();
void noBlink();
void blink();
void noCursor();
void cursor();
void scrollDisplayLeft();
void scrollDisplayRight();
void printLeft();
void printRight();
void leftToRight();
void rightToLeft();
void shiftIncrement();
void shiftDecrement();
void noBacklight();
void backlight();
void autoscroll();
void noAutoscroll();
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
virtual size_t write(uint8_t);
void command(uint8_t);
void init();
////compatibility API function aliases
void blink_on(); // alias for blink()
void blink_off(); // alias for noBlink()
void cursor_on(); // alias for cursor()
void cursor_off(); // alias for noCursor()
void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight()
void load_custom_character(uint8_t char_num,
uint8_t *rows); // alias for createChar()
void printstr(const char[]);
////Unsupported API functions (not implemented in this library)
uint8_t status();
void setContrast(uint8_t new_val);
uint8_t keypad();
void setDelay(int, int);
void on();
void off();
uint8_t init_bargraph(uint8_t graphtype);
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len,
uint8_t pixel_col_end);
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len,
uint8_t pixel_col_end);
private:
mbed::I2C *i2c;
void init_priv();
void begin_priv(uint8_t charsize = LCD_5x8DOTS);
void send(uint8_t, uint8_t);
void write4bits(uint8_t);
void expanderWrite(uint8_t);
void pulseEnable(uint8_t);
uint8_t _Addr;
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _numlines;
uint8_t _cols;
uint8_t _rows;
uint8_t _backlightval;
};
#endif

230
lib/Print/Print.cpp Normal file
View File

@@ -0,0 +1,230 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 03 August 2015 by Chuck Todd
*/
#include <string>
#include <cmath>
#include "Print.h"
// Public Methods //////////////////////////////////////////////////////////////
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
while (size--) {
if (write(*buffer++)) n++;
else break;
}
return n;
}
size_t Print::print(const std::string &s)
{
return write(s.c_str(), s.length());
}
size_t Print::print(const char str[])
{
return write(str);
}
size_t Print::print(char c)
{
return write(c);
}
size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base);
}
size_t Print::print(int n, int base)
{
return print((long) n, base);
}
size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base);
}
size_t Print::print(long n, int base)
{
if (base == 0) {
return write(n);
} else if (base == 10) {
if (n < 0) {
int t = print('-');
n = -n;
return printNumber(n, 10) + t;
}
return printNumber(n, 10);
} else {
return printNumber(n, base);
}
}
size_t Print::print(unsigned long n, int base)
{
if (base == 0) return write(n);
else return printNumber(n, base);
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
}
size_t Print::println(void)
{
return write("\r\n");
}
size_t Print::println(const std::string &s)
{
size_t n = print(s);
n += println();
return n;
}
size_t Print::println(const char c[])
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(char c)
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base);
n += println();
return n;
}
size_t Print::println(int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
n += println();
return n;
}
// Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if (base < 2) base = 10;
do {
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
return write(str);
}
size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0;
if (isnan(number)) return print("nan");
if (isinf(number)) return print("inf");
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
// Handle negative numbers
if (number < 0.0)
{
n += print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
n += print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
n += print('.');
}
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
unsigned int toPrint = (unsigned int)(remainder);
n += print(toPrint);
remainder -= toPrint;
}
return n;
}

96
lib/Print/Print.h Normal file
View File

@@ -0,0 +1,96 @@
/*
Print.h - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Print_h
#define Print_h
#include <stdint.h>
#include <string>
#include <string.h>
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
class Print {
private:
int write_error;
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
protected:
inline void setWriteError(int err = 1) {
write_error = err;
}
public:
Print() :
write_error(0) {
}
int getWriteError() {
return write_error;
}
void clearWriteError() {
setWriteError(0);
}
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) {
if(str == NULL)
return 0;
return write((const uint8_t *) str, strlen(str));
}
virtual size_t write(const uint8_t *buffer, size_t size);
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *) buffer, size);
}
// These handle ambiguity for write(0) case, because (0) can be a pointer or an integer
inline size_t write(short t) { return write((uint8_t)t); }
inline size_t write(unsigned short t) { return write((uint8_t)t); }
inline size_t write(int t) { return write((uint8_t)t); }
inline size_t write(unsigned int t) { return write((uint8_t)t); }
inline size_t write(long t) { return write((uint8_t)t); }
inline size_t write(unsigned long t) { return write((uint8_t)t); }
// Enable write(char) to fall through to write(uint8_t)
inline size_t write(char c) { return write((uint8_t) c); }
inline size_t write(int8_t c) { return write((uint8_t) c); }
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
size_t print(const std::string &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t println(const std::string &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(double, int = 2);
size_t println(void);
virtual void flush() { /* Empty implementation for backward compatibility */ }
};
#endif

View File

@@ -1,10 +1,12 @@
#include <mbed.h>
#include <pid.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
auto t_controller = PID(1, 1, 0, 2);
auto t_sensor = DHT(PC_10, AM2302);
auto led = DigitalOut(PA_5);
auto led = DigitalOut(LED1);
auto lcd = LiquidCrystal_I2C(0x20, 20, 4, I2C_SDA, I2C_SCL);
int main()
{
@@ -14,7 +16,8 @@ int main()
t_controller.setSetPoint(29);
while (true)
{
if (eError::ERROR_NONE != t_sensor.readData()){
if (eError::ERROR_NONE != t_sensor.readData())
{
printf("Error\n");
continue;
}