Hardware components | ||||||
| × | 1 | ||||
![]() |
| × | 1 | |||
| × | 1 |
We try taking advantage of the most popular gadgets of the moment, to create a project based on Linino.
The goal of the project is to control a robotic arm on which we installed the GoPro camera and run some commands: start / stop recording video, taking photos, localize the camera (the cam starts to beep).
You will need:
Warning: embedding parts within the project story has been deprecated. To edit, remove or add more parts, go to the "Hardware" tab. To remove this list from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Hardware" tab). | ||||||
|
||||||
|
||||||
|
NB Linino with Node.js and the Ideino development environment on-board
(For installing Node.Js and Ideino on the Yun, please refer to this guide: http://wiki.linino.org/doku.php?id=wiki:nodejscript).
The master piece of this project is the mips-gopro library for node.js (https://www.npmjs.org/package/mips-gopro). We had recompiled the Jaakko Manninen’s gopro lib (https://github.com/kschzt/gopro) for MIPS architecture and extend its functionality: now we had almost all of the gopro functionality.
Let’s start with the javascript code!
Now that we have everything you need, we can go to the Ideino worspace page via web browser (http://linino.local:2424) (after the root login) and create new project called “GoPro”, in which we will write our code to manage GoPro and robotic arm:
Before start coding, we need to install the mips-gopro module. To do so, open the package.json file inside the drone project you have just created, and add the dependence of the mips-gopro module. Your file should look like this:
Code
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
{
"name": "GoPro",
"version": "0.0.1",
"description": "GoPro example project",
"author": {
"name": "Ideino Team"
},
"dependencies": {
"mips-gopro": "*"
}
}
you can also write other information like the name and description of the project. Save the package.json file, press the right mouse button on it and click Install. Ideino will run the npm command and will install the mips-gopro module inside the project directory.
Now create a new file and name it gopro_demo.js :
Code
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
var linino = require('ideino-linino-lib'),
board = new linino.Board({layout:"linino_one"}),
html = new linino.Htmlboard(),
fs = require('fs'),
http = require('http'),
url = require('url'),
path = require('path'),
express = require('express'),
Camera = require('mips-gopro').Camera,
cam = new Camera('10.5.5.9', your_password);
var loc_btn = "locationButton",
power_btn = "powerButton",
photo_btn = "photoButton",
video_btn = "videoButton";
// PanTilt
var servoH = { pin: board.pin.servo.S8, value : 180 },
servoV = { pin: board.pin.servo.S9, value : 180 },
htmlH = { ctrl: 'sliderH' , param : 'value' },
htmlV = { ctrl: 'sliderV' , param : 'value' };
var app,x=90,y=90,angolo=5;
board.connect(function(){
//SIMPLE HTTP SERVER
var file, page;
app = express();
var server = http.createServer(app);
app.get('/',function(req, res) {
page = path.join(__dirname,'html','gopro_demo.html');
file = fs.readFileSync(page);
res.writeHead(200, {'Content-Type': 'text/HTML'});
res.end(file);
});
app.get('/up', function (req, res) {
if(x<180-angolo+1) {
x=x+angolo;
board.servoWrite(servoV.pin,x);
}
});
app.get('/down', function (req, res) {
if(x>angolo) {
x=x-angolo;
board.servoWrite(servoV.pin, x);
}
});
app.get('/left', function (req, res) {
if(y<180-angolo+1) {
y=y+angolo;
board.servoWrite(servoH.pin, y);
}
});
app.get('/right', function (req, res) {
if(y>angolo) {
y=y-angolo;
board.servoWrite(servoH.pin, y);
}
});
app.listen(1337);
//PanTilt
board.pinMode(servoH.pin, board.MODES.SERVO);
board.pinMode(servoV.pin, board.MODES.SERVO);
html.read(htmlH.ctrl,htmlH.param,function(data){
board.servoWrite(servoH.pin,data.value);
});
html.read(htmlV.ctrl,htmlV.param,function(data){
board.servoWrite(servoV.pin,data.value);
});
// GoPro
//Video
html.read(video_btn,'value',function(data){
switch(data.value)
{
case 0:
cam.switch2Camera().then(function(){cam.videoWVGA60(); cam.startCapture()});
break;
case 1:
cam.switch2Camera().then(function(){cam.videoWVGA120(); cam.startCapture()});
break;
case 2:
cam.switch2Camera().then(function(){cam.video720p30(); cam.startCapture()});
break;
case 3:
cam.switch2Camera().then(function(){cam.video720p60(); cam.startCapture()});
break;
case 4:
cam.switch2Camera().then(function(){cam.video960p30(); cam.startCapture()});
break;
case 5:
cam.switch2Camera().then(function(){cam.video960p60(); cam.startCapture()});
break;
case 6:
cam.switch2Camera().then(function(){cam.video1080p30(); cam.startCapture()});
break;
case "X":
cam.stopCapture();
break;
}
});
//Photo
html.read(photo_btn,'value',function(data){
switch(data.value)
{
case 0:
cam.switch2Photo().then(function(){cam.photo11w(); cam.startCapture()});
break;
case 1:
cam.switch2Photo().then(function(){cam.photo8m(); cam.startCapture()});
break;
case 2:
cam.switch2Photo().then(function(){cam.photo5w(); cam.startCapture()});
break;
case 3:
cam.switch2Photo().then(function(){cam.photo5m(); cam.startCapture()});
break;
}
});
//Localization
html.read(loc_btn,'value',function(data){
if(data.value == 'Y')
cam.localisationON();
else
cam.localisationOFF();
});
});
Create the html page (gopro_demo.html) in the html folder, to interact with the hardware:
Code
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
<html>
<head>
<style>
.text{
width: 150px;
height: 65px;
border: 1px solid gray;
border-radius: 5;
font-family: courier;
font-size: 1.1em;
text-align: center;
vertical-align: center;
}
</style>
<script src="http://linino.local:2424/js/ideino-linino-lib/socket.io.js"></script>
<script src="http://linino.local:2424/js/ideino-linino-lib/ideino-linino-lib-client.js"></script>
<script>
window.onload = connect('linino.local');
//PanTilt
function move(ctrl){
writeData(ctrl.id, 'value', ctrl.value);
}
//GoPro
function video(button)
{
if(button.value == "Record a Video")
{
var index = document.getElementById("video_resolutions").selectedIndex;
writeData('videoButton','value', index);
button.value = "Stop Recording";
}
else
{
writeData('videoButton','value', "X");
button.value = "Record a Video";
}
}
function photo()
{
var index = document.getElementById("photo_resolutions").selectedIndex;
writeData('photoButton','value', index);
}
function localize(btn)
{
if(btn.value == "Localize"){
btn.value = 'Stop';
writeData('locationButton','value','Y');
}else{
btn.value = 'Localize';
writeData('locationButton','value','X');
}
}
</script>
</head>
<body>
<!-- PanTilt -->
<p>
<span class="text">
Horizontal
<input type="range" id="sliderH" name="sliderH" min="10" max="180" onmouseup="move(this);">
</span>
</p>
<p>
<span class="text">
Vertical
<input type="range" id="sliderV" name="sliderV" min="50" max="180" onmouseup="move(this);">
</span>
</p>
<!-- GoPro -->
<input type="button" id="videoButton" onclick="video(this)" value="Record a Video"></input>
<select id="video_resolutions">
<option> WVGA - 60fps
<option> WVGA - 120fps
<option> 720p - 30fps
<option> 720p - 60fps
<option> 960p - 30fps
<option> 960p - 60fps
<option> 1080p - 30fps
</select>
<input type="button" id="photoButton" onclick="photo(this)" value="Take a Photo"></input>
<select id="photo_resolutions">
<option> 11 MP - Wide
<option> 8 MP - Medium
<option> 5 MP - Wide
<option> 5 MP - Medium
</select>
<input type="button" id="locationButton" onclick="localize(this)" value="Localize"></input>
</body>
</html>
Now that the code is ready to run, you need to put the application in autorun mode, this means that the application will run automatically at the next startup/reboot of Linino. Right mouse click on gopro_demo.js and click “Autorun”.
Now you just have to configure our board, making it connect to the GoPro WiFi Hotspot. To do that, please connect to the luci administration panel of your Arduino Yun via web browser. Wait a few minutes for the WiFi reconfiguration, the system will restart and your Node.Js file will autorun.
Now you are all set! Command your GoPro from Web!
{
"name": "GoPro",
"version": "0.0.1",
"description": "GoPro example project",
"author": {
"name": "Ideino Team"
},
"dependencies": {
"mips-gopro": "*"
}
}
var linino = require('ideino-linino-lib'),
board = new linino.Board({layout:"linino_one"}),
html = new linino.Htmlboard(),
fs = require('fs'),
http = require('http'),
url = require('url'),
path = require('path'),
express = require('express'),
Camera = require('mips-gopro').Camera,
cam = new Camera('10.5.5.9', your_password);
var loc_btn = "locationButton",
power_btn = "powerButton",
photo_btn = "photoButton",
video_btn = "videoButton";
// PanTilt
var servoH = { pin: board.pin.servo.S8, value : 180 },
servoV = { pin: board.pin.servo.S9, value : 180 },
htmlH = { ctrl: 'sliderH' , param : 'value' },
htmlV = { ctrl: 'sliderV' , param : 'value' };
var app,x=90,y=90,angolo=5;
board.connect(function(){
//SIMPLE HTTP SERVER
var file, page;
app = express();
var server = http.createServer(app);
app.get('/',function(req, res) {
page = path.join(__dirname,'html','gopro_demo.html');
file = fs.readFileSync(page);
res.writeHead(200, {'Content-Type': 'text/HTML'});
res.end(file);
});
app.get('/up', function (req, res) {
if(x<180-angolo+1) {
x=x+angolo;
board.servoWrite(servoV.pin,x);
}
});
app.get('/down', function (req, res) {
if(x>angolo) {
x=x-angolo;
board.servoWrite(servoV.pin, x);
}
});
app.get('/left', function (req, res) {
if(y<180-angolo+1) {
y=y+angolo;
board.servoWrite(servoH.pin, y);
}
});
app.get('/right', function (req, res) {
if(y>angolo) {
y=y-angolo;
board.servoWrite(servoH.pin, y);
}
});
app.listen(1337);
//PanTilt
board.pinMode(servoH.pin, board.MODES.SERVO);
board.pinMode(servoV.pin, board.MODES.SERVO);
html.read(htmlH.ctrl,htmlH.param,function(data){
board.servoWrite(servoH.pin,data.value);
});
html.read(htmlV.ctrl,htmlV.param,function(data){
board.servoWrite(servoV.pin,data.value);
});
// GoPro
//Video
html.read(video_btn,'value',function(data){
switch(data.value)
{
case 0:
cam.switch2Camera().then(function(){cam.videoWVGA60(); cam.startCapture()});
break;
case 1:
cam.switch2Camera().then(function(){cam.videoWVGA120(); cam.startCapture()});
break;
case 2:
cam.switch2Camera().then(function(){cam.video720p30(); cam.startCapture()});
break;
case 3:
cam.switch2Camera().then(function(){cam.video720p60(); cam.startCapture()});
break;
case 4:
cam.switch2Camera().then(function(){cam.video960p30(); cam.startCapture()});
break;
case 5:
cam.switch2Camera().then(function(){cam.video960p60(); cam.startCapture()});
break;
case 6:
cam.switch2Camera().then(function(){cam.video1080p30(); cam.startCapture()});
break;
case "X":
cam.stopCapture();
break;
}
});
//Photo
html.read(photo_btn,'value',function(data){
switch(data.value)
{
case 0:
cam.switch2Photo().then(function(){cam.photo11w(); cam.startCapture()});
break;
case 1:
cam.switch2Photo().then(function(){cam.photo8m(); cam.startCapture()});
break;
case 2:
cam.switch2Photo().then(function(){cam.photo5w(); cam.startCapture()});
break;
case 3:
cam.switch2Photo().then(function(){cam.photo5m(); cam.startCapture()});
break;
}
});
//Localization
html.read(loc_btn,'value',function(data){
if(data.value == 'Y')
cam.localisationON();
else
cam.localisationOFF();
});
});
<html>
<head>
<style>
.text{
width: 150px;
height: 65px;
border: 1px solid gray;
border-radius: 5;
font-family: courier;
font-size: 1.1em;
text-align: center;
vertical-align: center;
}
</style>
<script src="http://linino.local:2424/js/ideino-linino-lib/socket.io.js"></script>
<script src="http://linino.local:2424/js/ideino-linino-lib/ideino-linino-lib-client.js"></script>
<script>
window.onload = connect('linino.local');
//PanTilt
function move(ctrl){
writeData(ctrl.id, 'value', ctrl.value);
}
//GoPro
function video(button)
{
if(button.value == "Record a Video")
{
var index = document.getElementById("video_resolutions").selectedIndex;
writeData('videoButton','value', index);
button.value = "Stop Recording";
}
else
{
writeData('videoButton','value', "X");
button.value = "Record a Video";
}
}
function photo()
{
var index = document.getElementById("photo_resolutions").selectedIndex;
writeData('photoButton','value', index);
}
function localize(btn)
{
if(btn.value == "Localize"){
btn.value = 'Stop';
writeData('locationButton','value','Y');
}else{
btn.value = 'Localize';
writeData('locationButton','value','X');
}
}
</script>
</head>
<body>
<!-- PanTilt -->
<p>
<span class="text">
Horizontal
<input type="range" id="sliderH" name="sliderH" min="10" max="180" onmouseup="move(this);">
</span>
</p>
<p>
<span class="text">
Vertical
<input type="range" id="sliderV" name="sliderV" min="50" max="180" onmouseup="move(this);">
</span>
</p>
<!-- GoPro -->
<input type="button" id="videoButton" onclick="video(this)" value="Record a Video"></input>
<select id="video_resolutions">
<option> WVGA - 60fps
<option> WVGA - 120fps
<option> 720p - 30fps
<option> 720p - 60fps
<option> 960p - 30fps
<option> 960p - 60fps
<option> 1080p - 30fps
</select>
<input type="button" id="photoButton" onclick="photo(this)" value="Take a Photo"></input>
<select id="photo_resolutions">
<option> 11 MP - Wide
<option> 8 MP - Medium
<option> 5 MP - Wide
<option> 5 MP - Medium
</select>
<input type="button" id="locationButton" onclick="localize(this)" value="Localize"></input>
</body>
</html>
Comments
Please log in or sign up to comment.