관리 메뉴

Edward's Labs

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

Edward's Project/ARDUINO Project

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

Eddy 2016.06.01 12:58

안녕하세요.


이번에 아두이노를 이용해서 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/

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


감사합니다.


15 Comments
댓글쓰기 폼