본문 바로가기

아두이노/IoT 아두이노 프로젝트!

아두이노 IoT 주차시스템을 만들어보자 !!

안녕하세요.


이번에 아두이노를 이용해서 IoT 주차시스템을 구성하였습니다.

Ethernet은 WIZnet사의 W5500 칩을 이용하여 구현하였습니다.

본래 Ethernet or Internet 통신을 하기 위해서는 Peer to peer 사이에 프로토콜을 정의해놓고 그 프로토콜대로 통신할 수 있도록 구성하였습니다. 그것이 지금의 OSI 7계층이고, 이 7계층에서 필요없는 것을 추려내서 제작한 것이 TCP/IP 4계층입니다.

그런데, 이 TCP/IP 4계층은 본래 소프트웨어로 전부 제작해야 했습니다.

언제... 이 프로토콜을 전부 코딩한단 말입니까...

그래서 WIZnet W5500을 사용하였습니다.

W5500을 사용하면 TCP/IP 프로토콜을 전부 해결해주고, 사용자는 Application만 제작하면 됩니다.

구성품은 아래와 같습니다.

Component List

1. Arduino Uno

2. WIZnet W5500 Ethernet shield

3. Ultra Sonic Sensor(HC-SR04)

4. Servo motor (SG-90)

5. infrared rays sensor (GP2Y0A41SK0F)

6. Bread board

7. Wire


그래서 위 구성품을 이용해서 주차시스템을 만들어 보려고 합니다.

제작 완료된 사진은 아래와 같습니다.


사용한 센서의 설명을 드리자면,

1. UltrasonicSensor(HC-SR04)
-초음파를 발생시키는 원리는 피에조효과(압전효과*)와 같습니다.
-사용된 초음파 센서는 약 40KHz 정도의주파수를 생성하고, 5~7m정도 까지의 거리를 측정할 수 있습니다.
-이러한 초음파 센서는 거리측정에 사용됩니다.
-초음파센서는 송신부와 수신부로나뉘어져 있으며송신된신호가 반사되어 수신부로받아서 이에 대한 시간차를 기반으로 거리를 산출합니다.
-
-동작은 triger 핀에10us 정도의high 신호를주면 초음파센서는 40kHz 펄스를 자동적으로 8번 발생시킵니다.
-펄스를 발생시킨 직후에 echo핀은high되고반사된 초음파가 감지 되었을 때 echo핀이LOW가됩니다.
-이러한 echo핀이 high되었다가 low가 되는데 걸리는 시간을 측정하여 그 시간을 초음파의 속도/2(왕복이니깐 /2)를 나누면 거리가 나옵니다.


2. UltrasonicSensor(HC-SR04)

