8000 LCD support, misc. other fixes by natevw · Pull Request #31 · ecto/duino · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

LCD support, misc. other fixes #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 14, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,67 @@ Fade the to full brightness then back to minimal brightness in `interval` ms. De

Current brightness of the LED

##lcd

This is a port of the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal) into JavaScript. Note that communicating with the LCD requires use of the synchronous `board.delay()` busy loop which will block other node.js events from being processed for several milliseconds at a time. (This could be converted to pause a board-level buffered message queue instead.)

````javascript
var lcd = new d.LCD({
board: board,
pins: {rs:12, rw:11, e:10, data:[5, 4, 3, 2]}
});
lcd.begin(16, 2);
lcd.print("Hello Internet.");
````

In `options`, the "pins" field can either be an array matching a call to any of the [LiquidCrystal constructors](http://arduino.cc/en/Reference/LiquidCrystalConstructor) or an object with "rs", "rw" (optional), "e" and a 4- or 8-long array of "data" pins. Pins will default to `[12, 11, 5, 4, 3, 2]` if not provided.

###lcd.begin(), lcd.clear(), lcd.home(), lcd.setCursor(), lcd.scrollDisplayLeft(), lcd.scrollDisplayRight()

These should behave the same as their counterparts in the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal).

###lcd.display(on), lcd.cursor(on), lcd.blink(on), lcd.autoscroll(on)

These are similar to the methods in the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal), however they can take an optional boolean parameter. If true or not provided, the setting is enabled. If false, the setting is disabled. For compatibility `.noDisplay()`, `.noCursor()`, `.noBlink()` and `.noAutoscroll()` methods are provided as well.

###lcd.write(val), lcd.print(val)

These take a buffer, string or integer and send it to the display. The `.write` and `print` methods are equivalent, aliases to the same function.

###lcd.createChar(location, charmap)

