본문 바로가기

Raspberry Pi/DC Motor, Web

IoT, DC Motor Control on the Web

라즈베리파이, 아두이노를 이용한 원격 DC 모터 제어의 예


5V DC 모터를 제어하여 모터의 전원을 ON/OFF 하고 모터의 회전방향을 정회전, 역회전(REV)으로 변경할 수 있는 시스템을 만들어 보기로 한다. 이용자는 웹 페이지에서 버튼을 눌러 모터를 제어할 수 있으므로 웹브라우저가 있는 휴대전화기나 PC에서도 모터를 제어할 수 있도록 할 것이다.


준비물

라즈베리파이 B+ ( Node.js )  ** 라즈베리파이에 Node.js 를 설치하는 절차는 여기 링크를 눌러 참조하세요 **

라즈베리파이에 아두이노 개발환경 설치

아두이노 UNO

DC 모터( 3V~6V DC, HES-288서보형 DC모터 ) ** 아래 설명 참조 **

모터 제어 보드( RB-DBA6280 )                     ** 아래 설명 참조 **



아두이노의 5V 전원을 RB-DBA6280과 DC 모터에 연결할 수 있으나 모터를 동작시키려면 전류가 부족할 수 있고 아두이노에 과전류가 흐를 위험이 있으므로 별도의 5V 외부전원을 사용할 필요가 있다. 아주 작은 모터이므로 5V 2A 정도의 주변에 흔한 직류전원 어댑터를 사용하면 된다. 모든 GND 단자는 반드시 전기적으로 모두 연결된 상태이어야 한다


서보형 DC 모터(HES-288)

HES-288 서보형 DC모터 (제품번호 : EPX4UKAG)

가격 4,545 원

서보모터가 아니고 일반적인 서보모터와 비슷한 외형을 가진 감속기어 내장형 DC모터임

http://eleparts.co.kr/EPX4UKAG

- DC 감속기어모터 
- 케이스에 내장된 기어 DC 모터 
- 끝단 기어 : 플라스틱 
- 로봇 제작 , 도어락등에 사용 
- 전압범위 : 3 ~ 6V 
- 속도 : 50rpm 
- 토크 : 2.5Kg/cm
- 크기 : 41 x 20 x 35

- 무게 : 54g



DC 모터 제어보드 ( RB-DBA6280 )

http://eleparts.co.kr/EPX33W3K

[RB-DBA6208]DC모터 제어모듈(완제품)

가격 7,000 원

정격전압 4.5~15v

출력전류 100mA

BA6208 를 2개 사용해서 2개의 DC 모터의 정/역 제어가 가능합니다. 자세한 특징은 모터 드라이브 IC인 BA6208를 참고하세요.

BA6208 핀 연결법

1 NC

2 BIN      LM0 ( 아두이노의 3번 핀을 연결 )

3 AIN      LM1 ( 아두이노의 4번 핀을 연결)

4 NC1

5 GND

6 VCC

7 BOUT

8 AOUT

9 NC2



모터 정/역회전 제어법

BIN : 제어신호 입력

AIN : 제어신호 입력


작동전원(4.5V~15V) : VCC, GND

BIN에 0, AIN에 1 신호를 입력하여 모터가 회전하는 방향을 정방향이라고 한다면 BIN, AIN에 그 반대의 신호를 입력하면 역방향 회전이 된다


BA6280 IC의 BIN은 DBA6280 모듈의 LM0에 연결되어 있고, AIN은 LM1에 연결되어 있으므로 결국 아두이노를 이용하여 RB-DBA6280 모듈을 제어하려면 다음과 같이 하면된다

정회전

 - 아두이노 3번 핀( HIGH ) - LMO 연결

 - 아두이노 4번 핀( LOW ) - LM1 연결

역회전 

 - 아두이노 3번 핀( LOW ) - LMO 연결

 - 아두이노 4번 핀( HIGH ) - LM1 연결



라즈베리파에서 실행될 웹서버 프로그램 (Node.js 기반)

웹브라우저에서 전달되는 요청을 받고 아두이노 보드와 시리얼통신으로 아두이노에게 웹브라우저 파라미터(ON/OFF/REV)를 전달한다. 파라미터를 받은 아두이노는 라즈베리파이에게 받은 문자열을 시리얼통신으로 다시 되돌려 보낸다. 아두이노에게 받은 문자열을 웹브라우저에게 응답으로 전달한다. 라즈베리파이와 아두이노 사이의 시리얼통신 방법은 여기를 눌러 참조하세요

/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('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'
		});

		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");
		});
	});
}



/home/pi/www/motor_control.html

이용자가 버튼을 누르면 라즈베리파이에서 실행되는 web_node_serial.js 으로 파라미터(ON/OFF/REV)를 전달한다

<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title> DC Motor ON/OFF/REV Control </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(cmd) {
	var param = {};
	param.msg = cmd;

	$.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>
 DC Motor ON/OFF & REVERSE Control
<p>
<label for="svrMsg">Server Msg</label>
<div id='svrMsg'></div>
<button id='sw_on' type="button" onclick='ajaxRequest("ON");'>ON</button>
<button id='sw_off' type="button" onclick='ajaxRequest("OFF");'>OFF</button>
<button id='sw_rev' type="button" onclick='ajaxRequest("REV");'>REVERSE</button>
</body>
</html>



아두이노에서 실행될 코드

라즈베리파이로부터 전달된 파라미터(ON/OFF/REV)를 시리얼통신으로 수신하여 모터 제어 모듈인 RB-DBA6280의 LM0, LM1 단자에 HIGH, LOW 신호를 출력하여 연결된 모터의 시동, 정지, 역회전 등을 명령한다

/* RB-DBA6280 Module Control --> HES-288 DC Motor
  PIN 3 -> LM0, PIN 4 -> LM1
*/
String msg = "";
void setup()
{
 pinMode(3, OUTPUT);
 pinMode(4, OUTPUT);

 Serial.begin(9600); 
 //msg = "OFF";
}

void loop()
{
  if(msg=="ON") {
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
  }else if(msg=="OFF") {
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
  }else if(msg=="REV") {
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);    
  }
  
  if(Serial.available())
  {
    msg = Serial.readString();
    Serial.println(msg);
  }
}



테스트 방법

라즈베리파이에서 web_node_serial.js 를 다음과 같이 실행한다

$ cd /home/pi/www

$ sudo node web_node_serial.js

웹브라우저에서 http://라즈베리파이의 IP:서버측 프로그램의 포트/web_node_serial.js 으로 접속한다

웹페이지에서 ON, OFF, REV 등의 버튼을 눌러 모터의 시동, 정지, 역회전 등의 작동상태를 확인한다