-초음파의 속도는 약 340m/s
-초음파 센서의 송신부(triger)에서 일정한 시간의 간격을 둔 짧은초음파 펄스를 방사하고대상물에부딪혀 돌아온 펄스를 수신부(echo)에서 받아,이에 대한 시간차를 기반으로 거리를 산출합니다.
-1cm를이동하는데 걸리는 시간은 다음과 같이 구할 수 있습니다.
-따라서,t = 2* 0.01 / 340 = 58.824us초음파가1cm를이동하는데 걸리는 시간은 약 29us가걸립니다.
-거리(cm)= duration(왕복에걸린시간) / 29 / 2(왕복

다른 블로거의 초음파센서의 관한 설명을 참조바란다.

http://dokkodai.tistory.com/104


3. 적외선센서(GP2Y0A21YK0F)

-적외선 센서는 보통 거리측정인체감지로 많이 사용됩니다.
-적외선 센서는 일정 주파수의 빛을 발산하는 발광부,발산하는 빛이 반사되어 감지하는 수광부로이루어져 있습니다.
-적외선 센서는 이러한 반사된 빛을 감지하여 물체의 유,무또는 물체와의 거리를 알 수 있습니다.
-위 소자는 발광부와 수광부가 일체형으로 구성된 소자입니다.
-적외선은 외부 빛에 대한 노이즈를너무 많이 받기 때문에실내에서만사용해야한다는 단점이 있습니다.
-그렇기 때문에,외부에서 거리 측정용으로는 적합하지 않다.
-관련된 소자
-포토트랜지스터(적외선을 인식하면 전류를 흐르게 한다.)
-IR Sensor(리모콘)

-이런 적외선 센서는 아날로그 상태일 때 그래프를 보면거리가10cm 이하로떨어질 경우 오히려 전값이감소합니다.
-그리고 10cm부근에서 최대의 전압값을갖고 있다가 거리가 멀어질 수록 다시 전압이 감소합니다.
-이래서,10cm 이하의 거리측정을 할 때는 오히려 값이 증가하기 때문에 이 센서는 근거리 측정에 부적합.
-데이터 시트에는 10~80cm까지의 거리 측정이 가능하지만주변환경에따른 변수가 많이 때문에 실질적으로 신뢰가 가능한 거리는 10~ 40cm정도까지 입니다.

-아래 타이밍은 최대 38.3ms+9.6ms+5ms이후에 첫 번째 출력이 나온다는 의미입니다.



3.Servo Motor(SG90)

-서보모터는각도를 정밀하게 제어할 수 있는 장점을 이용하여 로보틱스 분야에서 관절부분에 많이 사용되고 있습니다.
-0-180or 360도까지 각도제어가 가능합니다.
-,정해진 명령에 따라 정확한 위치와 속도를 맞출 수 있는 모터를 서보모터라합니다.
-서보모터는PWM(Pulse Width Modulation)을 사용하여 펄스의 폭을 조절하여 제어하게 됩니다.
-이 때,각도를 제어함에 있어서 아래 그림의 Duty Cycle의길이를 조정함으로써 제어를 할 수 있게 됩니다.
-사용한 SG90는 한 주기가 20ms로 정해져 있으며,이 한 주기 내에 Duty Cycle몇이냐에따라 움직이는 각도가 달라집니다.
-아두이노에서서보모터를제어하는 방법으로는 2가지가있습니다.
-직접 각도를 입력하는 방법
-사용자가 직접 DutyCycle 폭을 제어하는 방법




각 센서들은 위와 같이 사용하면 됩니다.

위 센서들을 아래 사진들과 같이 구성하였습니다.

0. 회로도


1. 전체 작품 사진


2. 서보모터를 아용하여 출입문으로 만들었습니다.


3. 초음파 센서를 이용해서 차량이 왔는지 확인할 수 있습니다.

4. LED를 이용해서 문이 OPEN되었는지 CLOSE 되었는지 확인할 수 있습니다.




5. 적외선 센서를 사용해서 차량이 주차되어 있는지 안되어있는지 확인할 수 있습니다.


6. 이 모든 것을 Ethernet(웹 브라우저)로 확인할 수 있습니다.




- 소스 코드


[code language="c"]

/* Parking System with Ethernet(Web Server) in Arduino created 25 Mar 2016 by Jinhee Ahn */ #include <SPI.h> #include <Ethernet.h> #include <Servo.h> #if defined(WIZ550io_WITH_MACADDRESS) // WIZ550io는 MAC주소가 내장되어 있는 모듈입니다. ; #else byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // mac 주소 입력 #endif //#define __USE_DHCP__ // DHCP사용 시 Define // Static IP 설정 IPAddress ip(192,168,1,177); // 로컬 네트워크에서 독립적인 IP를 사용해야 합니다. IPAddress gateway( 192, 168, 1, 1 ); IPAddress subnet( 255, 255, 255, 0 ); // fill in your Domain Name Server address here: IPAddress myDns(8, 8, 8, 8); // google puble dns // 소켓을 80번 포트로 생성 // 위 함수로 Socket을 생성하고 클라이언트 접속을 기다리는 대기모드로 진입한다. // HTTP를 사용할 땐 기본적으로 80번 포트 사용. // IANA(Internet Assigned Numbers Authority)에서 HTTP는 포트를 80번을 사용하자고 권유하였음. // 하지만 사용자가 원하는 대로 포트 설정 가능하다. // https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt EthernetServer server(80); void check_led_status(); #define close_led 5 #define open_led 3 #define trig 8 // 초음파센서의 송신부를 8번핀으로 설정합니다. #define echo 9 // 초음파센서의 수신부를 9번핀으로 설정합니다. // 적외선 센서 int pinNum = A1; //아날로그 0번핀 사용 int distance = 0; //거리값 변수 생성 // 초음파 센서 float distance2 = 0; //거리값 변수 생성 Servo servo; void setup() { servo.attach(7); Serial.begin(9600); pinMode(trig, OUTPUT); pinMode(echo, INPUT); pinMode(close_led, OUTPUT); pinMode(open_led, OUTPUT); pinMode(pinNum, INPUT); //A1번핀을 INPUT으로 설정 servo.write(95); digitalWrite(close_led, LOW); digitalWrite(open_led, HIGH); while (!Serial) { ; // 시리얼 포트가 연결 될 때까지 기다림, 레오나르도 보드의 경우만에만 필요 } // 이더넷 디바이스 초기화 #if defined __USE_DHCP__ // DHCP 사용 시 (네트워크 정보 DHCP에서 할당받음) #if defined(WIZ550io_WITH_MACADDRESS) // WIZ550io에 할당된 MAC 주소를 사용할 경우 Ethernet.begin(); #else Ethernet.begin(mac); // MAC이 없는 이더넷 디바이스의 경우 #endif #else // Static 주소로 사용 시 (네트워크 정보 사용자가 임의로 지정) #if defined(WIZ550io_WITH_MACADDRESS) Ethernet.begin(ip, myDns, gateway, subnet); #else Ethernet.begin(mac, ip, myDns, gateway, subnet); #endif #endif // 서버 연결 시작 server.begin(); Serial.println("Parking Control System"); Serial.print("server is at "); Serial.println(Ethernet.localIP()); // 설정된 IP 시리얼 메세지로 출력 } void loop() { EthernetClient client = server.available(); // 클라이언트로 부터 받은 Data "size"를 리턴 // loop에서 반복문으로 돌면서 클라이언트가 연결될 때 까지 대기 if (client) { // 클라이언트와 연결되면 '1'이 된다. (칩 내부적으로 ESTABLISHED 상태가 된다) 그리고 Data "Size"를 읽는다. Serial.println("new client"); boolean currentLineIsBlank = true; String buffer = ""; // 문자열 버퍼 선언 // 예외처리를 위한 서버의 현재 소켓 상태를 읽는다. // LISTEN, CLOSE, FIN_WAIT, CLOSE_WAIT 상태라면 Connection이라 판단하지 않는다. while (client.connected()) { // 적외선 int data = analogRead(pinNum); //적외선 거리 센서로 부터 측정값을 읽어온다 int volt = map(data, 0, 1023, 0, 5000); //측정한 volt값을 0에서 5000사이의 값으로 변환 distance = (21.61/(volt-0.1696))*1000; //측정값을 통해 거리를 계산 long start = millis(); // 초음파 센서는 송신부와 수신부로 나뉘어 있으며, // 송신부터 수신까지의 시간을 기준으로 거리를 측정합니다. // 트리거로 연결된 핀이 송신부를 담당하며, 에코로 연결된 핀이 수신부를 담당합니다. // 송신부에서 2마이크로초 정도 또는 그 이상의 시간동안 초음파를 발생시킵니다. // 초음파 발생 전후로, 잡음을 제거하기 위하여 전류를 보내지 않도록 설정합니다. digitalWrite(trig, LOW); digitalWrite(echo, LOW); delayMicroseconds(2); digitalWrite(trig, HIGH); delayMicroseconds(10); digitalWrite(trig, LOW); // 수신부의 초기 로직레벨을 HIGH로 설정하고, 반사된 초음파에 의하여 ROW 레벨로 바뀌기 전까지의 시간을 측정합니다. // 단위는 마이크로 초입니다. unsigned long duration = pulseIn(echo, HIGH); // 초음파의 속도는 초당 340미터를 이동하거나, 29마이크로초 당 1센치를 이동합니다. // 따라서, 초음파의 이동 거리 = duration(왕복에 걸린시간) / 29 / 2 입니다. distance2 = duration / 29.0 / 2.0; if (client.available()) { // 클라이언트로 부터 수신된 데이터가 있다면 char c = client.read(); // 데이터를 1byte씩 읽어서 c 변수에 저장 buffer += c; // 1 byte 데이터를 문자열 버퍼에 저장 Serial.write(c); // 클라이언트로 부터 수신한 데이터 시리얼로 출력 if (c == '\n' && currentLineIsBlank) { // currentLineIsBlank이 True일 때 // 클라이언트로 부터 HTTP 요청이 빈 라인(\n)으로 끝났을 때, 표준 HTTP 응답 헤더 전송 시작 // HTTP 시작 client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println("Refresh: 5"); client.println(); // 서버에 지정되어 있는 데이터 클라이언트로 전송 // client.println("<!DOCTYPE HTML>"); // HTML5 사용시 // HTML 시작 client.println("<html>"); // HTML 언어로 코드 작성 client.println("<body>"); if (distance > 10) { client.println("Parking is <font color='blue'>Empty</font>"); } else { client.println("Parking is <font color='red'>Full</font>"); } client.println("<br />"); client.println("<br />"); if(distance2 > 7){ client.println("<font color='red'>There is not a car in front of door !!</font>"); } else if (distance2 < 7) { client.println("<font color='green'>There is a car in front of door !!.</font>"); } client.println("<br />"); client.println("<br />"); if (digitalRead(open_led) == LOW) { // LED PORT가 '1'이면 LED ON, 아니면 LED OFF client.println("<font color='blue'>Door is open</font>"); // LED ON } else { client.println("<font color='red'>Door is close</font>"); // LED OFF } client.println("<br />"); client.println("<FORM method=\"get\" action=\"/parking.htm\">"); client.println("<P> <INPUT type=\"radio\" name=\"status\" value=\"1\">Door is OPEN"); client.println("<P> <INPUT type=\"radio\" name=\"status\" value=\"0\">Door is CLOSE"); client.println("<P> <INPUT type=\"submit\" value=\"Submit\"> </FORM>"); client.println("</body>"); client.println("</html>"); /* if(distance2 > 20){ servo.write(0); digitalWrite(close_led, LOW); digitalWrite(open_led, HIGH); } else if (distance2 < 20) { servo.write(90); digitalWrite(close_led, HIGH); digitalWrite(open_led, LOW); }*/ // HTML 종료 break; } if (c == '\n') { // 클라이언트로 부터 빈 라인을 받으면 버퍼 Clear currentLineIsBlank = true; buffer=""; } // LED ON else if ( c == '\r') { // 빈 라인이 아닌 "GET /led.cgi?status=1" 데이터를 받으면 if(buffer.indexOf("GET /parking.htm?status=1")>=0){ // HTTP client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // HTML client.println("<html>"); client.println("<body>"); if(distance2 > 20){ client.println("<font color='red'>There is not a car in front of door.</font>"); } else if (distance2 < 20) { client.println("<font color='green'>There is a car in front of door.</font>"); } client.println("<br />"); client.println("<a href=\"/parking.htm\">Go to control-page</a>"); // Main 페이지로 리턴 client.println("</body>"); client.println("</html>"); servo.write(10); digitalWrite(close_led, HIGH); digitalWrite(open_led, LOW); // HTML DONE currentLineIsBlank = false; break; } // LED OFF if(buffer.indexOf("GET /parking.htm?status=0")>=0){ // "GET /led.cgi?status=0" 데이터를 받으면 // HTTP client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); // HTML client.println("<html>"); client.println("<body>"); if(distance2 > 20){ client.println("<font color='red'>There is not a car in front of door.</font>"); } else if (distance2 < 20) { client.println("<font color='green'>There is a car in front of door.</font>"); } client.println("<br />"); client.println("<a href=\"/parking.htm\">Go to control-page</a>"); // Main 페이지로 리턴 client.println("</body>"); client.println("</html>"); servo.write(95); digitalWrite(close_led, LOW); digitalWrite(open_led, HIGH); // HTML DONE currentLineIsBlank = false; break; } } // \r과 \n이 아니라면 아직 전송 받을 Data가 남아있다는 뜻으로 알고 서버는 데이터를 기다린다. else{ //if( c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } delay(1); client.stop(); // TCP Connection 종료 Serial.println("client disonnected"); } }

[/code]


코드 업로드

WebServer_LED_2.ino



저자 : Edward AHN

저자 블로그 : http://openstory.tistory.com/

답글 및 댓글 모두 환영합니다.


감사합니다.