In this tutorial, I propose to combine Nodejs/Johnny-Five with Blynk to remotely control the GPIO of the Arduino/Firmata from a smartphone or a tablet and to make measurements (temperature and atmospheric pressure of a BMP180 in I2C ). In the previous article, we saw that it was very easy to use an Arduino (we will choose the model according to the number of I / O needed) to replace the original GPIO of Orange Pi. Thus freeing itself of the (current) lack of libraries allowing to exploit the GPIO. This project will work identically on any Pi Raspberry. The interest is less, as Johnny-Five is able to exploit the GPIO of all models of Raspberry Pi.
Project Architecture
The diagram below shows the architecture of the system we are going to set up:
- We will install the Firmata firmware on an Arduino Nano v3
- The Arduino / Firmata will be connected using a USB cable to an Orange Pi Lite (WiFi version, 512MB Ram, Armbian server).
- The script written in Javascript is interpreted (executed) by Node.js.
- This script uses the Blynk library to communicate with the local Blynk server (or the official server, it’s all the same).
- It publishes the measurements on the virtual pins V0 (temperature) and V1 (atmospheric pressure).
- It receives the state change of the GPIO allowing to turn on or off the Led
- This script uses the Johnny-Five library to drive the Arduino / Firmata GPIO
- The Led object will control the LED on the indicated pin
- The Multi object will retrieve measurements from the BMP180 on the I2C bus
- This script uses the Blynk library to communicate with the local Blynk server (or the official server, it’s all the same).
On video, here is what it will give
Installing Node.js on Armbian or Raspbian
Node.js is a runtime engine that allows Javascript scripts to run on a computer or mini-PC (Raspberry Pi, Orange Pi …). It is a multiplatform engine, meaning that code written on an environment can work identically (provided that the hardware resources also exist) on another environment. Node.js is available for Windows, MacOS, Linux (x86 and ARM).
First, make sure that Node.js is not already installed on your distribution
# node -v && npm -v v5.12.0 3.8.6
If you get an error message, install Node.js 4.x (sufficient) as well as Python and Build
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash - sudo apt-get install -y build-essential python-dev nodejs
Why Johnny-Five (J5) ?
Johnny-Five is a very popular open source project for the programming of connected objects or robotics in Javascript (official page). The name was inspired by the character of the film Short Circuit of which here is a small excerpt for the pleasure of re-discovering
Johnny-Five adds a layer of abstraction to your projects. We use objects (Led, Servo, Multi …) that we configure (pin, sensor name, home position …) and functions (led.blink (), servo.to (position) …).
In a few lines of code, you can control a servo motor. You do not even have to worry about the serial port on which the Arduino is plugged in, Johnny-Five takes care of everything! It’s just magical. This greatly simplifies coding. You can focus on your project rather than spend time looking for mistakes.
Matériel nécessaire
Orange Pi Lite (WiFi) or One (Ethernet) | |
5V/3A micro-USB power supply | |
Arduino Nano v3 5V/16MHz | |
BMP180 (barometer, temperature) | |
Led | |
Resistor 220Ω | |
Jumper Dupont | |
Breadboard |
Circuit
How to install Firmata firmware on an Arduino
The Firmata firmware provides access to all Arduino features via the serial port (using a USB cable). Connect the board to the computer and open the Arduino IDE. In the examples menu you will find a submenu named Firmata. Select the firmware that fits your need. The most common is to use the standard firmware. There is also a Plus version for communicating with peripheral devices via serial link UART, USART or SoftwareSerial.
Simply upload the firmware to the board. It’s ready !
If you have specific needs, you can go through the Firmata Builder site (configuration page, GitHub project) which allows you to choose the features and speed of the serial port.
Project Blynk
Launch Blynk on your smartphone or tablet. If you have a local server, connect to it by changing the source as shown in the screenshot below.
Create a new project and add 2 gauges. Choose the Virtual Pin V0 for temperature and V1 for atmospheric pressure.
Then place a button. Choose Pin V2. There are 2 operating modes for the Blynk button:
- Push: the ON state is maintained while the button is held. When the button is released, it returns to OFF.
- Switch: this is a normal switch. It turns ON when touched. Press again to turn off.
Choose the Switch mode.
Add a second button (V3) to test the Johnny-Five Pulse mode. You received an email with the token of the project when it was created. If you have lost the Token, return to the project configuration page (hex shaped button) and press E-Mail.
Installing the required Node.js plugins: Blynk, Johnny-Five
For this project, we will need to install the Blynk (for Nodejs) and Johnny-Five packages. Run this command to install them. The sudo command is preferred on Unix systems. The -g option allows you to install the packages glabalement, allowing them to be used in all scripts. The dependencies required for the packages will be automatically installed at the same time (magic npm).
npm install -g blynk-library johnny-five
Javascript code of the project (Node.js)
Your environment must be ready before proceeding. Connect to the Orange Pi (or Raspberry Pi) in SSH (or live). Create a new directory (nodebot) and place inside
cd ../.. mkdir nodebot && cd nodebot;
Create a new javascript script
nano j5BMP180.js
At the beginning of the script, we will call the different libraries necessary:
- Blynk: blynk-library
- Johnny-Five
- Events: Allows you to send and receive events.
var Blynk = require('blynk-library'); var five = require("johnny-five"); var EventEmitter = require('events').EventEmitter;
Then we will create several objects:
- board: it is the basic object that allows to use the Johnny-Five API, for example to control the servos, turn on the LEDs …
- event: This object is used to send and receive Javascripts events
- blynk: allows you to use the Blynk API
- connector: object containing the HTTP connection to the local Blynk server
- Vx: objects to exchange data with the Blynk server
var board = new five.Board(); // Objet permettant l'appel à l'API J5 - Object to call J5 API var AUTH = 'b065eb0a6e36434da42367b3fa7c3340'; // Remplacer par votre Token Blynk - Replace by your Blynk Token var event = new EventEmitter(); // Evenements javascript - Javascript Events var DEBUG = true; //false; // Setup Blynk var blynk = new Blynk.Blynk(AUTH, options = { // Connecteur au serveur Blynk local - Local Blynk server connector connector : new Blynk.TcpClient( options = { addr:"xxx.xxx.xxx.xxx", port:8442 } ) }); var V0 = new blynk.VirtualPin(0); // Pin virtuel temperature - Virtual Pin for temperature (BMP180) var V1 = new blynk.VirtualPin(1); // Pression atmosphérique - Atmospheric pressure (BMP180) var V2 = new blynk.VirtualPin(2); // Bouton ON/OFF pour la Led - ON/OFF button for the led var V3 = new blynk.VirtualPin(3); // Start/Stop Pulse Led var temp; // Contiendra la dernière mesure de température - Will store last Temperature value var pa;
It is very easy to monitor the connection status of the Blynk server at any time and “plug in” a function that is triggered when an event is issued by the object. For example, one can monitor whether one is connected (connect) to the server, or on the contrary that one is disconnected. It is possible, for example, to carry out a treatment in the event of disconnection. Here, we will simply display a message when connected to the server, or if the script is disconnected.
blynk.on('connect', function() { console.log("Blynk ready."); }); blynk.on('disconnect', function() { console.log("DISCONNECT"); });
You must wait until communication with the Arduino board is established before you can use the Johnny-Five API. To do this, we will plug into the ready event like this. The ready event does not return any information.
board.on("ready", function() { // code console.log("J5 Board is Ready"); })
To manage the LED, you need to create a led object. All the options of the Led PLC can be found here. At a minimum, it must be indicated to which pin the LED is connected.
var led = new five.Led(11);
The BMP180 is classified in the Multi category, sensors returning several measurements. The API is detailed on this page. At least, the controller should be used (here BMP180). Johnny-Five supports the following controllers. Use the property in parenthesis to retrieve the measure.
Sensor | Altimeter | Barometer | Hygrometer | Thermometer |
BMP180 | X | X | ||
BMP280 | X | X | ||
BME280 | X | X | X | |
HTU21D | X | X | ||
HIH6130 | X | X | ||
MPL115A2 | X | X | ||
MPL3115A2 | X | X | X | |
SI7020 | X | X | ||
SI7021 | X | X | ||
MS5611 | X | X | X | |
TH02 | X | X |
DHT11 and DHT22 only via an Arduino that plays the role of I2C gateway, which is not very easy to use.
var multi = new five.Multi({ controller: "BMP180" });
We can now retrieve the measurements with each change (“change“). We will copy the value into an intermediate variable.
multi.on("change", function() { temp = this.thermometer.celsius; // copie la valeur de la température - Make a copy of the temperature value pa = this.barometer.pressure * 10 // idem pour la pression atmosphérique - Same thing for atm. pressure });
How to turn on and off an LED with Johnny-Five?
To turn the LED on and off, we will connect a function to the event object (created at the beginning of the program) that will be executed when event V2 is issued. It will suffice to test the state of a parameter to turn on or off the LED. We will see a little later how to issue an event. Here we will use the on() and off() properties. Johnny-Five offers other properties to manage leds:
- toggle: reverses the state
- strobe(ms, callback): flashes the led at a certain frequency (duration of lighting in milliseconds). It is possible to stop flashing with the function
- led.stop(). A callback function can be called whenever the LED is off.
- blink(ms, callback): same as strobe
- brightness(0-255): changes the brightness. The LED must be connected to a PWM compatible output
- fade(brightness, ms, callback): Changes the brightness of the current level to the indicated level in a time specified in ms. A callback function can be called at the end of the variation. You can stop the function with led.stop ().
- fade(animation options): brightness variation animated. See the API for more details
- fadeIn(ms, callback)
- fadeOut(ms, callback)
- pulse(ms, callback)
- pulse(animation options)
The properties are available for single LEDs, RGB LEDs, LED arrays and LEDs.
event.on('V2', function(param){ if ( param == 1 || param == true ) { if ( DEBUG ) { console.log("Power ON Led on (V2 Pin)"); } led.on(); } else { if ( DEBUG ) { console.log("Power OFF Led (V2 Pin)"); } led.off(); } });
How to send regular measurements on the Blynk server?
To publish the measurements at regular intervals, we will use the javascript setInterval function to execute code or call a function at regular intervals. It is of the following form
setInterval(function() { // code ou fonction - code or function }, duration),
For example, the measurements will be sent every 2 seconds (2000 milliseconds). Blynk integrates a data verification system but it does not cost a small test to do nothing if the variable does not contain anything. In javascript, an empty variable is of type undefined. We publish to a virtual variable using the write function (as in the Arduino library).
setInterval(function() { if ( temp != undefined ) { if ( DEBUG ) { console.log('Temperature:', temp + ' C'); } V0.write(temp); } if ( pa != undefined ) { if ( DEBUG ) { console.log('Humidity: ', pa + ' hPa'); } V1.write(pa); } }, 2000);
How do I receive the order to turn on and off the led sent from the Blynk app?
It only remains to issue an event when the ON / OFF button is pressed from the Blynk app. A “write” event is retrieved on the V2 object. Then just issue our own event on the event object like this
event.emit("EVENT", param);
Parameters can be passed when the event is transmitted. Here, we just copy the param variable which contains the state of the desired led (1 or 0). Which give
V2.on('write', function(param){ if ( DEBUG ) { console.log("V2 ", param); } event.emit('V2',param); });
Why not directly call Johnny-Five objects directly?
One could actually think that it is possible to turn on or off the led at each change of state. Like this for example.
V2.on('write', function(param){ if ( DEBUG ) { console.log("V2 ", param); } if ( param == 1 || param == true ) { led.on(); } else { led.off(); } });
Only problem, the led object is created when the board is ready, so when the script is launched, it does not exist yet when Node.js created the “event” V2.on. You will have a nice javascript error that will crash the script as soon as you press the ON / OFF button!
Full code of javascript script
Paste the following code into the previously opened file without forgetting to change the IP address of your local Blynk server and the token of the project.
var board = new five.Board(); // Objet permettant l'appel à l'API J5 - Object to call J5 API var AUTH = 'b065eb0a6e36434da42367b3fa7c3340'; // Remplacer par votre Token Blynk - Replace by your Blynk Token var event = new EventEmitter(); // Evenements javascript - Javascript Events var DEBUG = true; //false; // Setup Blynk var blynk = new Blynk.Blynk(AUTH, options = { // Connecteur au serveur Blynk local - Local Blynk server connector connector : new Blynk.TcpClient( options = { addr:"xxx.xxx.xxx.xxx", port:8442 } ) }); var V0 = new blynk.VirtualPin(0); // Pin virtuel temperature - Virtual Pin for temperature (BMP180) var V1 = new blynk.VirtualPin(1); // Pression atmosphérique - Atmospheric pressure (BMP180) var V2 = new blynk.VirtualPin(2); // Bouton ON/OFF pour la Led - ON/OFF button for the led var V3 = new blynk.VirtualPin(3); var temp; // Contiendra la dernière mesure de température - Will store last Temperature value var pa; // idem pour la PA - The same for Atm. Pressure blynk.on('connect', function() { console.log("Blynk ready."); }); blynk.on('disconnect', function() { console.log("DISCONNECT"); }); board.on("ready", function() { console.log("Board J5 Ready "); var led = new five.Led(11); // PWM var multi = new five.Multi({ controller: "BMP180", freq: 2000 }); multi.on("change", function() { temp = this.thermometer.celsius; // copie la valeur de la température - Make a copy of the temperature value (Celsius) pa = this.barometer.pressure * 10 // idem pour la pression atmosphérique - Same thing for atm. pressure (hPa) }); event.on('V2', function(param){ if ( param == 1 || param == true ) { if ( DEBUG ) { console.log("blink led V2"); } led.on(); } else { if ( DEBUG ) { console.log("Stop Blink Led V2"); } led.off(); } }); event.on('V3', function(param){ if ( param == 1 || param == true ) { if ( DEBUG ) { console.log("Pulse led"); } led.pulse(500); } else { if ( DEBUG ) { console.log("Stop Pulse Led"); } led.stop(); led.off(); } }); }); setInterval(function() { if ( temp != undefined ) { if ( DEBUG ) { console.log('Temperature:', temp + ' C'); } V0.write(temp); } if ( pa != undefined ) { if ( DEBUG ) { console.log('Humidity: ', pa + ' hPa'); } V1.write(pa); } }, 2000); V2.on('write', function(param){ if ( DEBUG ) { console.log("V2 ", param); } event.emit('V2',param); }); V3.on('write', function(param){ if ( DEBUG ) { console.log("V3 ", param); } event.emit('V3',param); });
Testing in operation
Run the script with the node j5BMP180.js command, if you have enabled debug, temperature and atmospheric pressure will start scrolling
root@orangepilite:~/nodebot# node j5BMP180.js Connecting to TCP: 192.168.1.24 8442 Connected 1489765605100 Device(s) /dev/ttyUSB0 1489765605167 Connected /dev/ttyUSB0 Authorized Blynk ready. 1489765606738 Repl Initialized >> Temperature: 21.7 C Humidity: 974.42 hPa
Everything works perfectly. The script was successfully authenticated on the local Blynk server (IP 192.168.1.24, port 8442). Johnny-Five found the Arduino/Firmata on the USB port /dev/ttyUSB0 and it is connected. Temperature and atmospheric pressure measurements are correct and are sent regularly to the local Blynk server.
You can launch the Blynk application on your smartphone or tablet. You should have a screen similar to this one
You can now turn on and off the LED connected to the GPIO 11 from the mobile application and retrieve temperature and atmospheric pressure measurements from the BMP180. But the best is still a short video to sum up all that.
If you are interested in this topic, you can also follow this series of articles on driving a Pan/Tilt articulated system with an ESP8266 with Blynk, Cayenne or Node-RED + MQTT.
- Integrate Arduino / ESP8266 + Blynk IoT to iOS with Homebridge and HomeKit
- Recycle a remote-controlled car (RC car) with an ESP8266, Shield Motor Wemos d1 mini and Blynk
- Connecting an ESP8266 to Blynk on WiFi with Johnny-Five (Firmata WiFi)
- IoT development based on Orange Pi, Arduino (Firmata), Nodejs, Blynk and Johnny-Five
- Blynk + Node.js + Johnny-Five: drive a Pan-Tilt PTZ SG90 kit on Orange Pi with an Arduino / Firmata
- Blynk + ESP8266: drive a Pan-Tilt PTZ SG90 in WiFi with a smartphone or tablet
Great tutorial!
I like Blynk, but to have more control over the interface I was thinking about making a web server (not using Blynk).
Is there an easy way to do this?
Could I use nodejs on the Orange Pi to host a web page with an interface (buttons & a graph etc) integrated with Johnny-Five? Would it be best to use Sockets.io or something else?
Cheers!
Hello Leaden. You’re right, blynk is especially interesting if you do not want to get started in the development of an application iOS or Android.
You can easily develop with nodejs on Orangepi. The advantage of johnny-five is to bypass the lack of support for the GPIO.
To answer your question about the best solution, I think it depends mainly on your skills and the time you have. All technologies are good. Some require more work. I find that Johnny-five combined with Nodejs is very good because you eliminate all encoding on the Arduino / ESP8266. Before launching, make sure that your sensors / actuators are supported by Johnny-five.
Do not hesitate to share with us your accomplishments, I am sure that it will be an inspiration for many beginners.
Thanks for your reply!
I have done a little front end development, but nothing with nodejs. I will follow this tutorial and stick with Blynk for now to get my project running, then look at a simple node web app later, after I learn a little about that.
Cheers!
Great. Do not hesitate to ask me if you need advice. See you soon