Last active
November 8, 2015 04:37
-
-
Save pearlchen/31ac996f8688a01cc5b6 to your computer and use it in GitHub Desktop.
Scroll text across your Grove LCD screen using JavaScript on the Intel Edison or Intel Galileo. Video: https://twitter.com/PearlChen/status/588890387260903424. And check it out within a larger project: https://github.com/pearlchen/iot-smart-desk-clock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global setInterval: false, setTimeout: false, clearInterval: false, clearTimeout:false, module: false, console: false */ | |
/** | |
* Module exports. | |
*/ | |
module.exports = LcdTextHelper; | |
/** | |
* LcdTextHelper constructor. | |
* | |
* @param {Jhd1313m1} UPM I2C LCD instance | |
* @api public | |
*/ | |
function LcdTextHelper(lcd) { | |
var TOTAL_LCD_ROWS = 2; | |
var TOTAL_LCD_COLUMNS = 16; | |
var KEEP_TEXT_ON_SCREEN_DELAY = 2000; // in ms | |
var TEXT_UPDATE_INTERVAL = 550; // in ms, should be less than TEXT_DRAW_INTERVAL | |
var TEXT_DRAW_INTERVAL = 500; // in ms, should be more than TEXT_UPDATE_INTERVAL | |
var REPEATING_TEXT_PADDING = " "; // whitespace between looping message when text is scrolling | |
var BLANK_ROW_TEXT = " "; // exactly 16 space characters | |
var lcdRows = []; //var EXAMPLE_ROW_OBJECT = { displayText: BLANK_ROW_TEXT, updateDisplayTextIntervalId: 0 }; | |
var startScrollingTimeoutId = 0; | |
var drawIntervalId = 0; | |
/** | |
* Takes array of message strings to display. | |
* Later uses string lengths to set text on LCD with or without scrolling. | |
* | |
* @param {string[]} messages - Each string in the array corresponds to a row on the LCD. | |
* @api public | |
*/ | |
function set(messages){ | |
reset(); | |
messages = messages || []; // default, empty array | |
if (messages.length > TOTAL_LCD_ROWS) { | |
console.log("This LCD screen only supports %s rows of text but you tried to give me %s", TOTAL_LCD_ROWS, messages.length); | |
messages.length = TOTAL_LCD_ROWS; // truncate array, if needed | |
} | |
for (var row=0; row<messages.length; row++) { | |
var msg = messages[row]; | |
if (msg.length < TOTAL_LCD_COLUMNS) { | |
msg = msg + BLANK_ROW_TEXT.slice(msg.length); // fill in any remaining gaps with spaces | |
} else if (msg.length > TOTAL_LCD_COLUMNS) { | |
msg = msg + REPEATING_TEXT_PADDING; // add padding for looping text | |
} | |
// create a new slot in lcdRows to save the display string | |
// (and later save any scrolling interval timer IDs) | |
lcdRows[row] = {displayText: msg}; | |
} | |
// immediately draw text to LCD then, after a slight startup delay, start scrolling effect | |
draw(); | |
startScrollingTimeoutId = setTimeout(startScrolling, KEEP_TEXT_ON_SCREEN_DELAY); | |
} | |
/** | |
* Checks length of display text strings and, if long enough for scrolling, will: | |
* - Add a timer interval for each row to update the string value to give illusion of scrolling. | |
* - Add a timer interval to re-draw all strings to the LCD. | |
* | |
* @api private | |
*/ | |
function startScrolling() { | |
var totalScrolling = 0; | |
for (var r=0; r<lcdRows.length; r++) { | |
if (lcdRows[r].displayText.length > TOTAL_LCD_COLUMNS) { | |
lcdRows[r].updateDisplayTextIntervalId = setInterval(updateScrollingRow, TEXT_UPDATE_INTERVAL, r); | |
totalScrolling++; | |
} | |
} | |
if (totalScrolling > 0) { | |
drawIntervalId = setInterval(draw, TEXT_DRAW_INTERVAL); | |
} | |
} | |
/** | |
* Takes the first character of the display string and moves it to the end | |
* of the string to give the illusion of scrolling. | |
* | |
* @api private | |
*/ | |
function updateScrollingRow(row){ | |
var currentText = lcdRows[row].displayText; | |
var shiftedText = currentText.slice(1) + currentText.slice(0, 1); | |
lcdRows[row].displayText = shiftedText; | |
} | |
/** | |
* Draws all display strings to the LCD | |
* | |
* @api private | |
*/ | |
function draw() { | |
//console.log("----------------"); | |
for (var r=0; r<lcdRows.length; r++) { | |
var text = lcdRows[r].displayText.slice(0, TOTAL_LCD_COLUMNS); | |
//console.log(text); | |
lcd.setCursor(r, 0); | |
lcd.write(text); | |
} | |
} | |
/** | |
* Clear LCD screen and clear any timer events that might try to write to the screen | |
* | |
* @api public | |
*/ | |
function reset() { | |
// write blank rows instead of lcd.clear() | |
// which takes too long to execute and messes up drawn text sometimes | |
lcd.setCursor(0, 0); | |
lcd.write(BLANK_ROW_TEXT); | |
lcd.setCursor(1, 0); | |
lcd.write(BLANK_ROW_TEXT); | |
clearInterval(drawIntervalId); | |
clearTimeout(startScrollingTimeoutId); | |
for (var r=0; r<lcdRows.length; r++) { | |
var rowObject = lcdRows[r]; | |
clearInterval(rowObject.updateDisplayTextIntervalId); | |
} | |
lcdRows.length = 0; | |
} | |
/** | |
* Return public methods for module.exports. | |
*/ | |
return { | |
set: set, | |
reset: reset | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global require: false, setInterval: false, setTimeout: false, clearInterval: false, clearTimeout:false, module: false, console: false */ | |
/** | |
* Module dependencies. | |
*/ | |
var mraa = require('mraa'); | |
/* | |
If you get any mraa missing errors, run this on your board: | |
$ echo "src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/mraa-upm.conf | |
$ opkg update | |
$ opkg install libmraa0 | |
*/ | |
var jsUpmI2cLcd = require('jsupm_i2clcd'); | |
/* | |
If you get any upm missing errors, run this on your board: | |
$ opkg install upm | |
*/ | |
var LcdTextHelper = require('./lcd_text_helper'); | |
/* | |
Download lcd_text_helper.js from https://gist.github.com/pearlchen/31ac996f8688a01cc5b6 | |
*/ | |
/** | |
* Initialization. | |
*/ | |
// Initialize the LCD. | |
// The 1st param is the BUS ID: | |
// Intel Edison: Use 6 | |
// Intel Galileo Gen 2: Use 6 (TODO: unconfirmed) | |
// Intel Galileo Gen 1: Use 0 | |
var lcd = new jsUpmI2cLcd.Jhd1313m1(6, 0x3E, 0x62); | |
var lcdText = new LcdTextHelper(lcd); | |
/** | |
* Try it out with some test messages. | |
*/ | |
var LCD_MESSAGE_VERY_LONG = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxyz"; // >16 characters long (48 chars) | |
var LCD_MESSAGE_LONG = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // >16 characters long (24 chars) | |
var LCD_MESSAGE_16CHAR = "1234567890ABCDEF"; // ==16 characters long | |
var LCD_MESSAGE_SHORT = "1234567890"; // <16 characters long (10 chars) | |
var LCD_MESSAGE_VERY_SHORT = "ABC"; // <16 characters long (3 chars) | |
lcdText.set([ | |
" Hello,", | |
" World!" | |
]); | |
setTimeout(function(){ | |
lcdText.set([ | |
LCD_MESSAGE_SHORT, | |
LCD_MESSAGE_VERY_SHORT | |
]); | |
}, 5000); | |
setTimeout(function(){ | |
lcdText.set([ | |
LCD_MESSAGE_LONG, | |
LCD_MESSAGE_VERY_LONG | |
]); | |
}, 10000); |
Updated:
- Breaking changes: removed
init()
. Pass in lcd instance using the constructor, e.g.var lcdText = new LcdTextHelper(lcd);
- performance improvements
- minor bug fixes
- added JSDocs comments
- passes jsLint
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some quick notes about my implementation:
BLANK_ROW_TEXT
andmsg = msg + BLANK_ROW_TEXT.slice(msg.length);