Closed SteadEXE closed 9 years ago
i2c-bus writeI2cBlockSync should work as a replacement for node-i2c writeBytes,
Under the covers, node-i2c writeBytes has the same 32 byte limitation as can be seen here, but it just ignores the 33rd byte and beyond. i2c-bus writeI2cBlockSync throws an error when passed more than 32 bytes.
Perhaps there's a logical error in the original adafruit-i2c-lcd or in the rewrite. Maybe in this section of code which handles the 32 byte limit specially?
Can I give you the code I rewrote to got an external point of view, because it seems to not work as intended ?
Thanks for your reply :)
Sure, add the code here in the issue.
// Port expander registers var MCP23017_IOCON_BANK0 = 0x0A; // #IOCON when Bank 0 active var MCP23017_IOCON_BANK1 = 0x15; // #IOCON when Bank 1 active // These are register addresses when in Bank 1 only: var MCP23017_GPIOA = 0x09; var MCP23017_IODIRB = 0x10; var MCP23017_GPIOB = 0x19;
// LCD Commands var LCD_CLEARDISPLAY = 0x01; var LCD_RETURNHOME = 0x02; var LCD_ENTRYMODESET = 0x04; var LCD_DISPLAYCONTROL = 0x08; var LCD_CURSORSHIFT = 0x10; var LCD_FUNCTIONSET = 0x20; var LCD_SETCGRAMADDR = 0x40; var LCD_SETDDRAMADDR = 0x80;
// Flags for display on/off control var LCD_DISPLAYON = 0x04; var LCD_DISPLAYOFF = 0x00; var LCD_CURSORON = 0x02; var LCD_CURSOROFF = 0x00; var LCD_BLINKON = 0x01; var LCD_BLINKOFF = 0x00;
// Flags for display entry mode var LCD_ENTRYRIGHT = 0x00; var LCD_ENTRYLEFT = 0x02; var LCD_ENTRYSHIFTINCREMENT = 0x01; var LCD_ENTRYSHIFTDECREMENT = 0x00;
// Flags for display/cursor shift var LCD_DISPLAYMOVE = 0x08; var LCD_CURSORMOVE = 0x00; var LCD_MOVERIGHT = 0x04; var LCD_MOVELEFT = 0x00;
var flip = [ 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E ];
var pollables = [ LCD_CLEARDISPLAY, LCD_RETURNHOME ];
var EventEmitter = require('events').EventEmitter; var I2C = require('i2c-bus');
var Plate = function(device, address, pollInterval) {
this.ADDRESS = address;
this.PORTA = 0;
this.PORTB = 0;
this.DDRB = 0x10;
this.WIRE = I2C.openSync(1);
this.BSTATE = 0;
this.colors = {
OFF: 0x00,
RED: 0x01,
GREEEN: 0x02,
YELLOW: 0x03,
BLUE: 0x04,
VIOLET: 0x05,
TEAL: 0x06,
WHITE: 0x07,
ON: 0x07
}
this.buttons = {
SELECT: 0x01,
RIGHT: 0x02,
DOWN: 0x04,
UP: 0x08,
LEFT: 0x10
}
this.clear = function() {
this.writeByte(LCD_CLEARDISPLAY);
}
this.home = function() {
this.writeByte(LCD_RETURNHOME);
}
this.close = function() {
if (poll != null)
clearInterval(poll);
}
this.backlight = function(colors) {
this.PORTA = (this.PORTA & 0x3F) | ((~colors & 0x3) << 6);
this.PORTB = (this.PORTB & 0xFE) | ((~colors & 0x4) >> 2);
this.sendBytes(MCP23017_GPIOA, this.PORTA);
this.sendBytes(MCP23017_GPIOB, this.PORTB);
}
this.message = function(text) {
var lines = text.split('\n');
for (var line in lines)
if (line == 1)
this.writeByte(0xC0);
if (line < 2)
this.writeByte(lines[line], true);
}
this.buttonState = function() {
var ret = this.WIRE.readBytes(MCP23017_GPIOA, 1);
ret = ret[0] & 0x1F;
return ret;
}
this.init = function()
{
this.sendBytes(MCP23017_IOCON_BANK1, 0);
this.sendBytes(0, [
0x3F, // IODIRA R+G LEDs=outputs, buttons=inputs
this.DDRB, // IODIRB LCD D7=input, Blue LED=output
0x3F, // IPOLA Invert polarity on button inputs
0x0, // IPOLB
0x0, // GPINTENA Disable interrupt-on-change
0x0, // GPINTENB
0x0, // DEFVALA
0x0, // DEFVALB
0x0, // INTCONA
0x0, // INTCONB
0x0, // IOCON
0x0, // IOCON
0x3F, // GPPUA Enable pull-ups on buttons
0x0, // GPPUB
0x0, // INTFA
0x0, // INTFB
0x0, // INTCAPA
0x0, // INTCAPB
this.PORTA, // GPIOA
this.PORTB, // GPIOB
this.PORTA, // OLATA 0 on all outputs; side effect of
this.PORTB // OLATB turning on R+G+B backlight LEDs.
]);
this.sendBytes(MCP23017_IOCON_BANK0, 0xA0);
var displayshift = LCD_CURSORMOVE | LCD_MOVERIGHT;
var displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
var displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
this.writeByte(0x33);
this.writeByte(0x32);
this.writeByte(0x28);
this.writeByte(LCD_CLEARDISPLAY);
this.writeByte(LCD_CURSORSHIFT | displayshift);
this.writeByte(LCD_ENTRYMODESET | displaymode);
this.writeByte(LCD_DISPLAYCONTROL | displaycontrol);
this.writeByte(LCD_RETURNHOME);
this.clear();
this.backlight(0x0);
}
this.sendBytes = function(cmd, values) {
var cmd = new Buffer([ cmd ]);
var bytes;
if (values instanceof Array)
bytes = new Buffer(values);
else
bytes = new Buffer([ values ]);
var buffer = Buffer.concat([ cmd, bytes ]);
this.WIRE.i2cWriteSync(this.ADDRESS, buffer.length, buffer);
}
this.sendByte = function(value) {
this.WIRE.i2cWriteSync(this.ADDRESS, 1, value);
}
this.maskOut = function(bitmask, value) {
hi = bitmask | flip[value >> 4];
lo = bitmask | flip[value & 0x0F];
return [ hi | 0x20, hi, lo | 0x20, lo ];
}
this.writeByte = function(value, char_mode) {
var char_mode = char_mode || false;
if (this.DDRB & 0x10)
{
var lo = (this.PORTB & 0x01) | 0x40;
var hi = lo | 0x20;
this.sendBytes(MCP23017_GPIOB, lo);
var bits;
do {
this.sendByte(hi);
bits = this.readByte();
this.sendBytes(MCP23017_GPIOB, [lo, hi, lo])
} while ((bits & 0x2) != 0);
this.PORTB = lo;
this.DDRB &= 0xEF;
this.sendBytes(MCP23017_IODIRB, this.DDRB);
}
var bitmask = this.PORTB & 0x01;
bitmask = (char_mode) ? bitmask | 0x80 : bitmask;
if (value instanceof String)
{
var last = value.length - 1;
var data = [];
for (var k = 0; k <= last; k++)
{
if (value[k])
{
data = data.concat(this.maskOut(bitmask, value[k].charCodeAt(0)));
if (data.length >= 32 || k == last)
{
this.sendBytes(MCP23017_GPIOB, data);
this.PORTB = data[data.length - 1];
data = []
}
}
}
}
else
{
data = this.maskOut(bitmask, value);
this.sendBytes(MCP23017_GPIOB, data);
this.PORTB = data[data.length - 1];
}
if(!char_mode && pollables.indexOf(value)!=-1)
{
this.DDRB |= 0x10;
this.sendBytes(MCP23017_IODIRB, this.DDRB);
}
}
this.readByte = function() {
var _byte_ = new Buffer(1);
this.WIRE.i2cReadSync(this.ADDRESS, 1, _byte_);
return _byte_;
}
var pollInterval = pollInterval || 200;
/*if (pollInterval > 0)
{
this.poll = setInterval(function() {
var cur = this.buttonState();
if (cur != this.BSTATE)
{
var key = this.BSTATE ^ cur;
emit("button_change", key);
if (cur < this.BSTATE)
emit("button_up", key);
else
emit("button_down", key);
this.BSTATE = cur;
}
}, pollInterval);
}*/
this.init();
}
module.exports = Plate;
I tried with writeI2cBlockSync in sendBytes method but it throw an error. I tried to translate adafruit_i2c_lcd.coffee to javascript.
I can't see any calls to writeI2cBlockSync in the above code but see that sendBytes is now using i2cWriteSync. What currently doesn't function correctly?
// Port expander registers var MCP23017_IOCON_BANK0 = 0x0A; // #IOCON when Bank 0 active var MCP23017_IOCON_BANK1 = 0x15; // #IOCON when Bank 1 active // These are register addresses when in Bank 1 only: var MCP23017_GPIOA = 0x09; var MCP23017_IODIRB = 0x10; var MCP23017_GPIOB = 0x19;
// LCD Commands var LCD_CLEARDISPLAY = 0x01; var LCD_RETURNHOME = 0x02; var LCD_ENTRYMODESET = 0x04; var LCD_DISPLAYCONTROL = 0x08; var LCD_CURSORSHIFT = 0x10; var LCD_FUNCTIONSET = 0x20; var LCD_SETCGRAMADDR = 0x40; var LCD_SETDDRAMADDR = 0x80;
// Flags for display on/off control var LCD_DISPLAYON = 0x04; var LCD_DISPLAYOFF = 0x00; var LCD_CURSORON = 0x02; var LCD_CURSOROFF = 0x00; var LCD_BLINKON = 0x01; var LCD_BLINKOFF = 0x00;
// Flags for display entry mode var LCD_ENTRYRIGHT = 0x00; var LCD_ENTRYLEFT = 0x02; var LCD_ENTRYSHIFTINCREMENT = 0x01; var LCD_ENTRYSHIFTDECREMENT = 0x00;
// Flags for display/cursor shift var LCD_DISPLAYMOVE = 0x08; var LCD_CURSORMOVE = 0x00; var LCD_MOVERIGHT = 0x04; var LCD_MOVELEFT = 0x00;
var flip = [ 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E ];
var pollables = [ LCD_CLEARDISPLAY, LCD_RETURNHOME ];
var EventEmitter = require('events').EventEmitter; var I2C = require('i2c-bus');
var Plate = function(device, address, pollInterval) {
this.ADDRESS = address;
this.PORTA = 0;
this.PORTB = 0;
this.DDRB = 0x10;
this.WIRE = I2C.openSync(1);
this.BSTATE = 0;
this.colors = {
OFF: 0x00,
RED: 0x01,
GREEEN: 0x02,
YELLOW: 0x03,
BLUE: 0x04,
VIOLET: 0x05,
TEAL: 0x06,
WHITE: 0x07,
ON: 0x07
}
this.buttons = {
SELECT: 0x01,
RIGHT: 0x02,
DOWN: 0x04,
UP: 0x08,
LEFT: 0x10
}
this.clear = function() {
this.writeByte(LCD_CLEARDISPLAY);
}
this.home = function() {
this.writeByte(LCD_RETURNHOME);
}
this.close = function() {
if (poll != null)
clearInterval(poll);
}
this.backlight = function(colors) {
this.PORTA = (this.PORTA & 0x3F) | ((~colors & 0x3) << 6);
this.PORTB = (this.PORTB & 0xFE) | ((~colors & 0x4) >> 2);
this.sendBytes(MCP23017_GPIOA, this.PORTA);
this.sendBytes(MCP23017_GPIOB, this.PORTB);
}
this.message = function(text) {
var lines = text.split('\n');
for (var line in lines)
if (line == 1)
this.writeByte(0xC0);
if (line < 2)
this.writeByte(lines[line], true);
}
this.buttonState = function() {
var ret = this.WIRE.readBytes(MCP23017_GPIOA, 1);
ret = ret[0] & 0x1F;
return ret;
}
this.init = function()
{
this.sendBytes(MCP23017_IOCON_BANK1, 0);
this.sendBytes(0, [
0x3F, // IODIRA R+G LEDs=outputs, buttons=inputs
this.DDRB, // IODIRB LCD D7=input, Blue LED=output
0x3F, // IPOLA Invert polarity on button inputs
0x0, // IPOLB
0x0, // GPINTENA Disable interrupt-on-change
0x0, // GPINTENB
0x0, // DEFVALA
0x0, // DEFVALB
0x0, // INTCONA
0x0, // INTCONB
0x0, // IOCON
0x0, // IOCON
0x3F, // GPPUA Enable pull-ups on buttons
0x0, // GPPUB
0x0, // INTFA
0x0, // INTFB
0x0, // INTCAPA
0x0, // INTCAPB
this.PORTA, // GPIOA
this.PORTB, // GPIOB
this.PORTA, // OLATA 0 on all outputs; side effect of
this.PORTB // OLATB turning on R+G+B backlight LEDs.
]);
this.sendBytes(MCP23017_IOCON_BANK0, 0xA0);
var displayshift = LCD_CURSORMOVE | LCD_MOVERIGHT;
var displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
var displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
this.writeByte(0x33);
this.writeByte(0x32);
this.writeByte(0x28);
this.writeByte(LCD_CLEARDISPLAY);
this.writeByte(LCD_CURSORSHIFT | displayshift);
this.writeByte(LCD_ENTRYMODESET | displaymode);
this.writeByte(LCD_DISPLAYCONTROL | displaycontrol);
this.writeByte(LCD_RETURNHOME);
this.clear();
this.backlight(0x0);
}
this.sendBytes = function(cmd, values) {
var buffer;
if (values instanceof Array)
buffer = new Buffer(values);
else
buffer = new Buffer([ values ]);
console.log(buffer);
this.WIRE.writeI2cBlockSync(this.ADDRESS, cmd, buffer.length, buffer);
}
this.sendByte = function(value) {
this.WIRE.i2cWriteSync(this.ADDRESS, 1, value);
}
this.maskOut = function(bitmask, value) {
hi = bitmask | flip[value >> 4];
lo = bitmask | flip[value & 0x0F];
return [ hi | 0x20, hi, lo | 0x20, lo ];
}
this.writeByte = function(value, char_mode) {
var char_mode = char_mode || false;
if (this.DDRB & 0x10)
{
var lo = (this.PORTB & 0x01) | 0x40;
var hi = lo | 0x20;
this.sendBytes(MCP23017_GPIOB, lo);
var bits;
do {
this.sendByte(hi);
bits = this.readByte();
this.sendBytes(MCP23017_GPIOB, [lo, hi, lo])
} while ((bits & 0x2) != 0);
this.PORTB = lo;
this.DDRB &= 0xEF;
this.sendBytes(MCP23017_IODIRB, this.DDRB);
}
var bitmask = this.PORTB & 0x01;
bitmask = (char_mode) ? bitmask | 0x80 : bitmask;
if (value instanceof String)
{
var last = value.length - 1;
var data = [];
for (var k = 0; k < last; k++)
{
if (value[k])
{
data = data.concat(this.maskOut(bitmask, value[k].charCodeAt(0)));
if (data.length >= 32 || k == last)
{
this.sendBytes(MCP23017_GPIOB, data);
this.PORTB = data[data.length - 1];
data = []
}
}
}
}
else
{
data = this.maskOut(bitmask, value);
this.sendBytes(MCP23017_GPIOB, data);
this.PORTB = data[data.length - 1];
}
if(!char_mode && pollables.indexOf(value)!=-1)
{
this.DDRB |= 0x10;
this.sendBytes(MCP23017_IODIRB, this.DDRB);
}
}
this.readByte = function() {
var _byte_ = new Buffer(1);
this.WIRE.i2cReadSync(this.ADDRESS, 1, _byte_);
return _byte_;
}
var pollInterval = pollInterval || 200;
/*if (pollInterval > 0)
{
this.poll = setInterval(function() {
var cur = this.buttonState();
if (cur != this.BSTATE)
{
var key = this.BSTATE ^ cur;
emit("button_change", key);
if (cur < this.BSTATE)
emit("button_up", key);
else
emit("button_down", key);
this.BSTATE = cur;
}
}, pollInterval);
}*/
this.init();
}
module.exports = Plate;
I replaced "for (var k = 0; k <= last; k++)" by "for (var k = 0; k < last; k++)" It seems to work without throw exception.
Then on my main program I use: var LCDPlate = require("./LCD.js"); var LCD = new LCDPlate('/dev/i2c-1', 0x20);
LCD.backlight(th.colors.red); LCD.message("Hello world!");
On my PI the LCD turn on for 1 second and all LEDs are turning off and a special char is displayed. LEDs never turn red, and hello world is never displayed.
Thanks for help :-)
Hmm, ...
Sorry, but I'm afraid I can't help you out here. There's too much code there for attempting to figure out what's going wrong.
@Stead68 I'm going to close this one. If there's a concrete issue with i2c-bus, feel free to re-open or create a new issue.
Hello,
I totally rewrote adafruit-i2c-lcd which works with node-i2c, because it seems to be broken with latest version of node.js. I decided to use i2c-bus, but I don't found equivalent of wire.writeBytes(cmd, bytes); I tried:
var buf = new Buffer(values); bus.writeI2cBlockSync(this.ADDRESS, cmd, buf.length, buf);
But data length are over 32 bytes and it doesn't works. Do you have any idea about how can I fix it ?
Thanks guys.