본문 바로가기
Coding/Raspberry pi - node.js

초음파 센서 제어와 웹 연동

by hyun-am 2019. 11. 15.

초음파 센서제어와 웹 연동 

 

1. 초음파 센서 구성 

 

 

왼쪽 부터 차례대로 

 

5V, Trig, Echo, Gnd 입니다.

 

2. 초음파 센서(거리측정) 코드 예시

 

부품 구성 

 

5V : 물리적 2번

GND : 물리적 6번

Trig : 29(물리적 40번)

ECHO : 28(물리적 38번)

 

소스 코드

 

const gpio = require('node-wiring-pi');
const TRIG = 29;
const ECHO = 28;

var startTime; // 초음파 송출 시간
var travelTime;	// 초음파수신까지 경과시간


const Triggering = () =>{
        
        gpio.digitalWrite(TRIG,gpio.LOW);
        gpio.delayMicroseconds(2);
        gpio.digitalWrite(TRIG,gpio.HIGH);
        gpio.delayMicroseconds(20);
        gpio.digitalWrite(TRIG,gpio.LOW);
        
        while(gpio.digitalRead(ECHO)==gpio.LOW);
        startTime = gpio.micros();
        while(gpio.digitalRead(ECHO)==gpio.HIGH);
        
        // 초음파 거리를 구할때 공식과 같은것 입니다. 
        travelTime = gpio.micros() - satrtTime;
        distance = travelTime / 58;
        if(distance < 400)
            console.log("Distance : %dcm\n", distance);
            
        setTimeout(Triggering,500);
    }
    
process.on('SIGINT',()=>{
    console.log("Program Exit...");
    process.exit();
});

gpio.wiringPiSetup();
gpio.pinMode(TRIG,gpio.OUTPUT);
gpio.pinMode(ECHO,gpio.INPUT);
setImmediate(Triggering);

 

3. 웹서버 프로그래밍 기술

 

웹 소켓을 이용한 웹제어

 

먼저 시작하기전에 $npm install socket.io를 통해 웹소켓을 설치합니다

이것으로 웹을 실시간으로 제어할 수 있고, 실시간 데이터 전송도 가능합니다.

 

웹을 제어하기 위한 js코드

 

먼저 TRIG와 ECHO는 앞에와 마찬가지로 wpi번호 29, 28을 설정하고 LED는 27번을 하겠습니다.

 

const http = require('http');
const gpio = require('node-wiring-pi');
const fs = require('socket.io');
const LED = 27;
const TRIG = 29, ECHO = 28;
var startTime, travelTime;	// 초음파 거리 계산용
var index=0, value = []; // 측정거리데이터 저장용
var timerid, timeout=800	// 타이머 제어용

const server = http.createServer((request, response)=>{
    fs.readFile('views/web_so.html','utf8',(error,data)=>{
        response.writeHead(200,{'Content-Type':'text/html'});
        response.end(data);
        });	//end of readFile
    }).listen(65001,()=>{		//end of createServer
        gpio.wiringPiSetup();
        gpio.pinMode(LED,gpio.OUTPUT);
        gpio.pinMode(TRIG,gpio.OUTPUT);
        gpio.pinMode(ECHO,gpio.INPUT);
        gpio.digitalWrite(LED,0);	// LED초기화 과정
        console.log("Server running at http://IP주소:65001");
    });		//end of listen
    
const io = socket.listen(server);
io.sockets.on('connection',function(socket){
    socket.on('startmsg',function(data){
        console.log('가동메시지 수신(측정주기:%d)!',data);
        timeout = data;
        watchon();	// 타이머가동(초음파가동)
    });	// end of socket.on
    
    socket.on('stopmsg',function(data){
        console.log('중지메시지 수신!');
        clearTimeout(timeid);
    });	// end of socket.on
});	// end of io.sockets.on

