uno-ethernet-button
본 예제는 가장 많이 사용되는 아두이노 UNO R3에 이더넷쉴드( Ethernet shield) 를 추가하여 네트웍 기능을 제공하고 버튼 1개와 LED 출력을 지원하는 예제입니다.
간단한 예제이지만 앱으로 아두이노를 제어할 뿐 아니라 아두이노로 유튜브 동영상 제어까지 가능함을 보여주는 재밌는 예제입니다
1. 라이브러리와 예제 설치
- 아두이노 라이브러리 매니저에서
remocon
을 검색하여 라이브러리를 설치합니다. - 라이브러리 설치시 Boho, Crypto를 함께 설치할 지 물을때 Yes 를 선택해주셔야합니다.
- 파일(File) > 예제(Examples) > Remocon 폴더에 예제파일이 있습니다.
- 본 문서는 uno-ethernet-button.ino 를 소개합니다.
- 이더넷쉴드 라이브러리는 아두이노 IDE에 기본 내장되어있습니다.
2. 예제 소개
동일한 공유기에 연결된 장치들(아두이노 또는 리모컨 앱)에게 실행 가능한 명령어 정보(최소화된 UI)를 알리고, 수신된 시그널에 따라 LED(또는 Relay)를 on, off, toggle 제어하는 예제입니다.
- 체험 서버를 이용할 경우, 이더넷쉴드 예제는 소스를 수정하지 않고 그대로 업로드 합니다.
- 예제 소스코드에 있는 서버 주소와 포트 번호로 테스트 서버에 접속가능합니다.
- 주의. 체험 서버 운영 상태는 변경 될 수 있습니다.
- 직접 IO시그널 서버를 운영 할 경우, 주소와 포트번호를 변경해주시면 됩니다.
3. 소스코드 구현 내용
- IO시그널 서버에 연결합니다.
- 자신의 CID(통신ID)를 #notify (홈)채널로 알립니다.
- #search 채널을 구독합니다.
- #search 채널에서 시그널을 수신하면, #notify 채널로 CID를 보냅니다.
- 자신의 UI정보(명령어목록)를 CID발행 시그널로 알립니다.
- 제어 시그널을 수신하면 IO를 on, off, toggle 합니다.
- IO 상태가 변경되면 state 정보를 CID발행으로 시그널을 전송합니다.
- 버튼을 누르면 외부로 시그널을 전송합니다.
- 참고로 여러유형의 시그널 예제명령문이 적혀있고 1개를 제외하고 주석처리된 상태입니다.
- 필요한 시그널로 수정하시면 됩니다.
4. 리모컨 앱 사용법
- 동일한 리모트 시그널에 접속된 장치는 리모컨 앱을 통해 제어가 가능합니다. 웹앱은 설치할 필요가 없습니다.
- 제어할 장치와 동일한 공유기에 접속된 스마트폰, 노트북 등에서 웹브라우저를 열고 아래의 주소에 접속합니다.
- https://remocon.kr
- 리모컨 앱이 뜹니다.
- 홈채널을 통해 장치를 자동 검색 후 제어 가능한 장치 목록이 뜹니다.
- 장치의 on, off, toggle 버튼을 눌러 제어합니다.
5. 부품 준비
리모컨 앱으로 LED 원격제어 실습만 해 보실 경우 버튼은 생략하셔도 됩니다.
- 아두이노 UNO
- 아두이노 이더넷쉴드(W5100)
- 브레드보드, 점퍼선
- 푸시버튼
- LED
- 저항 약 330옴
6. 부품 연결하기
아래 예제는 D5핀에 LED가 장착된 예제입니다. 예제 소스코드는 D6핀도 D5와 동일하게 on,off 됩니다. D6핀에 릴레이를 추가로 연결하면 전등, 모터 같은 외부 장치의 on, off 제어가 가능합니다.
간단히 LED 1개와 전류 제한 용 저항, 그리고 버튼이 1개 연결되었습니다 저항 크기는 약 220~560옴 정도로 바꿔도 무방합니다.
7. 리모컨 앱과 연동 준비
- 가정 이나 사무실 공유기를 준비합니다.
- 위와 같이 아두이노를 설치 후 이더넷 쉴드를 공유기에 연결합니다.
- PC나 스마트폰이 아두이노와 동일한 공유기에 연결되어있는지 확인합니다.
8. 리모컨 앱으로 제어하기
- 웹브라우저로 리모컨앱을 https://remocon.kr 실행합니다.
- 아두이노가 서버에 연결되면, 서버를 통해 버튼과 LED제어를 위한 UI정보를 전달합니다.
- 리모컨 앱에 아두이노 장치 이름과 UI 정보 [on][off][toggle] 버튼이 보입니다.
- 버튼을 누르면 아두이노의 LED가 제어됩니다.
9. 아두이노 버튼으로 유튜브 동영상 제어하기
본 예제에서 버튼을 누르면 동일한 공유기에 연결된 #screen 채널에 “next”라는 시그널을 전송합니다.
이 시그널을 수신하는 장치가 있다면 해당 명령이 실행됩니다. 실제 작동을 테스트 하기 위해 직접 다른 아두이노 보드나 웹프로그램을 만들수 있지만, 일단은 이미 공개된 동영상 플레이어를 제어해보도록 합니다.
또 다른 컴퓨터나 스마트폰에서 https://bayo.tv 사이트를 열어서 재생버튼을 누릅니다.
웹 브라우저는 보안상의 이유로 사용자가 처음 한번은 직접 버튼을 눌러서 동영상을 재생해줘야 합니다.
이제 아두이노 버튼을 눌러봅니다. #screen 채널에 next 라는 시그널을 전송하고, 이를 수신한 동영상 플레이어는 다음곡 재생이 됩니다.
10. source code
/*
* IOSignal Remocon Example.
* Arduino Uno + Ethernet shield W5100 + Button
*
* Example of the Remote Control WebApp integration.
* Open and control https://remocon.kr with a web browser connected to the same router
*
* IoT리모컨 WebApp 연동 예제입니다.
* 동일한 공유기에 연결된 웹브라우저로 https://remocon.kr 을 열고 제어하세요
*
* Lee Dongeun <sixgen@gmail.com>
* https://github.com/remocons/remocon-arduino
*
* MIT License
*/
#include <SPI.h>
#include <Ethernet.h>
#include <string.h>
#include <IOSignal.h>
#include <Bounce2.h>
// If you have multiple devices, you'll need to change the MAC address.
byte mac[]{0, 0, 0, 0, 0, 0x07};
EthernetClient client;
IOSignal io;
const char *name = "UnoR3-EthBtn:HOME";
const char *ui = "on,off,toggle";
const int buttonPin = 2;
int lastButtonState = HIGH;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(5, OUTPUT); // LED
pinMode(6, OUTPUT); // Relay
digitalWrite(5, LOW);
digitalWrite(6, LOW);
Serial.begin(115200);
Serial.println(F("Init.."));
Ethernet.init(10);
Ethernet.begin(mac); // DHCP
Serial.print(F("IP:"));
Serial.println(Ethernet.localIP());
io.setRxBuffer( 80 );
io.begin( &client, "io.remocon.kr", 55488);
io.onReady( &onReady );
io.onMessage( &onMessage );
// io.auth( "id_key" );
}
void deviceOn(){
digitalWrite( 5, HIGH);
digitalWrite( 6, HIGH);
io.signal("@$state", "on" );
}
void deviceOff(){
digitalWrite(5, LOW);
digitalWrite(6, LOW);
io.signal("@$state", "off" );
}
void deviceToggle(){
int nextState = !digitalRead(5);
digitalWrite(5, nextState);
digitalWrite(6, nextState);
if(nextState){
io.signal("@$state", "on" );
}else{
io.signal("@$state", "off" );
}
}
int isPressed(){
int currentState = digitalRead(buttonPin);
if(lastButtonState == HIGH && currentState == LOW){
lastButtonState = LOW;
return 1;
}
else{
lastButtonState = currentState;
return 0;
}
}
void loop() {
io.loop();
if(isPressed()){
Serial.println(F("pressed"));
io.signal("#screen", "playToggle" );
}
}
void onReady()
{
Serial.print(F("onReady cid: "));
Serial.println( io.cid );
io.signal("@$state", "off" );
io.signal("@$ui", ui );
io.signal("@$name", name );
io.signal("#notify", io.cid );
io.subscribe("#search");
}
void onMessage( char *tag, uint8_t payloadType, uint8_t* payload, size_t payloadSize)
{
Serial.print(F(">> signal tag: ") );
Serial.print( tag );
Serial.print(F(" type: ") );
Serial.print( payloadType );
Serial.print(F(" size: " ));
Serial.println( payloadSize );
if( payloadType == IOSignal::PAYLOAD_TYPE::TEXT ){
Serial.print(F("string payload: ") );
Serial.println( (char *)payload );
}
if( strcmp(tag, "#search") == 0){
io.signal( "#notify", io.cid );
}
if( strcmp(tag, "@ui") == 0){
io.signal2( (const char*)payload, "@ui", io.cid , ui);
}
if( strcmp(tag, "@") == 0){
if( strcmp((const char*)payload, "on") == 0){
deviceOn();
}else if( strcmp((const char*)payload, "off") == 0){
deviceOff();
}else if( strcmp((const char*)payload, "toggle") == 0){
deviceToggle();
}
}
}