라즈베리파이와 아두이노를 이용하여 웹에서 스테핑모터 제어하기
이 페이지는 앞의 내용에 연결되는 페이지이므로 반드시 처음 페이지부터 참조해야 자연스럽게 이해가 됩니다.
사용된 스테핑 모터와 제어용 보드에 대한 상세한 설명도 앞페이지에서 확인해 주세요
테스트 환경
라즈베리파이 B+, Node.js, 라즈베리파이에 아두이노 개발환경(Arduino IDE)을 설치함
아두이노 UNO
스테핑모터(), 스테핑모터 제어보드
아두이노의 USB 케이블을 라즈베리파이의 USB 포트에 연결하고 node-serialport 라이브러리를 이용하여 시리얼 통신
라즈베리파이에서 실행되는 웹서버 프로그램 및 html 파일
/home/pi/www/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('step_motor_control.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' }); var msg = fields.speed+" "+fields.revolution; serialSend(msg, res); console.log("Form Received:"+msg); res.write('Received from Webbrowser:'+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"); }); }); }
/home/pi/www/step_motor_control.html
<!doctype html> <html> <head> <meta charset='utf-8'> <title> Stepping Motor Control </title> <style type="text/css"> #svrMsg { border:1px solid gray;} input[type=range] { width:400px; } </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 = {}; param.speed = $('input[name=speed]').val(); param.revolution = $('input[name=revolution]').val(); $.ajax( { url:'web_node_serial.js', type:'post', data:param, dataType:'text', success:function(res) { $('div#svrMsg').text(res); }, error:function(xhr, status, err){ $('div#svrMsg').text(err); } }); } </script> </head> <body> <p> Stepping Motor Control <p> Speed (+0.04 ~ +0.15) : <input type="range" name="speed" min="0.04" max="0.15" step="0.01" value="0.04" oninput="$('#spdOut').val(this.value);"> <output id="spdOut"><p> Revolutions & Direction (-5 ~ +5) : <input type="range" name="revolution" min="-5" max="5" step="0.01" value="0.01" oninput="$('#amtOut').val(this.value);"> <output id="amtOut"><p> <label for="svrMsg">Server Msg</label> <div id='svrMsg'></div> <button type="button" onclick='ajaxRequest();'> Apply </button> </body> </html>
아두이노에서 실행될 스텝모터 제어용 코드
라즈베리파이에 설치된 Arduino IDE에서 작성하여 아두이노에 업로드함
스테핑 모터의 회전방향 제어 : myStepper.setStep( 스텝수 ) -> 스텝수가 양수이면 정회전, 음수이면 역회전함
스테핑 모터의 회전수(량)은 위의 스텝수의 크기에 따라 결정됨
스테핑 모터의 회전속도 제어 : myStepper.setSpeed( n * 64 ) -> n 값이 0.04~0.15이면 적절함
#include <StepperAK.h> //use modified stepper library with 1000/0100/0010/0001 magnet firing sequence. Put library in your library folder. #define gearratio 64 //1:64 gear ratio const int stepsPerRevolution = 2048; //the Arduino Kit motor is geared down. By experiment I determined that 2048 steps turn the shaft one round. // instantiate a 4-wire stepper on pins 8 through 11: Stepper myStepper(stepsPerRevolution, 8,9,10,11); void setup() { Serial.begin(9600); } float speed = 0.0F; int amount = 0; int step = 0; void loop() { if(Serial.available()) { String msg = Serial.readString(); int idx = msg.indexOf(" "); if(idx < 0) return; String spd = msg.substring(0, idx); if(spd=="" || spd==NULL) spd = "0.15"; String amt = msg.substring(idx+1); if(amt=="" || amt==NULL) amt = "1.0"; char spdbuf[32]; spd.toCharArray(spdbuf, sizeof(spdbuf)); speed = atof(spdbuf); char amtbuf[32]; amt.toCharArray(amtbuf, sizeof(amtbuf)); float _amount = atof(amtbuf); amount = _amount * 2048.0F; myStepper.setSpeed( speed * 64 ); if( amount > 0) step = 1; else if( amount < 0 ) step = -1; else step = 0; char pChrBuffer[50]; String res = "Speed:"; res += dtostrf(speed, 5, 2, pChrBuffer ); res += " Steps:"; res += String(amount); Serial.println(res); } if(amount!=0) { if(amount>0) { if(--amount == 0) step = 0; }else if(amount<0){ if(++amount ==0) step = 0; } } myStepper.step(step); }