Blog Index | Next >> |
---|
Last week I promised to add an I2C node to Node-RED in order to control the PCF8574ANPCF8574AN IO expander.
Unfortunately I lost a lot of time in trying all kind of different options, got stuck in version differences and didn't have much progress. In the mean time I came across Johnny-Five: The JavaScript Robotics & IoT Platform. Luckily this platform brought me again on track. I will very briefly mention my actions regarding Node-RED, and then explain how I got my expander working.
I2C on Node-RED
First library I found and tried was https://flows.nodered.org/node/node-red-contrib-i2c. Although only the Raspery Pi is mentioned in the documentation I expected it to work on the Edison as wel. Unfortunately it didn't, not because of the hardware difference, but because this library needs a newer Node.js version than the one which is installed on the Edison. I couldn't upgrade Node.js using the package manager. I also learned from the other challengers that they all have the same version as I do (Which Node.js version are you running on the Edison?). I decided not to try to update it from source, because according to what I found on the internet that will take at least five hours.
Here is an image of the flow. As you can see the scan bus (I2C-1) doesn't give any result and the send to i2c gives an "TypeError: Buffer.allocUnsafe is not a function" which according to what I found on the internet is related to an outdated Node.js version.
Next one I tried was https://flows.nodered.org/node/node-red-contrib-gpio. A set of input and output nodes for controlling General Purpose Input and Outputs (GPIOs) though the use of johnny-five I/O Plugins as well as running johnny-five scripts! Here is where Johnny-Five comes in. jasonwier92 already mentioned it (Getting To Know the Sensors with Node-Red [Upcycle It #3] ) briefly. Here is a picture of what I tested:
As you can see all GPIO nodes (the yellow ones) are properly connected to Johnny Five as indicated by 'connected!!!!'. The 'led' node for which a grove led block connected to D2 was used, nicely gave a 250ms flash, so works well. But the other nodes didn't. The 'backred' node should set the background color of the lcd display to red using I2C, but unfortunately nothing happend. The 'johnny5' node contains the following code:
var lcd = new five.LCD({ controller: "JHD1313M1", board: board }); lcd.useChar("heart"); lcd.cursor(0, 0).print("I :heart: Johnny-Five");
Also, nothing happend on the display.
I decided to postpone my Node-RED experiments and switch back to Node.js and give Johnny-Five a try.
For this I needed to stop Node-RED temporary using the pm2 command (it will start again after a reboot!!),
root@edison_arduino:~# pm2 stop node-red
[PM2] Applying action stopProcessId on app [node-red](ids: 0)
[PM2] [node-red](0) ✓
┌──────────┬────┬──────┬─────┬─────────┬─────────┬────────┬─────┬────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
├──────────┼────┼──────┼─────┼─────────┼─────────┼────────┼─────┼────────┼──────────┤
│ node-red │ 0 │ fork │ 0 │ stopped │ 0 │ 0 │ 0% │ 0 B │ disabled │
└──────────┴────┴──────┴─────┴─────────┴─────────┴────────┴─────┴────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
root@edison_arduino:~#
Later I decided to completely delete it from the startup, it can easily be added again when needed:
root@edison_arduino:~# pm2 delete node-red
[PM2] Applying action deleteProcessId on app [node-red](ids: 0)
[PM2] [node-red](0) ✓
┌──────────┬────┬──────┬─────┬────────┬─────────┬────────┬─────┬─────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ watching │
└──────────┴────┴──────┴─────┴────────┴─────────┴────────┴─────┴─────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
root@edison_arduino:~# pm2 save
[PM2] Saving current process list...
[PM2] Successfully saved in /home/root/.pm2/dump.pm2
root@edison_arduino:~#
Johnny-Five
Johnny-Five brought me back on track. It also directly supports the the PCF8574ANPCF8574AN IO expander (JavaScript Robotics: Expander - PCF8574 with Johnny-Five ).
As I'm somewhat careful with the Nixie counter, wouldn't like to fry it before the end of the challenge. (also not afterwards ), I first tried the interface board loose on my desk. Here is a picture of the setup:
I glued a small test program together:
/* * Blank IoT Node.js starter app. * * Use this template to start an IoT Node.js app on any supported IoT board. * The target board must support Node.js. It is helpful if the board includes * support for I/O access via the MRAA and UPM libraries. * * <https://software.intel.com/en-us/xdk/docs/using-templates-nodejs-iot> */ /* spec jslint and jshint lines for desired JavaScript linting */ /* see http://www.jslint.com/help.html and http://jshint.com/docs */ /* jslint node:true */ /* jshint unused:true */ "use strict" ; var mraa = require("mraa") ; // add any UPM requires that you need // and the rest of your app goes here // see the samples for more detailed examples console.log(mraa) ; // prints mraa object to XDK IoT debug output panel var five = require("johnny-five"); var Edison = require("edison-io"); var board = new five.Board({ io: new Edison() }); board.on("ready", function() { // Plug the LED module into the // Grove Shield's D6 jack. // // Select an LED from the kit // (red, green, blue) and insert // it into the LED module, with // the long pin in + and short // pin in -. var led = new five.Led(2); // Plug the LCD module into any of the // Grove Shield's I2C jacks. var lcd = new five.LCD({ controller: "JHD1313M1" }); var virtual = new five.Board.Virtual( new five.Expander("PCF8574A") ); var leds = new five.Leds( Array.from({ length: 8 }, function(_, i) { return new five.Led({ pin: i, board: virtual }); }) ); leds.blink(500); lcd.bgColor(100,50,0).cursor(0, 0).print("Nixie Display"); lcd.cursor(1, 0).print("Johnny Five"); // This will blink the LED over // 500ms periods. led.blink(500); this.repl.inject({ leds: leds }); });
The program puts all 8 expander outputs in an array called leds, which altogether blink in an interval of 500 ms.
A scope connected to one of the PCF8574ANPCF8574AN outputs shows the signal:
Conclusion; worked like a charm!
Controlling the nixie tubes
As all looks well, it is time for the next step. So the interface board is inserted in the counter, the I2C signals (SDA, SCL) as wel as the ground are connected to the Grove interface board. This way the EdisonEdison and interface are powered from the Edison Arduino boardEdison Arduino board, the PCF8574ANPCF8574AN IO expander is powered from the nixie counter.
The software is modified such that the individual outputs of the expander can be set.
Here is the function which is responsible for that:
function nixie_disp(number, l) { var n1 = number % 10; var n2 = (number - n1) / 10; var bcd_number = 16 * n2 + n1; for (var i = 0; i < 8; i++) { var bit = (bcd_number & (1 << i)) != 0; //console.log(i,number,bcd_number,bit); if (bit) { l[i].on(); } else { l[i].off(); } } }
First the number is converted to BCD, then in a loop each individual bit is set on or off.
Subsequently a function is added to display the currents time number of seconds:
function showTime() { setInterval(function () { var date = new Date(); var sec = date.getSeconds(); var min = date.getMinutes(); nixie_disp(sec, leds); }, 1000); } showTime();
As you can see this works like a charm:
This concludes the blog of this week. I'm very happy that despite the struggling earlier this week I finally was able to easily control the nixie tubes. Regarding the hardware my plan is to switch to the other Edison with mini breakout boardmini breakout board. This board will be mounted inside the display case. Also two more interface boards still needs to be build.
Regarding the software I'm not completely sure which road to take. Maybe I will stick to Node.js and Johnny-Five. In any case the plan is still to implement weather info as well as blog post counters.
Stay tuned!
Top Comments