라즈베리파이와 아두이노를 연결하여 웹에서 아두이노의 LED를 ON/OFF 하는 예
웹페이지에서 ON/OFF 버튼을 누르면 라즈베리파이에서 Node.js 로 작성한 프로그램이 요청을 받고 USB 케이블로 연결된 아두이노에게 전달하여 결과적으로 아누이노 보드의 LED를 켜고 끄는 기능을 작성해보려고 한다
테스트 환경
라즈베리파이 B+, Jessie, Node.js
Node.js의 라이브러리 : Serialport(시리얼통신 기능), Formidable(폼처리 기능)
Arduino UNO
라즈베리파이에 아두이노 개발환경과 Node.js를 설치하고 아두이노에 포함되어 있는 USB 케이블을 사용하여 라즈베리파이와 연결하면 Node.js 의 Serialport 라이브러리를 이용하여 라즈베리파이와 아두이노 사이에 시리얼통신이 가능하다. 이와 같은 환경설정은 여기 링크를 따라 참조하면 된다
웹브라우저에서 아래의 파일을 요청할 때, GET 방식일 경우 'power_on_off.html' 을 보여주고, POST 방식 요청일 경우에는 msg 파라미터의 값을 아두이노 측에 시리얼통신으로 전달하여 아두이노가 LED를 켜거나 끄도록 한다. Node.js 에서 폼 데이터를 처리하기 위해서 여기서는 Formidable 라이브러리를 사용하므로 사전에 설치해야 한다
/home/pi/www/web_node_serial.js ( http://라즈베리파이의 IP주소:포트번호/web_node_serial.js )
var http = require('http'); var fs = require('fs'); var formidable = require('formidable'); var util = require('util'); var server = http.createServer( function(req, res) { if(req.method.toLowerCase()=='get') { displayForm(res); }else if(req.method.toLowerCase()=='post'){ processAllFieldsOfTheForm(req, res); } } ); function displayForm(res) { console.log('GET'); fs.readFile('power_on_off.html', function(err, data){ res.writeHead(200, { 'Content-Type':'text/html', 'Content-Length':data.length }); res.write(data); }); } function processAllFieldsOfTheForm(req, res) { console.log('POST'); var form = new formidable.IncomingForm(); form.parse(req, function(err, fields, files) { res.writeHead(200, { 'Content-Type':'text/plain' }); serialSend(fields.msg, res); console.log("Form Received:"+fields.msg); res.write('Received from Webbrowser:'+fields.msg+'\n\n'); }); } server.listen(8088); console.log('Server running at port 8088'); function serialSend(web_data, res) { var SerialPort = require("serialport").SerialPort; serialPort = new SerialPort("/dev/ttyUSB0", { baudrate: 9600, dataBits:8, parity:'none', stopBits: 1, flowControl: false }); serialPort.on("open", function() { console.log("open"); serialPort.on("data", function(data) { res.write('Received from Arduino:'+data+'\n\n'); res.end(); console.log('Received from Arduino:' + data+'\n'); }); serialPort.write(web_data, function(err, results){ console.log('err: ' + err); console.log('results : '+ results); }); /* serialPort.close(function(err){ console.log('port closed', err); }); */ serialPort.on("error", function(err) { console.log('error : '+ err); }); serialPort.on("close", function(){ console.log("closed"); }); }); }
버튼을 누르면 AJAX 요청으로 'ON' 혹은 'OFF' 문자열이 서버측으로 전달되고 서버측에서 처리된 결과가 화면에 출력된다.
power_on_off.html
<!doctype html> <html> <head> <meta charset='utf-8'> <title> Power ON/OFF </title> <style type="text/css"> #svrMsg { border:1px solid gray;} </style> <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> <script> $(function(){ //alert('jquery ready!'); }); function ajaxRequest() { var param = {}; var cmd = $('button#switch').text(); param.msg = cmd; $.ajax( { url:'web_node_serial.js', type:'post', data:param, dataType:'text', success:function(res) { $('div#svrMsg').text(res); if(cmd=='ON') { $('button#switch').text('OFF'); }else{ $('button#switch').text('ON'); } }, error:function(xhr, status, err){ $('div#svrMsg').text(err); } }); } </script> </head> <body> <p> Power ON/OFF <p> <label for="svrMsg">Server Msg</label> <div id='svrMsg'></div> <button id='switch' type="button" onclick='ajaxRequest();'>ON</button> </body> </html>
아두이노 측의 코드
라즈베리파이 측에서 시리얼 통신으로 'ON' 문자열이 전달되면 13번 핀에 연결된 LED를 켜고 'OFF'가 전달되면 LED를 끈다
arduino_serial.ino
String msg = ""; void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); Serial.begin(9600); msg = "OFF"; } void loop() { if(msg=="ON") { digitalWrite(13, HIGH); }else{ digitalWrite(13, LOW); } if(Serial.available()) { msg = Serial.readString(); Serial.println(msg); } }