5 분 소요

Hits

Arduino IDE 에서 시리얼 통신으로 LED 온오프

const int pinLed = 13;

void setup() {
  pinMode(pinLed, OUTPUT);
  digitalWrite(pinLed, LOW);
  Serial.begin(9600);
}

void loop() {
  if(Serial.available() > 0) {
    unsigned char ch = Serial.read();
    if     (ch == '1') digitalWrite(pinLed, HIGH);
    else if(ch == '0') digitalWrite(pinLed, LOW );
    else;
  }
}

파이썬 라이브러리 설치

pip install pyserial

파이썬 코드로 아두이노와 시리얼 통신 확인 (확인용 코드)

import serial
import time

sp = serial.Serial('/dev/ttyACM0', 9600, timeout=1)

while True:
    data = '1'
    sp.write(data.encode())
    #sp.write(str.encode('1'))
    time.sleep(1)

    sp.write(str.encode('0'))
    time.sleep(1)

robot_ws/src에서 패키지 만들기

ros2 pkg create arduino --build-type ament_python --dependencies rclpy

cd arduino/arduino 가서 pub_led_msg.py 만들기

getchar.py 파일은 딴 데서 복붙해오기

import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from .getchar import Getchar


class PubLedMsg(Node):

    def __init__(self):
        super().__init__('pub_led_msg')
        
def main(args=None):
    rclpy.init(args=args)

    node = PubLedMsg()
    msg = String()
    kb = Getchar()

    pub = node.create_publisher(String, '/led_msg', 10)
    
    try:
        while rclpy.ok():
            key = kb.getch()

            if key == '1':
                print("on")
                msg.data = "on"
            elif key == '0':
                print("off")
                msg.data = "off"
            else:
                pass

            pub.publish(msg)

    except KeyboardInterrupt:
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()

cd .. 해서 setup.py에 ‘pub_led_msg = arduino.pub_led_msg:main’,

entry_points={
    'console_scripts': [
        'pub_led_msg = arduino.pub_led_msg:main',
    ],
},

당연히 빌드, 소스 하고

ros2 topic list

/*
/led_msg
/parameter_events
/rosout
*/
ros2 topic echo /led_msg