const watchon = () =>{
    gpio.digitalWrite(TRIG,gpio.LOW);
    gpio.delayMicroseconds(2);
    gpio.digitalWrite(TRIG,gpio.HIGH);
    gpio.delayMicroseconds(20);
    gpio.digitalWrite(TRIG,gpio.LOW);
    
    while(gpio.digitalRead(ECHO)==gpio.LOW);
    startTime = gpio.micros();
    while(gpio.digitalRead(ECHO)==gpio.HIGH);
    travelTime = gpio.micros()-staartTime;
    
    distance = travelTime / 58;
    if(distance < 400){
        if(index < 500){
            value[index++]=distance;
            console.log('근접거리:%d cm',value[index-1]);
            io.sockets.emit('watch',value[index-1]);
            }
            else index = 0;
            if((index % 2)==0)gpio.digitalWrite(LED,1);	// 가동중 LED 점멸
            else gpio.digitalWrite(LED,0);
        }
        timerid = setTimeout(watchon, timeout);
    }

 

웹 코드(web_so.html)

 

<!DOCTYPE html>
<html>
<head>
    <meta charset = 'utf-8'>
    <script src = "/socket.io/socket.io.js"></script>
    <script>
    window.onload = ()=>{
        var dataview = document.getElementById("dataview");
        var socket = io.connect();
        var html= '';
        
        socket.on('watch',function(data){
            html += '<b>' + data + '</b>' + '<br>';
            dataview.innerHTML = html;
        });
    // 문서 객체 이벤트 연결
    document.getElementById('start').onclick = function(){
        var text = document.getElementById('text').value;
        socket.emit('startmsg',text);
    };
    document.getElementById('stop').onclick = function(){
        var text = document.getElementById('text').value;
        socket.emit('stopmsg',text);
    };
};
</script>
</head>

<body bgcolor = "lightcyan">
    <h2>거리측정제어(초음파센서제어)</h2>
    <hr>
    <h3>측정주기 설정 및 가동 </h3>
    <hr>
    <input type = "text" id="text" value="800" />ms
    <input type = "button" id="start" vaule="초음파센서가동"/>
    <input type = "button" id="stop" value="초음파센서중지"/>
    <hr>
    <p id = "dataview">초음파센서가동시 이곳에 측정거리값이 출력됩니다. </p>
</body>
</html>

 

※ 만약 선형 그래프를 그리고 싶으면 아래와 같은 코드를 사용하면 됩니다. 

 

plotly.html (위에서 연결하는 코드만 바꾸면 됩니다)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <script src = "/socket.io/socket.io.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    <script>
    window.onload = function(){
        var dataview = document.getElementById("dataview");
        var socket = io.connect();
       

        socket.on('watch',function(sonicdata){  // 초음파데이터 실시간수신
            Plotly.extendTraces('chart',{y:[[sonicdata]]},[0]); //차트에 그리기
            widthcount++;   // 그래프데이터 카운트
            if(widthcount>100){ // 100이상부터 차트 동적이동
                Plotly.relayout('chart',{
                    xaxis:{
                        range:[widthcount-99,widthcount]    // x축 동적이동
                    }
                });
            }
        });
        document.getElementById('start').onclick = function(){
            var text = document.getElementById('text').value;
            socket.emit('startmsg',text);
        };
        document.getElementById('stop').onclick = function(){
            var text = document.getElementById('text').value;
            socket.emit('stopmsg',text);
        };
    };    
    </script>
    <style>
        *{
            color:#6382ff;
            font-weight: bold;

        }
    </style>

    <title>초음파 센서 제어</title>
</head>

<body style="background-color: black;">
    <div class="container">
    <h2>거리측정제어(초음파센서제어)</h2>
    <hr>
    <h3>측정주기 설정 및 가동</h3>
    <h5>측정주기 입력 범위: 500~1000(단위:ms) 입력 값으로 조정 가능</h5>
    <hr>
    <input type="text" id="text" value="800"/>ms
    <input type="button" id="start" class="btn btn-outline-primary" value="초음파센서가동"/>
    <input type="button" id="stop" class="btn btn-outline-danger" value="초음파센서중지"/>
    <br><br><br>
    <div id="chart" class="container bg-dark shadow mx-auto">
        <script>
        Plotly.plot('chart',[{
            y:[0],  // 출력값 지정
            type:'line',    // 선차트 지정
            line:{shape:'spline'}   // 곡선형태 지정
        }]);
        </script>
    </div>
    <hr>
    <!-- <p id="dataview">초음파센서가동시 이곳에 측정거리값이 출력됩니다.</p> -->
</div>
</body>
</html>

 

 

댓글