In the previous tutorial, we saw how to replace the GPIO of the Orange Pi with an Arduino (using the Firmata firmware) and then how to create a Javascript script to drive a Led from a smartphone with the Blynk and Johnny-Five library. In this tutorial we will implement a new method to drive a PTZ articulated system based on servo motors.
Reminder of previous episodes and presentation of the project
We have already seen several methods of driving a Pan-Tilt system based on SG90 servo motors:
In this new tutorial, we will use an Arduino/Firmata which will replace the GPIO of the Orange Pi, which is fishing because of its lack of successful libraries to manage the GPIO. For this we will develop a script in Javascript which will be executed by Node.js. We will use the Johnny-Five library (all articles on Johnny-Five) as well as the Blynk library for Node.js. The Blynk library will link the mobile application to the local (or official) Blynk server and the Node.js. The Johnny-Five library will be used to control the actuators of the Pan and Tilt axes. Here is a small diagram that summarizes the architecture of the project.
A short video preview
Matériel nécessaire
Suivez ce guide étape par étape pour le montage de votre kit Pan-Tilt PTZ.
Blynk server on Raspberry Pi or Orange Pi (optionnal)
How to install a blynk server on a Raspberry Pi 3 or Orange Pi (Armbian) |
|
Orange Pi Lite (WiFi version) or One (Ethernet) | |
5V/3A micro-usb power supply | |
Arduino Nano v3 5V/16MHz | |
Mini Kit FPV Pan Tilt 2x SG90 | |
Jumper Dupont |
Circuit
Install Firmata firmware on the 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 ! To customize the firmware, read this article.
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
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
Blynk project on mobile application
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.
Add 2 sliders. The first V0 will control the PAN servo. The second V1 will control the servo TILT. For both sliders, check Send values on release only if you want the servo to move only when the slider is released. Change the maximum output level to 180 (for 180 degrees).
You can also add 4 buttons
- V2 (Center): reposition the 2 axes in the center (90 °, 90 °)
- V3 (Stop): Stop all current movements
- V4 (Pan Sweep): horizontal scanning
- V5 (Tilt Sweep): sweeping Vertical
Here is the project obtained
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 j5PanTilt.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; // Active les messages de mise au point - Activate debug message // 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); // Pan servo var V1 = new blynk.VirtualPin(1); // Tilt servo var V2 = new blynk.VirtualPin(2); // Reset position
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"); })
How to drive a servo with Johnny-Five?
Johnny-Five offers two classes to drive the servo motors:
- servo: A servo motor is individually controlled. The complete documentation can be found here
- servos: two actuators can be operated simultaneously. The complete documentation can be found here. This API is recommended if you want to create perfectly synchronized movements of several servos. All the methods of the servo API are available!
The servo API offers many functions:
- to (deg ms, rate): moves the servo to the indicated position (deg). Ms is used to indicate the time to perform the movement and misses the number of steps. For example servo.to (90,500,10) will move the servo at the 90 ° angle in 500ms in 10 steps.
- min: moves the servo to the mini position. Default 0 °. It is possible to modify the possible range of movement of the servo at initialization. For example 30 ° to 150 °.
var servo = new five.Servo({ pin: 10, range: [ 30, 150 ] });
- max: idem but maximum. Default is 180 °.
- center: positions the servo in the center position. It is calculated at the center of the range. By default 0 – 180 °, the center will be at 90 °
- home: returns the servo to the position defined by the startAt parameter
var servo = new five.Servo({ pin: 10, startAt: 20 }); // Set horn to 90 degrees servo.to(90); // Return to startAt value of 20 degrees servo.home();
- sweep: alternate sweep between min and max
- sweep([low, high]): alternate sweep from low to high
- sweep(options): sweep with options. Range: [start position, end position], interval: half-displacement (ms) duration, step: step-by-step
- stop: stops the current movement
- cw(speed 0-1): continuous movement in the clockwise direction
- ccw(speed 0-1): continuous movement counterclockwise
Preparing the Pan and Tilt Servo Moves
We will take advantage of it to test some functions very quickly thanks to Johnny-Five. One could, for example, develop a small surveillance camera system that would regularly scan horizontally. We will add a function to stop all movements in progress and one last one to return the axes Pan and Tilt to their central position.
In the board.on(“ready”) function, the two servos
var pan = new five.Servo(PIN_PAN); var tilt = new five.Servo(PIN_TILT);
Then we will plug in treatments by listening to events. For example, the PAN event will cause the Pan servo to move to the position passed as a parameter
event.on('PAN', function(position){ if ( DEBUG ) { console.log("Move Pan servo to ", position); } pan.to(position); }); event.on('PAN_SWEEP', function(position){ if ( DEBUG ) { console.log("Move Pan servo to ", position); } pan.to(position); });
Now just after the board.on(“ready”) function, a message will be sent as soon as we receive an order from the Blynk application. In Javascript, simply call the event object (created at the beginning of the program) and use the emit method. The emit method takes two parameters. The first one is a string that allows you to name the event. The optional second is a parameter. It can be a string, a numeric value, a Boolean … or a JSON object. Here, the angle is sent as an integer. To do this, use the parseInt function to convert the string to integer.
V0.on('write', function(param){ if ( DEBUG ) { console.log("V0 (Pan) ", param); } event.emit('PAN',parseInt(param) ); });
Full Project Code
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 Blynk = require('blynk-library'); var five = require("johnny-five"); var EventEmitter = require('events').EventEmitter; 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; // Active les messages de mise au point - Activate debug message var DEBUG = true; //false; var PIN_PAN = 10; var PIN_TILT = 9; // Configure l'objet Blynk - Setup Blynk object var blynk = new Blynk.Blynk(AUTH, options = { connector : new Blynk.TcpClient( options = { addr:"192.168.1.24", port:8442 } ) }); var V0 = new blynk.VirtualPin(0); // Pan servo var V1 = new blynk.VirtualPin(1); // Tilt servo var V2 = new blynk.VirtualPin(2); // Retourne à la position centrale - Go to center position var V3 = new blynk.VirtualPin(3); // Stop tous les mouvements - Stop all movements var V4 = new blynk.VirtualPin(4); // Balayage horizontal - Pan sweep var V5 = new blynk.VirtualPin(5); // Balayage vertical - Tilt sweep 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); var pan = new five.Servo(PIN_PAN); var tilt = new five.Servo(PIN_TILT); function stopBlink(){ led.stop(); led.off(); }; event.on('PAN', function(position){ if ( DEBUG ) { console.log("> Move Pan servo to ", position); led.blink();} pan.to(position); stopBlink(); }); event.on('PAN_SWEEP', function(position){ if ( DEBUG ) { console.log("> Sweep Pan servo "); led.blink();} pan.sweep(); }); event.on('TILT', function(position){ if ( DEBUG ) { console.log("> Move Tilt servo to ", position); led.blink();} tilt.to(position); stopBlink(); }); event.on('TILT_SWEEP', function(){ if ( DEBUG ) { console.log("> Sweep Tilt servo "); led.blink();} tilt.sweep(); }); event.on('CENTER', function(position){ if ( DEBUG ) { console.log("> Go Home Pan/Tilt servos"); led.blink();} pan.center(); tilt.center(); stopBlink(); }); event.on('STOP', function(){ if ( DEBUG ) { console.log("> Stop All movements"); led.blink();} pan.stop(); tilt.stop(); stopBlink(); }); }); V0.on('write', function(param){ if ( DEBUG ) { console.log("V0 (Pan) ", param); } event.emit('PAN',parseInt(param) ); }); V1.on('write', function(param){ if ( DEBUG ) { console.log("V1 (Tilt) ", param); } event.emit('TILT',parseInt(param) ); }); V2.on('write', function(param){ if ( DEBUG ) { console.log("GO Home position "); } event.emit('CENTER'); }); V3.on('write', function(param){ if ( DEBUG ) { console.log("STOP all movements"); } event.emit('STOP'); }); V4.on('write', function(param){ if ( DEBUG ) { console.log("SWEEP Pan servo"); } event.emit('PAN_SWEEP'); }); V5.on('write', function(param){ if ( DEBUG ) { console.log("SWEEP Tilt servo"); } event.emit('TILT_SWEEP'); });
Save the file with CTRL + X then Y. Start the script with the command node j5PanTilt.js , if you have enabled debug, you will be able to follow the arrival of the commands from the Blynk server; The execution of the command is preceded by a ‘>’.
# node j5PanTilt.js Connecting to TCP: 192.168.1.24 8442 Connected 1490105773157 Device(s) /dev/ttyUSB0 1490105773264 Connected /dev/ttyUSB0 Authorized Blynk ready. 1490105774854 Repl Initialized >> Board J5 Ready V0 (Pan) [ '99' ] > Move Pan servo to 99 V0 (Pan) [ '31' ] > Move Pan servo to 31 SWEEP Pan servo > Sweep Pan servo
A short demonstration video to conclude this tutorial.
- 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
- Start programming with Node Js and Johnny-Five: IoT and robotics based on Arduino, Raspberry Pi, Orange Pi
- Orange Pi (Armbian): replace the GPIO by an Arduino/Firmata, Node-RED and Johnny-Five