Skip to content

Instantly share code, notes, and snippets.

@haugstrup
Created July 29, 2012 17:15
Show Gist options
  • Save haugstrup/3200331 to your computer and use it in GitHub Desktop.
Save haugstrup/3200331 to your computer and use it in GitHub Desktop.
LCD proof of concept for johnny-five
// Wire up LCD as described here:
// http://learn.adafruit.com/character-lcds/overview
var five = require("johnny-five"),
board, lcd;
board = new five.Board();
board.on("ready", function() {
lcd = {
rsPin: 7, // LCD pin 4
// rwPin:, // LCD pin 5, only needed when reading from display
enPin: 8, // LCD pin 6
dataPins: [12, 11, 10, 9] // D7 to D4. LCD pins 14, 13, 12, 11
};
var sleep = function(milliSeconds) {
var startTime = new Date().getTime();
while (new Date().getTime() < startTime + milliSeconds);
};
var highLowFromBinary = function(number) {
return number === 1 ? board.firmata.HIGH : board.firmata.LOW;
};
var sendCommand = function(command) {
board.digitalWrite(lcd.dataPins[0], highLowFromBinary(command[0]));
board.digitalWrite(lcd.dataPins[1], highLowFromBinary(command[1]));
board.digitalWrite(lcd.dataPins[2], highLowFromBinary(command[2]));
board.digitalWrite(lcd.dataPins[3], highLowFromBinary(command[3]));
// Pulse the EN pin to send first nibble
board.digitalWrite(lcd.enPin, board.firmata.HIGH);
board.digitalWrite(lcd.enPin, board.firmata.LOW);
board.digitalWrite(lcd.dataPins[0], highLowFromBinary(command[4]));
board.digitalWrite(lcd.dataPins[1], highLowFromBinary(command[5]));
board.digitalWrite(lcd.dataPins[2], highLowFromBinary(command[6]));
board.digitalWrite(lcd.dataPins[3], highLowFromBinary(command[7]));
// Pulse the EN pin to send second nibble
board.digitalWrite(lcd.enPin, board.firmata.HIGH);
board.digitalWrite(lcd.enPin, board.firmata.LOW);
};
var writeMessage = function() {
board.digitalWrite(lcd.rsPin, board.firmata.LOW);
sendCommand([0,0,0,0,0,0,0,1]);
board.digitalWrite(lcd.rsPin, board.firmata.HIGH);
sendCommand([0,1,0,0,1,0,1,0]);
sleep(200);
sendCommand([0,1,1,0,1,1,1,1]);
sleep(200);
sendCommand([0,1,1,0,1,0,0,0]);
sleep(200);
sendCommand([0,1,1,0,1,1,1,0]);
sleep(200);
sendCommand([0,1,1,0,1,1,1,0]);
sleep(200);
sendCommand([0,1,1,1,1,0,0,1]);
sleep(200);
sendCommand([0,0,1,0,1,1,0,1]);
sleep(200);
sendCommand([0,1,1,0,0,1,1,0]);
sleep(200);
sendCommand([0,1,1,0,1,0,0,1]);
sleep(200);
sendCommand([0,1,1,1,0,1,1,0]);
sleep(200);
sendCommand([0,1,1,0,0,1,0,1]);
board.digitalWrite(lcd.rsPin, board.firmata.LOW);
};
// RS to low (for command mode), EN to low to start
board.digitalWrite(lcd.rsPin, board.firmata.LOW);
board.digitalWrite(lcd.enPin, board.firmata.LOW);
// Switch to 4-bit mode
board.digitalWrite(lcd.dataPins[0], board.firmata.LOW);
board.digitalWrite(lcd.dataPins[1], board.firmata.LOW);
board.digitalWrite(lcd.dataPins[2], board.firmata.HIGH);
board.digitalWrite(lcd.dataPins[3], board.firmata.LOW);
board.digitalWrite(lcd.enPin, board.firmata.HIGH);
board.digitalWrite(lcd.enPin, board.firmata.LOW);
// Set to two-line mode
sendCommand([0,0,1,0,1,0,0,0]);
// Clear display and turn it on
sendCommand([0,0,0,0,0,0,0,1]);
sendCommand([0,0,0,0,1,1,1,1]);
// Write some text
writeMessage();
});
@haugstrup
Copy link
Author

