Wiki
Clone wikiArduino LCD Bitmap / Home
LCDBitmap Library for Arduino
Index
Introduction
Arduino library that allows you to create a tiny 20x16 pixel bitmap (raster) display on a normally character-only Hitachi HD44780 based LCD display. Typical drawing functions like line, rectangle, invert, etc. Control is right down to the pixel level.
Works with both the standard Liquid Crystal library as well as Francisco's New Liquid Crystal library. Works with LCD connection methods including: 4bit, shift register (2 or 3 wire), and I2C. In-depth example sketches are included with library download.
It works by creating a memory array for the 20x16 pixel bitmap that the functions work within. It then converts this bitmap to the 8 custom characters available with the HD44780 and displaying them as 2 rows of 4 characters at the location specified. As each character is 5x8 pixels and arranged in a 4x2 character array, the total addressable resolution is 20x16. As there's an 8 custom character limit with the HD44780, 20x16 is the maximum resolution that can be achieved (5*4=20 X 8*2=16).
Download & Install
Save the .zip file to your desktop, then use the Importing a .zip Library instructions to import the library into the Arduino IDE.
(2,694 downloads on Google Code before being closed)
If you wish to fork this library, please create a private repository as to not confuse others trying to download the latest official version.
Show Your Appreciation
Help future development by making a small donation.
Connection Examples
Connection via standard 4bit | Connection via shift register | Connection to Teensy 2.0 |
Syntax
LCDBitmap bitmap( &lcd, x, y ) - &lcd is from Liquid Crystal, (x,y) is character position of the bitmap, 0,0 = top/left, 12,0 = far righton a 16x2 LCD. The 20x16 pixel display that LCDBitmap creates is 4 characters wide by 2 characters high.
- bitmap.begin() - Initialize the LCD bitmap
- bitmap.clear() - Clear the bitmap display (automatically updates bitmap display) doesn't clear text
- bitmap.inverse() - Invert the bitmap, automatically updates the bitmap display
- bitmap.update() - Update bitmap display
- bitmap.clear_text() - Clear just the text on the display (leaves bitmap alone)
- bitmap.home() - Move cursor the home position (0,0). Does a lcd.setCursor(0,0), just added for convenience
- bitmap.move( x, y ) - Move the LCD bitmap position to this character position
- bitmap.pixel( x, y, color, update ) - Add pixel at (x,y), color is either ON or OFF, update is either UPDATE or NO_UPDATE
- bitmap.line( x1, y1, x2, y2, color, update ) - Draw the line from (x1,y1) to (x2,y2), color & update as in pixel
- bitmap.rect( x1, y1, x2, y2, color, update ) - Draw a rectangle from (x1,y1) to (x2,y2), color & update as in pixel
- bitmap.rectFill( x1, y1, x2, y2, color, update ) - Draw a filled rectangle from (x1,y1) to (x2,y2), color & update as in pixel
- bitmap.barGraph( bars, *graph, color, update ) - Draw bar graph, bars is # of bars (1,2,4,5,10,20), graph is array containing height values, color & update as in pixel
History
v1.6 - Released 7/05/2012: BITMAP_RANGE_CHK bug fix.
v1.5 - Released 6/28/2012: 4bit method now works without the New LiquidCrystal? library (was always supposed to work this way, oversight on my part). Update switch now optional on all functions, defaults to NO_UPDATE.
v1.4 - Released 5/25/2012: Fixed a few problems with the barGraph function. Further optimization with the range checking. Compatible with Arduino 0023 through 1.0+
v1.3 - Released 5/10/2012: Many performance tweaks and reduced compiled code size. Optimization were enough to deprecate the lineHor and lineVert commands. Both functions still work, there's just no longer any advantage in using them. Thanks to robtillaart for suggesting the Bresenham line algorithm. Modified range checking removing redundant checks. Added new function barGraph that easily creates a 1 to 20 bar graph.
Support Forum
Examples
Simple sketch using I2C LCD interface
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <LCDBitmap.h>
LiquidCrystal_I2C lcd(0x38);
// Assign LCD bitmap to "&lcd", set bitmap display location to character position (0,0).
LCDBitmap bitmap(&lcd, 0, 0);
void setup() {
lcd.begin(16,2); // Do this first.
bitmap.begin(); // Then initialize the LCD bitmap.
lcd.setCursor(5, 0);
lcd.print("LCDBitmap");
}
void loop() {
// Draws some concentric rectangles to the bitmap, don't update bitmap display till the final command.
bitmap.rectFill(0, 0, 19, 15, ON, NO_UPDATE);
bitmap.rectFill(2, 2, 17, 13, OFF, NO_UPDATE);
bitmap.rectFill(4, 4, 15, 11, ON, NO_UPDATE);
bitmap.rect(6, 6, 13, 9, OFF, UPDATE);
while(1){}
}
barGraph sketch using standard 4bit LCD interface
#include <LiquidCrystal.h>
#include <LCDBitmap.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LCDBitmap bitmap(&lcd, 0, 0); // Set the bitmap to the &lcd display at character position 0,0.
byte graph[20];
byte bars[] = { 1, 2, 4, 5, 10, 20 };
void setup() {
lcd.begin(16,2); // Initialize the LCD display, do this before you initialize LCDBitmap.
bitmap.begin(); // Then initialize the LCD bitmap.
lcd.setCursor(5, 0);
lcd.print("LCDBitmap");
}
void loop() {
byte curr_bars = bars[(millis()/3000)%6];
for (byte x=0; x<curr_bars; x++) {
graph[x] = random(0, BITMAP_H+1);
}
bitmap.barGraph(curr_bars, graph, ON, UPDATE); // Display the bar graph.
delay(50);
}
Complex sketch using 4bit LCD interface
#include <LiquidCrystal.h>
#include <LCDBitmap.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LCDBitmap bitmap(&lcd, 12, 0); // Assign the LCD bitmap to "&lcd" set in the previous line and set display location to (12,0)
unsigned long currentMillis; // Timer variable
#define sample 4000 // Sets how long to run each sample
void setup() {
lcd.begin(16,2); // Initialize the LCD
bitmap.begin(); // Initalize the LCD bitmap
bitmap.home(); // Move cursor the home position (0,0)
lcd.print("LCDBitmap");
randomSeed(analogRead(A0));
}
void loop() {
// bitmap.pixel
lcd.setCursor(0, 1);
lcd.print(".pixel ");
currentMillis = millis();
while(millis()-currentMillis<sample) {
for (byte i=0; i<8; i++) {
bitmap.pixel(random(0, BITMAP_W), random(0, BITMAP_H), random(0, 2), NO_UPDATE); // Add one random pixel but don't update bitmap display
}
bitmap.update(); // 8 pixels positioned, now update bitmap display
}
// bitmap.line sample #1
lcd.setCursor(0, 1);
lcd.print(".line #1 ");
bitmap.clear(); // Clear the bitmap display (automatically updates bitmap display) doesn't clear text
currentMillis = millis();
int startdelay=120;
while(millis()-currentMillis<sample*2) {
for (byte x=0; x<BITMAP_W; x=x+2) {
bitmap.line(x, 0, BITMAP_W-x-1, BITMAP_H-1, ON, UPDATE); // Draw the line from (x, 0) to (BITMAP_W-x-1, BITMAP_H-1) and update bitmap display
delay(startdelay);
bitmap.clear(); // Clear the display
}
for (byte y=0; y<BITMAP_H; y=y+2) {
bitmap.line(0, BITMAP_H-y-1, BITMAP_W-1, y, ON, UPDATE);
delay(startdelay);
bitmap.clear(); // Clear the display
}
startdelay=startdelay*2/3;
}
// bitmap.line sample #2
lcd.setCursor(0, 1);
lcd.print(".line #2 ");
currentMillis = millis();
while(millis()-currentMillis<sample) {
for (byte x=0; x<BITMAP_W; x++) {
bitmap.line(x, 0, x, BITMAP_H-1, ON, UPDATE); // Draw the line from (x, 0) to (x, BITMAP_H-1) and update bitmap display
}
for (byte y=0; y<BITMAP_H; y++) {
bitmap.line(0, y, BITMAP_W-1, y, OFF, UPDATE);
}
}
bitmap.clear(); // Clear the display
// bitmap.rect
lcd.setCursor(0, 1);
lcd.print(".rect ");
currentMillis = millis();
while(millis()-currentMillis<sample) {
bitmap.rect(random(0, BITMAP_W), random(0, BITMAP_H), random(0, BITMAP_W), random(0, BITMAP_H), ON, UPDATE); // Draw a rectangle from (x1,y1) to (x2,y2) and update bitmap display
delay(150);
bitmap.clear(); // Clear the display
}
// bitmap.rectFill
lcd.setCursor(0, 1);
lcd.print(".rectFill");
currentMillis = millis();
while(millis()-currentMillis<sample*1.5) {
bitmap.rectFill(random(0, BITMAP_W), random(0, BITMAP_H), random(0, BITMAP_W), random(0, BITMAP_H), ON, NO_UPDATE); // Draw a filled rectangle from (x1,y1) to (x2,y2) and update bitmap display
bitmap.rectFill(random(0, BITMAP_W), random(0, BITMAP_H), random(0, BITMAP_W), random(0, BITMAP_H), OFF, NO_UPDATE); // Draw a filled rectangle from (x1,y1) to (x2,y2) and update bitmap display
bitmap.update(); // Filled rectangles drawn, now update bitmap display
delay(10);
}
bitmap.clear(); // Clear the display
// bitmap.barGraph
lcd.setCursor(0, 1);
lcd.print(".barGraph ");
byte bars=10;
byte graph[bars]; // 10 Bar graph values
currentMillis = millis();
while(millis()-currentMillis<sample*2) {
for (byte x=0; x<bars; x++) {
graph[x] = random(0, BITMAP_H); // Fill array with random height values
}
bitmap.barGraph(bars, graph, ON, UPDATE); // Display the bar graph
delay(10);
if (bars==10 && millis()-currentMillis>=sample) bars=4;
}
bitmap.clear(); // Clear the display
// This creates a big "X" using the LCDBitmap to show the inverse and move functions
for (byte x=0; x<=4; x++) {
bitmap.line(x, BITMAP_H-1, x+BITMAP_H-1, 0, ON, NO_UPDATE); // Draw a line, but don't update the bitmap display
bitmap.line(x, 0, x+BITMAP_H-1, BITMAP_H-1, ON, NO_UPDATE); // Draw a line, but don't update the bitmap display
}
bitmap.update(); // Now that everything is written to the bitmap, show the changes
// bitmap.inverse
lcd.setCursor(0, 1);
lcd.print(".inverse ");
delay(1000);
int x_status = 1;
currentMillis = millis();
while(millis()-currentMillis<sample/2) {
for (byte a=0; a<6; a++) {
bitmap.inverse(); // Invert the bitmap, automatically updates the bitmap display
x_status *= -1;
delay(75);
}
}
if (x_status==-1) bitmap.inverse();
// bitmap.move
bitmap.clear_text(); // Clear just the text on the display (leaves bitmap alone)
lcd.setCursor(0, 1);
lcd.print(".move");
for (byte x=11; x>4; x--) {
bitmap.move(x,0); // Move the LCD bitmap position to the left one position
delay(150);
}
for (byte x=6; x<13; x++) {
bitmap.move(x,0); // Move the LCD bitmap position to the right one position
delay(150);
}
bitmap.home(); // Move cursor the home position (0,0)
lcd.print("LCDBitmap");
delay(500);
// bitmap.clear
lcd.setCursor(0, 1);
lcd.print(".clear ");
delay(1000);
bitmap.clear(); // Clear the bitmap display only (automatically updates bitmap display) doesn't clear text
delay(2000);
}
My Other Arduino Libraries
NewPing Works with many ultrasonic sensors, can communicate using only one pin, very low lag, fast (up to 30 pings per second), timer interrupt method for event-driven sketches, light code, and much more.
LCDBitmap Arduino library that allows you to create a tiny 20x16 pixel bitmap (raster) display on a normally character-only Hitachi HD44780 based LCD display. Typical drawing functions like line, rectangle, invert, etc. Control is right down to the pixel level.
toneAC Replacement to the standard tone library with the advantage of nearly twice the volume, higher quality, can produce higher frequencies, 1.5k smaller compiled code, and less stress on the speaker.
toneAC2 Replacement to the standard tone library with the advantage of nearly twice the volume, 800 bytes smaller compiled code size, and less stress on the speaker.
NewTone About 1,200 bytes smaller code size than the standard tone library, faster execution time, exclusive use of port registers for fastest and smallest code, higher quality sound output than tone library.
TimerFreeTone Replacement to the standard tone library but without using timers. Also over 1.5k smaller compiled code, exclusive use of port registers, and compatible with ATmega, ATtiny, and ARM-based microcontrollers.
Updated