Files
Arduino/libraries/hd44780/examples/ioClass/hd44780_I2Cexp/LCDCustomChars/LCDCustomChars.ino
Jérôme Delacotte 7b30d6e298 first commit
2025-03-06 11:15:32 +01:00

316 lines
11 KiB
C++

static const int dummyvar = 0; // dummy declaration for older broken IDEs!!!!
// vi:ts=4
// ----------------------------------------------------------------------------
// LCDCustomChars - simple demonstration of lcd custom characters
// Created by Bill Perry 2016-10-06
// bperrybap@opensource.billsworld.billandterrie.com
//
// This example code is unlicensed and is released into the public domain
// ----------------------------------------------------------------------------
//
// This sketch is for LCDs with PCF8574 or MCP23008 chip based backpacks
// WARNING:
// Use caution when using 3v only processors like arm and ESP8266 processors
// when interfacing with 5v modules as not doing proper level shifting or
// incorrectly hooking things up can damage the processor.
//
// Sketch demonstrates how to assign custom characters to the eight hd44780
// custom character codepoints and how to display on the LCD using
// write() and print()
//
// You can create your own custom characters.
// Here are a couple of web pages that have a tool that will generate the data
// values needed for custom character.
// https://kakedev.github.io/GlyphGenerator/
// http://www.quinapalus.com/hd44780udg.html
// https://omerk.github.io/lcdchargen
//
#include <Wire.h>
#include <hd44780.h> // include hd44780 library header file
#include <hd44780ioClass/hd44780_I2Cexp.h> // i/o expander/backpack class
hd44780_I2Cexp lcd; // auto detect backpack and pin mappings
// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
const int LongDelay = 5000;
const int ShortDelay = 800;
int customcharRow = 1; // default to printing custom chars on row 1
// Below are some custom characters for demonstration
// You can ensure that the data for these custom characters is only
// in flash and not in RAM by using the const qualifier.
// However....
// If using the AVR part, the AVR proprietary PROGMEM directive must be used.
// PROGMEM is only required on AVR parts since the AVR parts cannot directly
// access const data stored in flash like all the other processors.
// PROGMEM is an AVR specific proprietary kludge that tells the linker and
// startup code to handle the data differently.
// PROGMEM is only used by the AVR and not required by any other processor.
//
// Most non AVR cores provide AVR compatibilty by providing support (emulation)
// for the AVR proprietary PROGMEM directive and corresponding access functions,
// but some do not.
//
// Because of this AVR const data and PROGMEM issue, there is no way to
// guarantee code portability across all cores when using const data.
//
//
// the hd44780 library assumes that if a const qualifier is used on the AVR
// processor that the data has been stored in flash using the PROGMEM directive.
// There is no way for the hd44780 library to know or detect if PROGMEM has
// been used.
// So if the const qualifer is used but the PROGMEM directive is not used on
// an AVR processor, the custom char will be garbage.
//
// Examples:
// For all processors other than AVR:
// const char bell[8] = {0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00};
// const uint8_ bell[8] = {0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00};
//
// For AVR: (and non AVR cores that have AVR PROGMEM emulation)
// const char bell[8] PROGMEM = {0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00};
// const uint8_t bell[8] PROGMEM = {0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00};
// OR
// const PROGMEM char bell[8] = {0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00};
// const PROGMEM uint8_t bell[8] = {0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00};
// NOTE:
// if PROGMEM is used on older AVR compilers it generates a warning.
//
uint8_t bell[8] = {0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00};
uint8_t note[8] = {0x02,0x03,0x02,0x0e,0x1e,0x0c,0x00,0x00};
uint8_t clockface[8] = {0x00,0x0e,0x15,0x17,0x11,0x0e,0x00,0x00};
uint8_t heart[8] = {0x00,0x0a,0x1f,0x1f,0x0e,0x04,0x00,0x00};
uint8_t duck[8] = {0x00,0x0c,0x1d,0x0f,0x0f,0x06,0x00,0x00};
uint8_t check[8] = {0x00,0x01,0x03,0x16,0x1c,0x08,0x00,0x00};
uint8_t cross[8] = {0x00,0x1b,0x0e,0x04,0x0e,0x1b,0x00,0x00};
uint8_t smile[8] = {0x00,0x0a,0x0a,0x00,0x00,0x11,0x0e,0x00};
uint8_t degreeSymbol[8]= {0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00};
uint8_t degreeC[8] = {0x18,0x18,0x03,0x04,0x04,0x04,0x03,0x00};
uint8_t degreeF[8] = {0x18,0x18,0x07,0x04,0x07,0x04,0x04,0x00};
const PROGMEM uint8_t vsigbar[][8] = {
{0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0 bars, same as <space>
{0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x1F}, // 1 bars
{0x00, 0x00,0x00,0x00,0x00,0x00,0x1F,0x1F}, // 2 bars
{0x00, 0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F}, // 3 bars
{0x00, 0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F}, // 4 bars
{0x00, 0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F}, // 5 bars
{0x00, 0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, // 6 bars
{0x00, 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, // 7 bars
{0x1F, 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, // 8 bars
};
void setup()
{
int status;
// initialize LCD with number of columns and rows:
// hd44780 returns a status from begin() that can be used
// to determine if initalization failed.
// the actual status codes are defined in <hd44780.h>
// See the values RV_XXXX
//
// looking at the return status from begin() is optional
// it is being done here to provide feedback should there be an issue
//
// note:
// begin() will automatically turn on the backlight
//
status = lcd.begin(LCD_COLS, LCD_ROWS);
if(status) // non zero status means it was unsuccesful
{
// begin() failed so blink error code using the onboard LED if possible
hd44780::fatalError(status); // does not return
}
// initalization was successful, the backlight should be on now
}
void loop(void)
{
lcd.clear();
lcd.print("Custom Chars");
// create custom characters
// int rval = createChar(charval, charmap[]);
//
// createChar() creates a custom character
// for the character at the charval codepoint.
// It returns zero if successful.
//
// to display the custom character, simply call write()
// with the charval use in createChar()
//
// The display must be initialized *before* you attempt
// to create custom characters.
//
// Note: On hd44780 displays there are 8 custom characters.
// They are assigned to character codepoint values 0x00 to 0x07
// The codepoints 0x08 to 0x0f are duplicates for 0x00 to 0x07
// i.e. 0x08 is the same as 0x00, 0x09 same as 0x01, etc...
// create 8 custom characters
lcd.createChar(0, bell);
lcd.createChar(1, note);
lcd.createChar(2, clockface);
lcd.createChar(3, heart);
lcd.createChar(4, duck);
lcd.createChar(5, check);
lcd.createChar(6, cross);
lcd.createChar(7, smile);
// prepare to display the custom characters
// on multi line displays the custom characters will be
// displayed on the 2nd line
// on single line displays, delay a bit to see the initial display,
// then clear the display to display the custom characters on the top line
if(LCD_ROWS < 2)
{
customcharRow = 0;
delay(LongDelay);
lcd.clear();
}
lcd.setCursor(0, customcharRow);
// write() or print() can be used to display custom characters.
//
// To use write() pass the charval of the desired custom character.
// lcd.write(charval);
// NOTE:
// The Print class has an issue that does not allow 0 (zero) to be used
// on write() without casting it. The Arduino team refuses to fix this.
// hd44780 has a work around in it to remove this issue so you can call
// write() with a constant value of 0 without having to cast it.
//
// write() can also be used with literal characters that contain
// an octal (base 8) escape seuence.
// lcd.write('\###');
//
// To use print() pass in the charval of the desired custom character
// as a character *not* an integer.
// This requires using a literal character with an octal escape sequence.
// lcd.print('\###');
//
// Since both write() & print() both accept octal escaped literal characters
// it is the most compatible & portable way of sending custom characters
// display all 8 custom characters.
// write() with character codepoint values
lcd.write(0); // casting to an uint8_t or byte not needed with hd44780
lcd.write(1);
// write() & print() with octal escaped literal characters
lcd.write('\002'); // this is an octal escaped literal character
lcd.write('\003'); // this is an octal escaped literal character
lcd.print('\004'); // this is an octal escaped literal character
lcd.print('\005'); // this is an octal escaped literal character
// can also drop the leading zeros on small litereal values like these
lcd.print('\06'); // this is an octal escaped literal character
lcd.print('\7'); // this is an octal escaped literal character
delay(LongDelay);
// You can also insert custom character codepoints into C strings.
// To do so, insert the character codepoint value as an octal constant.
// However,
// because zero indicates the end of string in C you cannot use zero.
// Example:
// lcd.print("charval #1: \001"); // prints custom character at codepoint 1
lcd.setCursor(0,customcharRow);
lcd.print("code1: \001");
delay(ShortDelay);
lcd.setCursor(0,customcharRow);
lcd.print("code2: \002");
delay(ShortDelay);
lcd.setCursor(0,customcharRow);
lcd.print("code3: \003");
delay(ShortDelay);
lcd.setCursor(0,customcharRow);
lcd.print("code4: \004");
delay(ShortDelay);
lcd.setCursor(0,customcharRow);
lcd.print("code5: \005");
delay(ShortDelay);
lcd.setCursor(0,customcharRow);
lcd.print("code6: \006");
delay(ShortDelay);
lcd.setCursor(0,customcharRow);
lcd.print("code7: \007");
delay(ShortDelay);
// Another nifty trick is that you can modify custom characters on the
// display without having to re-write the characters on the display.
// To do this, simply create a new character for a codepoint.
// All characters on the display which have that codepoint will "magically"
// change to the new custom character.
// So for example, if the entire display was written with custom character
// zero and character zero was a bell, if you called createChar() to
// redefine character codepoint zero to be a duck,
// the entire display would turn to ducks without having to send any
// characters to the display.
// create the initial custom character
lcd.createChar(0, bell);
// fill the custom character line with the custom character.
lcd.setCursor(0,customcharRow);
for(uint8_t col=0; col<LCD_COLS; col++)
lcd.write(0);
delay(ShortDelay);
// change the single custom character previously written on the row
// and all the characters on the row will change
// without having to re-write the characters.
lcd.createChar(0, note);
delay(ShortDelay);
lcd.createChar(0, clockface);
delay(ShortDelay);
lcd.createChar(0, heart);
delay(ShortDelay);
lcd.createChar(0, duck);
delay(ShortDelay);
lcd.createChar(0, check);
delay(ShortDelay);
lcd.createChar(0, cross);
delay(ShortDelay);
lcd.createChar(0, smile);
delay(ShortDelay);
lcd.createChar(0, degreeSymbol);
delay(ShortDelay);
lcd.createChar(0, degreeC);
delay(ShortDelay);
lcd.createChar(0, degreeF);
delay(ShortDelay);
// show multiple vertical bars rising
// by changing the single custom character that is already written
// to the entire row on the display
for(int i = 0; i < 9; i++)
{
lcd.createChar(0, vsigbar[i]);
delay(ShortDelay);
}
delay(LongDelay);
}