johnny-five: https://github.com/rwldrn/johnny-five

Video: https://vimeo.com/46577266

Next steps:

  • Figure out how to properly clear the display
  • Make a nice little LCD package for johnny-five so no-one have to learn these commands, ever

@rwaldron
Copy link

Wow, this looks exciting - I'll take it for a spin this evening. As for API wrapper stuff... you might consider using the LiquidCrystal API as a starting point http://arduino.cc/en/Reference/LiquidCrystal/

:)

@rmurphey
Copy link

Super excited to see this -- was just talking to @rwldrn the other day about LCD stuff with johnny-five. I might have to buy that LCD after all :) Which LCD is this?

@rwaldron
Copy link

I've been trying to figure that out based on the video — I have two LCD's one requires Software Serial to work and the other is I2C

@rmurphey
Copy link

I couldn't tell from my reading whether software serial was something that could be "faked" with enough code ... it seemed that the way it worked wasn't dissimilar to the way I sent messages to a shift register. I wonder if that's what's happening here? Hopefully @haugstrup will shed some light :)

@haugstrup
Copy link
Author

I knew I shouldn't have dumped this right before leaving for the day!

I know next to nothing about arduino/microcontrollers and electronic parts. This may all be total n00b information, but I had to start from scratch. :)

The LCD I'm using is a part of the Arduino starter kit that Rick told me to buy: http://www.makershed.com/Ultimate_Microcontroller_Pack_p/msump.htm

But that's not that important. What's important is that the driver is one of these guys: http://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller -- as far as I can tell most cheap 'character' LCDs use this driver. There are 16 pins (14 if the LCD doesn't have a backlight). A software serial lcd looks like it would be easier to interface with, but they's also twice as expensive...

So far so good. I thought I had to convert my cheap LCD to one that runs on the I2C bus. That would include wiring up one of these http://www.makershed.com/Positive_RGB_LCD_Shield_Kit_w_16x2_Character_Disp_p/mkad44.htm but I didn't have the parts and I live in downtown San Francisco so I have to mail order everything. And it would be rather silly to have to require that much wiring to control an lcd with javascript...

Fortunately these two PDFs explain in very simple terms how the LCD driver works:

Compared to the specs us webdevs usually have to deal with this is refreshingly simple. You set the data pins to high/low to match the command you want to send and then pulse the EN pin to high to actually send the command. The RS pin goes to LOW when sending commands and to HIGH when writing characters to the screen.

I'm still having trouble clearing the display so I have to power off the arduino before I can run the script again.

I had seen the Liquid Crystal arduino api, this would be a javascript implementation of the same thing so it'll make a ton of sense to use a similar format. Do either of you know where I can find the source code for that library? I tried searching but no luck...

I'll see if I can't wrap this up nicely really soon. It's very exciting to toy with :)

@haugstrup
Copy link
Author

Oh, and the big advantage of the I2C solution is that you can get away with only using 2 pins on the arduino. The straight connection I'm using requires 6 digital pins. But again: So much extra soldering with I2C...

@rmurphey
Copy link

I think this is the LiquidCrystal API source: https://github.com/arduino/Arduino/tree/master/libraries/LiquidCrystal. Thanks so much for the writeup! This is hugely helpful and I'll be adding an LCD to my next order :)

@rwaldron
Copy link

This is brilliant — I must have this LCD somewhere as well...

Also, I wrote a little function for converting chars to their full binary sequence.

@haugstrup
Copy link
Author

@rmurphy, Thanks for the link, I'm certain it will come in handy even though I don't speak C at all. You should definitely add an lcd to your next order. If you look in the PDFs you will see that you can create your own 5x8 pixel graphics to use as characters. I want to make bar charts/sparklines and whatnot (or an equalizer?)

@rwaldron, Can I see your function? I don't wan't to write any code I don't have to. :)

@rmurphey
Copy link

@haugstrup I opened an issue on johnny-five related to this, maybe we can move the implementation discussion there for easier collaboration?

@haugstrup
Copy link
Author

Sounds good :)

@rmurphey
Copy link

Also, see https://gist.github.com/3185390#L34 for turning an integer into a sequence of binary digits, which may be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment