Friday, July 25, 2014

Raspberry Pi Servo Motor Controller using Node JS

This post is basically to support the below video, I have posted in Youtube regarding one of my fun projects that I'm working on my Raspberry Pi.
Project - Raspberry Pi Servo Motor Controller using Node JS
Project is to build a small Node JS application that runs a web socket server in my Raspberry Pi, which then enable my iPhone to connect to the web server using an ordinary browser like Safari through Web Socket Protocol to send its  Gyroscope data back to Raspberry Pi. Then web server will use this data to send PWM (Pulse Width Modulation) signals to it's selected GPIO pins connected to a servo motor.
By doing this I'll be able to control the servo motor using my iPhone over a LAN.

I know there are many ways you can achieve the same results, But I wanted use these selected technologies, so I can learn them better (and have FUN of doing it). I haven't used any Servo Controller Shields in this project either. Enjoy the video below.


Here is the code :
Server : app.js

1:  var express = require('express');  
2:  var app = express();  
3:  var server = require('http').createServer(app);  
4:  var fs = require('fs');  
5:  var WebSocketServer = require('websocket').server;  
6:  var piblaster = require("pi-blaster.js");  
7:    
8:    
9:  var clients = [ ];  
10:    
11:  //Getting request from browser  
12:  //and send response back  
13:  app.get ('/', function(req, res){    
14:    
15:     fs.readFile('ws.html', 'utf8', function(err, text){  
16:        res.send(text);  
17:      });  
18:  });  
19:    
20:  //Listening to Port 1337 for incoming messages  
21:  server.listen(1337, function (){  
22:    console.log((new Date()) + " Server is listening on port 1337... ");  
23:  });  
24:    
25:  websock = new WebSocketServer({  
26:    httpServer: server  
27:  });  
28:    
29:  //WebSocket Server  
30:    
31:  websock.on('request', function(request) {  
32:      
33:    console.log((new Date()) + ' Connection from origin ' + request.origin + '.');  
34:    
35:    var connection = request.accept(null, request.origin);  
36:      
37:    console.log((new Date()) + ' Connection accepted.');  
38:    
39:    //Incoming Data handling  
40:    connection.on('message', function(message) {  
41:    
42:      console.log('Data: ' + message.utf8Data);  
43:      
44:      var data = message.utf8Data;  
45:      data = data.slice(1,3);  
46:    
47:      // If incoming data is > 2 send a signal to pin 17  
48:      // Set GPIO pin 17 to a PWM of 24%  
49:      // Truns the Servo to it's right  
50:      if (Number(data)>2){      
51:        piblaster.setPwm(17, 0.24);  
52:      }  
53:    
54:      // If incoming data is > 2 send a signal to pin 17  
55:      // Set GPIO pin 17 to a PWM of 6%  
56:      // Truns the Servo to it's left  
57:      if (Number(data)<(-2)){      
58:        piblaster.setPwm(17, 0.06);  
59:      }  
60:    
61:      // If incoming data is > 2 send a signal to pin 17  
62:      // Set GPIO pin 17 to a PWM of 15%  
63:      // Truns the Servo to it's center position  
64:      if (Number(data)==0){      
65:        piblaster.setPwm(17, 0.15);  
66:      }  
67:    
68:    });  
69:      
70:    connection.on('close', function (connection){  
71:      //close connection  
72:      piblaster.setPwm(17, 0);  
73:    });  
74:    
75:    function closePin(){  
76:      piblaster.setPwm(17, 0);  
77:    }  
78:    
79:  });  


Client Page : ws.html


 <!doctype html>  
 <html>  
 <head>  
       <meta charset="utf-8">  
      <title>WebSockets - Simple chat</title>  
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>  
 </head>  
 <body>  
      <div id="content"></div>  
      <div>  
           <span id="status">Connecting...</span>  
      </div>  
   
 <script type="text/javascript">  
      $(function () {  
           // Position Variables  
           var x           = 0;  
           var y           = 0;  
           var z           = 0;  
   
           // Speed - Velocity  
           var vx           = 0;  
           var vy           = 0;  
           var vz           = 0;  
   
           // Acceleration  
           var ax           = 0;  
           var ay           = 0;  
           var az           = 0;  
           var ai           = 0;  
           var arAlpha = 0;  
           var arBeta      = 0;  
           var arGamma = 0;  
   
           var delay      = 200;  
           var vMultiplier = 0.01;                 
           var alpha      = 0;  
             
           var alpha      = 0;  
           var beta      = 0;  
           var gamma      = 0;  
             
           var content     = $('#content');  
           var status      = $('#status');  
   
        // if user is running mozilla then use it's built-in WebSocket  
        window.WebSocket = window.WebSocket || window.MozWebSocket;  
             
            if (!window.WebSocket) {  
                content.html($('<p>', { text: 'Sorry, but your browser doesn\'t '  
                                                        + 'support WebSockets.'} ));  
                input.hide();  
                $('span').hide();  
                return;  
           }  
             
             
        var connection = new WebSocket('ws://'+document.domain+':1337');  
   
        connection.onopen = function () {  
   
                status.text('You are connected to ThanboPi Server.' +  
                                    'Move your device and Have Fun!!');  
        };  
   
        connection.onerror = function (error) {  
           content.html($('<p>', { text: 'Sorry, but there\'s some problem with your '  
                                                   + 'connection or the server is down.' } ));  
        };  
   
   
        if (window.DeviceMotionEvent!=undefined) {  
   
                window.ondevicemotion = function(event) {  
                     ax = Math.round((event.accelerationIncludingGravity.x * 1));  
                     ay = Math.round(Math.abs(event.accelerationIncludingGravity.y * 1));  
                     az = Math.round(Math.abs(event.accelerationIncludingGravity.z * 1));            
                     ai = Math.round(event.interval * 100) / 100;  
                     rR = event.rotationRate;  
                     if (rR != null) {  
                          arAlpha = Math.round(rR.alpha);  
                          arBeta      = Math.round(rR.beta);  
                          arGamma = Math.round(rR.gamma);  
                     }            
                }  
                                                
                window.ondeviceorientation = function(event) {  
                     alpha = Math.round(event.alpha);  
                     beta = Math.round(event.beta);  
                     gamma = Math.round(event.gamma);  
                }       
             
                setInterval(function() {  
                     connection.send('x' + ax);  
                }, delay);                 
           }  
             
      });  
 </script>  
 </body>  
 </html>       
   


Schematic for this project is fairly simple on, but I'll post is anyway,



Components : RPI, Breadboard, a 1K resistor and a Basic Servo Motor

PS: If you need to know more details with regards to libraries, frameworks and hardware I'm using in this project, please ask your questions in the comment section. I would happily assist you.

10 comments:

Unknown said...

When you said its creates a socket, are you using socket.io?

Thanura Siribaddana said...

Not really,I'm not using socket.io for this project. I'm using WebSocket-Node plugin, which you can find here https://github.com/Worlize/WebSocket-Node

Unknown said...

ok, also could you post some sort of schematics of how you hooked everything up on the bread board, because it looks like you have some other components!:)

Looking forward to the integration into the rc buggie!

Thanura Siribaddana said...

I have updated the post with a schematic as requested.

Lady Cat said...

Could You tell me it works on phone with android?

Lady Cat said...

I tested this files on my raspi with raspbian and i have only Connecting... message. I copied only app.js and ws.html and try run.. Could You help me with this problem? Any tips?

Thanura Siribaddana said...

As far as you can capture gyroscope data on a android phone using javascripts. This should work. But I haven't tested it on an android phone.

Thanura Siribaddana said...

Do you have all dependencies installed? If you look at the first 6 line of app.js you can see what dependencies need to be installed. Let me know if you need more details on that

Alessandro said...

Hi Thanura, I couldn't find the code for ws.html. Would you please share it?
Thanks

Thanura Siribaddana said...

I have reposted the code for ws.html, please check