/*
ros2 run arduino pub_led_msg 를 한 터미널에서 1 또는 0 누를 때마다 
echo 한 터미널에서 아래와 같이 나옴

data: 'on'
---
data: 'off'
---
/*

cd arduino/arduino 가서 ctrl_led.py 만들기

import rclpy, serial
from rclpy.node import Node
from std_msgs.msg import String

sp = serial.Serial('/dev/ttyACM0', 9600, timeout=1)

class ControlLed(Node):

   def __init__(self):
        super().__init__('ctrl_led')      
        self.create_subscription(String, '/led_msg', self.get_led_msg, 10)
        self.tx_dat = '' # 전송할 데이터

   def get_led_msg(self, msg):
        if msg.data == "on" :
            self.tx_dat = '1'
        elif msg.data == "off":
            self.tx_dat = "0"
        else:
            pass            
        
        # sp.write(str.encode(self.tx_dat))
        sp.write(self.tx_dat.encode())


def main(args=None):

    rclpy.init(args=args)
    node = ControlLed()

    rclpy.spin(node)

    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
   main()

cd .. 해서 setup.py에 ‘ctrl_led = arduino.ctrl_led:main’,

entry_points={
    'console_scripts': [
        'pub_led_msg = arduino.pub_led_msg:main',
        'ctrl_led = arduino.ctrl_led:main',
    ],
},

당연히 빌드, 소스 하고

ros2 run arduino pub_led_msg
ros2 run arduino ctrl_led




Web Control

Node.js Install

curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install nodejs -y
node -v
npm -v
New major version of npm available! 10.8.2 -> 11.0.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.0.0
npm notice To update run: npm install -g npm@11.0.0

Express.js Install

sudo npm install -g express
sudo npm install -g express-generator

express 로 led_uno 폴더명 생성

express led_uno
cd led_uno
npm install

npmjs 에서 serialport 검색

npm i serialport

app.js

const express  = require('express');
const app      = express();
const path = require('path');
 
const SerialPort = require('serialport').SerialPort;

const sp = new SerialPort( {
  path:'/dev/ttyACM0',
  baudRate: 9600
});

const port = 3000;

app.get('/led_on',function(req,res)
{
	sp.write('1\n\r', function(err){
		if (err) {
            return console.log('Error on write: ', err.message);
        }
        console.log('send: led on');
		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.end('LED ON\n');
	});
});

app.get('/led_off',function(req,res)
{
	sp.write('0\n\r', function(err){
		if (err) {
            return console.log('Error on write: ', err.message);
        }
        console.log('send: led off');
		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.end('LED OFF\n');
	}); 
});

app.use(express.static(__dirname + '/public'));

app.listen(port, function() {
    console.log('listening on *:' + port);

});

app.js 실행

node app.js

public 폴더 안에 index.html 만들어서 꾸미면 됨

<a href="/led_on">Turn On</a>
<a href="/led_off">Turn Off</a>

Annyang api
음성인식 annyang API 사용할 수도 있다.

ResponsiveVoice API
말해주는 것도 활용 가능

cd public 에 index.html

<!DOCTYPE html>
<html lang=ko>
    <head>
        <title>Control LED on Arduino</title>
        <link rel="stylesheet" href="./stylesheets/style.css">
    </head>
    
    <body> 
        <table border="0">
        <tr>
            <td colspan="4"><h2> Control LED on Arduino </h2></td>
        </tr>
        <tr>
            <td rowspan="4" width="40"> &nbsp; </td>
            <td rowspan="4" width="60"><img src="./images/offRed.gif" id="ld"></td>
            <td rowspan="4" width="25"></td>
            <td> &nbsp; </td>
        </tr>
        <tr>
            <td>
            <a href="/led_on" target="response"><div onClick="led_on()">Turn On </div></a>
            </td>
        </tr>
        <tr>
            <td>
            <a href="/led_off" target="response"><div onClick="led_off()">Turn Off</div></a>
            </td>
        </tr>
        <tr>
            <td> &nbsp; </td>
        </tr>
        </table>
        
        <table border="0">
        <tr>
            <td rowspan="2">Status Message: <br /> &nbsp;<br /> &nbsp;</td>
            <td>
            <iframe src="about:blank" width="129" height="35" frameborder="0"
            marginwidth="0" marginheight="0" scrolling="no" name="response"></iframe>
            <p></p>
            </td>
        </tr>
        <tr>
            <td> &nbsp; </td>
        </tr>
        </table>
        
        <script src="javascripts/jquery-1.12.4.min.js"></script>
        <script src="javascripts/annyang.min.js"></script>
        <script>
        
        $(document).ready(function()
        {
            if (annyang)
            {
            var commands = {
                '불 켜':function(){
                response.location.href=("http://localhost:3000/led_on");
                led_on();
                },
                
                '불 꺼':function(){
                response.location.href=("http://localhost:3000/led_off");
                led_off();
                }
            };
            annyang.addCommands(commands);
            annyang.removeCallback();
            annyang.setLanguage('ko');
            annyang.start({ autoRestart: true, continuous: false });
            }
        });
        
        function led_on(){
            document.getElementById("ld").src = "./images/onRed.gif";
        }
        
        function led_off(){
            document.getElementById("ld").src = "./images/offRed.gif";
        }
        </script>
    </body>
</html>

아두이노에 가변저항 달고 구현

Arduino IDE

const unsigned int ledPin = 13;
const unsigned int potPin = A0;

String  inputString    = "";
boolean stringComplete = false;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  inputString.reserve(10);
}

void loop() {
  unsigned int adcVal = analogRead(potPin);
  Serial.print("adc");  Serial.println(adcVal);
  
  if(stringComplete) 
  {
    if(inputString.substring(0,3) == "led")
    {
      if     (inputString.substring(3,4) == "1")
        digitalWrite(ledPin, HIGH);
        
      else if(inputString.substring(3,4) == "0")
        digitalWrite(ledPin, LOW );
    }
    Serial.println(inputString);
    inputString = "";
    stringComplete = false;
  }
  delay(250);
}

void serialEvent() {
  while (Serial.available() > 0) {
    char inChar = Serial.read();
    inputString = inputString + inChar;
    if(inChar == '\n') stringComplete = true;
  }
}

Node.js 구현

express pot

cd pot

npm i
npm i serialport
npm i socket.io

app.js

var express = require('express');
var app = express();

var http     = require('http').Server(app);
var io       = require('socket.io')(http);

var SerialPort = require('serialport').SerialPort;

var ReadlineParser = require('@serialport/parser-readline').ReadlineParser;


var sp = new SerialPort( 
{
	path: '/dev/ttyACM0',
	baudRate: 9600,
});

const parser = sp.pipe(new ReadlineParser({ delimiter: '\r\n' }));

sp.on('open', () => console.log('Port open'));
var ledStatus ="";
parser.on('data', function (data) {
    var rcv = data.toString();

    if (rcv.substring(0, 3) == 'led'){
        if(rcv.substring(3,4) == "1")	ledStatus = "on";
        else							ledStatus = "off";  
        console.log('led status: ' + ledStatus);
        io.emit('led', ledStatus);
    }

    if (rcv.substring(0, 3) == 'adc'){
        var adc = parseInt(rcv.substring(3));
        console.log('adc:',adc);
        io.emit('adc', adc);
    }
});

app.get('/led_on',function(req,res)
{
	sp.write('led1\n\r', function(err){
		if (err) {
            return console.log('Error on write: ', err.message);
        }
        console.log('send: led on');
		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.end('LED ON\n');
	});

});

app.get('/led_off',function(req,res)
{
	sp.write('led0\n\r', function(err){

		if (err) {
            return console.log('Error on write: ', err.message);
        }
        console.log('send: led off');
		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.end('LED OFF\n');

	}); 

});

app.use(express.static(__dirname + '/public'));

const port = 3000;
http.listen(port, function () {
    console.log('Server listening on http://localhost:' + port);
});

cd public 에서 index.html

가변저항값 계속 보여주면서, LED on, off 기능

<!DOCTYPE html>
<html lang=ko>

<head>
    <style>
		#canvas { border: 1px solid lightgrey; }
        body { padding: 25px;  font: 12px "Lucida Grande", Helvetica, Arial, sans-serif; }
        iframe { overflow: hidden; }
        #title { font-weight: bold;  font-size: 12.5px; }
        a { color: #00B7FF; }
    </style>
	<title>Communicate with Arduino</title>
</head>

<body>
	<table border="0">
        <tr><td colspan="2" id="title">Communicate with Arduino</td></tr>
        <tr>
            <td rowspan="4" width="70"> &nbsp; <img id="imgLed" src="images/off.gif"></td>
            <td>&nbsp;</td>
        </tr>
        <tr>
			<td><a id="ledOn" href="/led_on" target="iframe">Turn On LED</a></td>
        </tr>
        <tr>
			<td><a id="ledOff" href="/led_off" target="iframe">Turn Off LED</a></td>
        </tr>
        <tr><td>&nbsp;</td></tr>
		<tr><td>LED State &nbsp; : </td><td id="led"></td></tr>
        <tr><td colspan="2">&nbsp;</td></tr>
        <tr><td colspan="2"><canvas id="canvas" width="160" height="20"></canvas></td></tr>
        <tr><td>ADC Value : </td><td id="adc"></td></tr>
	</table>
    
    <iframe src="about:blank" width="0" height="0" frameborder="0" border="0" marginwidth="0" marginheight="0" name="iframe"></iframe>
    
    <script src="http://code.jquery.com/jquery-1.8.3.js"></script>
	<script src="/socket.io/socket.io.js"></script>
	
    <script>
	
	
	$(document).ready(function() 
	{
		$(function()
        {
            var val    = 0;
            var oldval = 0;
            
			var socket = io();
				
			socket.on('led', function( ledStatus ){
				$('#led').text(ledStatus);
				console.log(ledStatus);
				if(ledStatus=='on')
					$('#imgLed').attr('src', "images/on.gif");
				else
					$('#imgLed').attr('src', "images/off.gif");
			});
            
			socket.on('adc', function( adcValue ){
				$('#adc').text(adcValue);
				
				oldval = val;
				val = parseInt(adcValue)/6;
				
				var canvas = document.getElementById('canvas');
						
				if (canvas.getContext){
					var ctx = canvas.getContext('2d');
					
					if( val != oldval ) {
					    // 512 x 20
						ctx.fillStyle = 'rgb(0, 200, 0)';
						ctx.fillRect(0,   0,    val, 20);
						ctx.fillStyle = 'rgb(255, 255, 255)';
						ctx.fillRect(val, 0, 1024/6, 20);
					}
				}
			});
		});
	});
	</script>

</body>
</html>

태그:

카테고리:

업데이트:

Comments