Configures a custom character for code `location` (numbers 0–7). `charmap` can be a 40-byte buffer as in [the C++ method](http://arduino.cc/en/Reference/LiquidCrystalCreateChar), or an array of 5-bit binary strings, or a 40-character string with pixels denoted by any non-space (`' '`) character. These bits determine the 5x8 pixel pattern of the custom character.

````javascript
var square = new Buffer("1f1f1f1f1f1f1f1f", 'hex');

var smiley = [
'00000',
'10001',
'00000',
'00000',
'10001',
'01110',
'00000'
];

var random =
". .." +
" . . " +
". . ." +
" . . " +
" .. " +
". . " +
" . ." +
".. .." ;

lcd.createChar(0, square);
lcd.createChar(1, smiley);
lcd.createChar(2, random);
lcd.setCursor(5,2);
lcd.print(new Buffer("\0\1\2\1\0")); // NOTE: when `.print`ing a string, 'ascii' turns \0 into a space
````

##piezo

````javascript
Expand Down Expand Up @@ -164,6 +225,20 @@ setInterval(function(){
}, 1000);
````

##ping

See: <http://arduino.cc/en/Tutorial/Ping>

````javascript
var range = new arduino.Ping({
board: board
});

range.on('read', function () {
console.log("Distance to target (cm)", range.centimeters);
});
````

##servo

````javascript
Expand Down Expand Up @@ -213,6 +288,8 @@ What is implemented right now:
* `02` digitalRead
* `03` analogWrite
* `04` analogRead
* `97` ping
* `98` servo
* `99` debug

##pin
Expand Down
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ module.exports = {
Servo: require('./lib/servo'),
Sensor: require('./lib/sensor'),
Ping: require('./lib/ping'),
PIR: require('./lib/pir')
PIR: require('./lib/pir'),
LCD: require('./lib/lcd')
};
254 changes: 254 additions & 0 deletions lib/lcd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
// port of LiquidCrystal.cpp by natevw


// commands
LCD_CLEARDISPLAY = 0x01;
LCD_RETURNHOME = 0x02;
LCD_ENTRYMODESET = 0x04;
LCD_DISPLAYCONTROL = 0x08;
LCD_CURSORSHIFT = 0x10;
LCD_FUNCTIONSET = 0x20;
LCD_SETCGRAMADDR = 0x40;
LCD_SETDDRAMADDR = 0x80;

// flags for display entry mode
LCD_ENTRYRIGHT = 0x00;
LCD_ENTRYLEFT = 0x02;
LCD_ENTRYSHIFTINCREMENT = 0x01;
LCD_ENTRYSHIFTDECREMENT = 0x00;

// flags for display on/off control
LCD_DISPLAYON = 0x04;
LCD_DISPLAYOFF = 0x00;
LCD_CURSORON = 0x02;
LCD_CURSOROFF = 0x00;
LCD_BLINKON = 0x01;
LCD_BLINKOFF = 0x00;

// flags for display/cursor shift
LCD_DISPLAYMOVE = 0x08;
LCD_CURSORMOVE = 0x00;
LCD_MOVERIGHT = 0x04;
LCD_MOVELEFT = 0x00;

// flags for function set
LCD_8BITMODE = 0x10;
LCD_4BITMODE = 0x00;
LCD_2LINE = 0x08;
LCD_1LINE = 0x00;
LCD_5x10DOTS = 0x04;
LCD_5x8DOTS = 0x00;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these globals?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't really recall if there was a particular reason or not, but unless you're doing something fancy when loading subcomponents, they are module-scoped and shouldn't affect (or be affected by) anyone else's code.




var LCD = function (options) {
if (!options || !options.board) throw new Error('Must supply required options');
this.board = options.board;

var pins = options.pins || [12, 11, 5, 4, 3, 2];
if (!Array.isArray(pins))
this.pins = pins;
else if (pins.length % 2)
this.pins = {rs:pins[0], rw:pins[1], e:pins[2], data:pins.slice(3)};
else
this.pins = {rs:pins[0], e:pins[1], data:pins.slice(2)};
if (!('rw' in this.pins)) this.pins.rw = 255;

this.board.pinMode(this.pins.rs, 'out');
if (this.pins.rw !== 255) {
this.board.pinMode(this.pins.rw, 'out');
}
this.board.pinMode(this.pins.e, 'out');

this.begin(16, 1);
}

LCD.prototype.begin = function (cols, lines, dotsize) {
this._numlines = lines;

var displayfunction = 0;
displayfunction |= (lines > 1) ? LCD_2LINE : LCD_1LINE;
displayfunction |= (dotsize && lines === 1) ? LCD_5x10DOTS : LCD_5x8DOTS;

this._delayMicroseconds(50000);
this.board.digitalWrite(this.pins.rs, this.board.LOW);
this.board.digitalWrite(this.pins.e, this.board.LOW);
if (this.pins.rw !== 255)
this.board.digitalWrite(this.pins.rw, this.board.LOW);

// put the LCD into 4 bit or 8 bit mode
if (this.pins.data.length === 4) {
displayfunction |= LCD_4BITMODE;
this._writeNbits(4, 0x03);
this._delayMicroseconds(4500);
this._writeNbits(4, 0x03);
this._delayMicroseconds(4500);
this._writeNbits(4, 0x03);
this._delayMicroseconds(150);
this._writeNbits(4, 0x02);
} else {
displayfunction |= LCD_8BITMODE;
this.command(LCD_FUNCTIONSET | displayfunction);
this._delayMicroseconds(4500);
this.command(LCD_FUNCTIONSET | displayfunction);
this._delayMicroseconds(150);
this.command(LCD_FUNCTIONSET | displayfunction);
}

this.command(LCD_FUNCTIONSET | displayfunction);

this._displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
this.display();

this.clear();

this._displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
this.leftToRight();
}

LCD.prototype.clear = function () {
this.command(LCD_CLEARDISPLAY);
this._delayMicroseconds(2000); // this command takes a long time!
}

LCD.prototype.home = function () {
this.command(LCD_RETURNHOME);
this._delayMicroseconds(2000);
}

LCD.prototype.setCursor = function (col, row) {
if (row >= this._numlines) {
row = this._numlines - 1;
}

var row_offsets = [0x00, 0x40, 0x14, 0x54];
this.command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}

LCD.prototype.display = function (on) {
on = (arguments.length) ? on : true;
if (on) this._displaycontrol |= LCD_DISPLAYON
else this._displaycontrol &= ~LCD_DISPLAYON;
this.command(LCD_DISPLAYCONTROL | this._displaycontrol);
}

LCD.prototype.noDisplay = function () { this.display(false); }

LCD.prototype.cursor = function (on) {
on = (arguments.length) ? on : true;
if (on) this._displaycontrol |= LCD_CURSORON
else this._displaycontrol &= ~LCD_CURSORON;
this.command(LCD_DISPLAYCONTROL | this._displaycontrol);
}

LCD.prototype.noCursor = function () { this.cursor(false); }

LCD.prototype.blink = function (on) {
on = (arguments.length) ? on : true;
if (on) this._displaycontrol |= LCD_BLINKON
else this._displaycontrol &= ~LCD_BLINKON;
this.command(LCD_DISPLAYCONTROL | this._displaycontrol);
}

LCD.prototype.noBlink = function () { this.blink(false); }

LCD.prototype.scrollDisplayLeft = function () {
this.command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}

LCD.prototype.scrollDisplayRight = function () {
this.command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}


LCD.prototype.leftToRight = function () {
this._displaymode |= LCD_ENTRYLEFT;
this.command(LCD_ENTRYMODESET | this._displaymode);
}

LCD.prototype.rightToLeft = function () {
this._displaymode &= ~LCD_ENTRYLEFT;
this.command(LCD_ENTRYMODESET | this._displaymode);
}

LCD.prototype.autoscroll = function (on) {
on = (arguments.length) ? on : true;
if (on) this._displaymode |= LCD_ENTRYSHIFTINCREMENT
else this._displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
this.command(LCD_ENTRYMODESET | this._displaymode);
}

LCD.prototype.noAutoscroll = function () { this.autoscroll(false); }

LCD.prototype.createChar = function (location, charmap) {
location &= 0x7;
this.command(LCD_SETCGRAMADDR | (location << 3));

var buffer = new Buffer(8);
if (Array.isArray(charmap)) for (var i = 0; i < 8; i++) {
buffer[i] = parseInt(charmap[i], 2);
} else if (typeof charmap === 'string') for (var i = 0; i < 8; i++) {
var byte = 0;
if (charmap[5*i + 0] !== ' ') byte |= 0x10;
if (charmap[5*i + 1] !== ' ') byte |= 0x08;
if (charmap[5*i + 2] !== ' ') byte |= 0x04;
if (charmap[5*i + 3] !== ' ') byte |= 0x02;
if (charmap[5*i + 4] !== ' ') byte |= 0x01;
buffer[i] = byte;
} else buffer = charmap;
this.write(buffer);
}

LCD.prototype.write = LCD.prototype.print = function (str) {
// TODO: map misc Unicode chars to typical LCD extended charset?
var bytes = (typeof str === 'string') ? new Buffer(str, 'ascii') :
(typeof str === 'object') ? str : new Buffer([str]);
for (var i = 0, len = bytes.length; i < len; i++)
this.send(bytes[i], this.board.HIGH);
}


/*
* mid/low level stuff
*/

LCD.prototype.command = function (value) {
this.send(value, this.board.LOW);
}

LCD.prototype.send = function (value, mode) {
this.board.digitalWrite(this.pins.rs, mode);
if (this.pins.rw !== 255) {
this.board.digitalWrite(this.pins.rw, this.board.LOW);
}
if (this.pins.data.length === 8) {
this._writeNbits(8, value);
} else {
this._writeNbits(4, value >> 4);
this._writeNbits(4, value & 0xF);
}
}

LCD.prototype._writeNbits = function (n, value) {
for (var i = 0; i < n; i++) {
this.board.pinMode(this.pins.data[i], 'out');
var bit = (value >> i) & 0x01;
this.board.digitalWrite(this.pins.data[i], (bit) ? this.board.HIGH : this.board.LOW);
}
this._pulseEnable();
}

LCD.prototype._pulseEnable = function () {
this.board.digitalWrite(this.pins.e, this.board.LOW);
this._delayMicroseconds(1);
this.board.digitalWrite(this.pins.e, this.board.HIGH);
this._delayMicroseconds(1); // enable pulse must be >450ns
this.board.digitalWrite(this.pins.e, this.board.LOW);
this._delayMicroseconds(100); // commands need > 37us to settle
}

LCD.prototype._delayMicroseconds = function (us) {
this.board.delay(us/1000);
}

module.exports = LCD;
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
"contributors": [
{ "name": "Rick Waldron", "email": "waldron.rick@gmail.com" },
{ "name": "Leonhardt Wille", "email": "wille@riverlabs.de" },
{ "name": "Seiya Konno", "email": "nulltask@gmail.com" }
{ "name": "Seiya Konno", "email": "nulltask@gmail.com" },
{ "name": "Nathan Vander Wilt", "email": "nate@calftrail.com" },
{ "name": "Adam Brault (&yet)", "email": "contact@andyet.com" }
],
"name": "duino",
"description": "Arduino framework for mad scientists",
"version": "0.0.7",
"version": "0.0.8",
"keywords": [
"arduino",
"serial",
Expand Down
4 changes: 2 additions & 2 deletions src/du.ino
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ void process() {
aux[3] = '\0';
} else {
strncpy(val, messageBuffer + 4, 3);
val[4] = '\0';
val[3] = '\0';
strncpy(aux, messageBuffer + 7, 3);
aux[4] = '\0';
aux[3] = '\0';
}

if (debug) {
Expand Down
0