과정명	IoT기반 융합 SW 개발자 양성과정
과목명	오픈플랫폼활용(2001020325_16v1 )	요소명	오픈플랫폼디바이스제어하기 오픈플랫폼APP제어하기
수행일자	2017년 12.29 ~ 2018년 01.12	훈련생

수행과제

아두이노 우노를 이용하여 태스크를 스케치하고 실행하시오. (5점 만점)

개발 환경 구축(1점), 센서 활용(2점), 모터 활용(3점), 쉴드 활용(4점), 통신(5점)

과제를 통해 확인할 능력 사항

- 오픈 플랫폼 개발 환경을 구축할 수 있다.

- 단위 모듈 및 공통 모듈의 프로그램을 구현할 수 있다.

- 오픈 플랫폼 드라이버를 활용할 수 있고 센서를 제어할 수 있다.

- 오픈 플랫폼에서 애플리케이션을 개발할 수 있다.

수행결과

아두이노 우노 보드와 PC상의 콘솔 응용 프로그램과 통신하는 애플리케이션

제일 먼저 필요한 헤더파일을 포함합니다.

/* Simple UDP */

#include <SPI.h>

#include <Ethernet.h>

#include <EthernetUdp.h>

통신에 사용할 포트 번호를 정합니다. 여기에서는 10200 번으로 할게요.

const int udp_port = 10200;

UDP 통신을 할 때 사용할 EthernetUDP 형식의 udp 개체를 선언합니다.

EthernetUDP udp;

아두이노에서 UDP 통신에 사용할 패킷의 최대 크기는 UDP_TX_PACKET_MAX_SIZE 로 정해졌습니다.

수신하기 위한 버퍼를 선언합니다.

char buffer[UDP_TX_PACKET_MAX_SIZE];

여기에서는 패킷을 수신하면 응답으로 약속한 문자열을 전송하기로 할게요. 주의할 점은 맨 마지막 종료 문자는 보내지 않으니 수신하는 곳에서 적절한 처리를 하세요.

const char ack_msg[UDP_TX_PACKET_MAX_SIZE]="everyday is a holiday!";

이제 설정 부분입니다.

void setup() {

자신의 IP를 확인하는 부분을 작성합시다. 테스트하는데 아두이노 우노의 IP를 모르면 통신을 할 수 없으니 확인하기 쉽게

자신의 IP를 확인하여 시리얼 모니터에 출력하게 합시다. 이에 관한 사항은 아두이노 IP 주소 확인하기를 참고하세요.

byte mac[] = { 0xDE, 0xAD, 0x11, 0xEF, 0xFE, 0xED };

EthernetClient client;

// Start Serial

Serial.begin(9600);

while (!Serial) {

; // Wait until connected

}

//ethernet start

if (Ethernet.begin(mac) == 0) {

Serial.println("Failed to configure Ethernet using DHCP");

return;

}

delay(1000);

Serial.println("My IP address");

IPAddress local_ip = Ethernet.localIP();

for (byte addrelem = 0; addrelem < 3; addrelem++) {

//print IPv4 Address

Serial.print(local_ip[addrelem], DEC);

Serial.print(".");

}

Serial.print(local_ip[3], DEC);

Serial.println();

udp 통신을 시작합니다.

udp.begin(udp_port);

그리고 시리얼 모니터에 udp 통신을 시작함을 출력합시다.

Serial.println("Ready UDP");

Serial.print("Maimum Packet Size :");

Serial.print(UDP_TX_PACKET_MAX_SIZE);

Serial.println("bytes.");

}

이제 실제 통신 부분입니다.

void loop()

{

udp의 멤버 메서드 parsePacket을 호출하면 수신한 패킷 크기를 알 수 있습니다.

int psize = udp.parsePacket();

if(psize)

{

수신한 패킷 크기가 유효하면 수신한 패킷이 있는 것입니다. 몇 바이트를 수신하였는지 시리얼 모니터에 출력합시다.

Serial.print("Received packet : ");

Serial.print(psize);

Serial.println("bytes.");

udp의 read 메서드를 호출하여 수신한 패킷의 데이터를 프로그램 메모리로 읽어옵니다.

udp.read(buffer,UDP_TX_PACKET_MAX_SIZE);

읽어온 데이터를 시리얼 모니터에 출력합시다.

Serial.println(buffer);

전송하기 위해 상대 IP와 Port 정보를 입력 인자로 beginPacket 메서드를 호출합니다.

udp.beginPacket(udp.remoteIP(), udp.remotePort());

udp의 write 메서드를 호출하여 메시지를 수신하였음을 알려줍니다. 여기에서는 약속한 문자열을 전송할 것입니다.

udp.write(ack_msg);

그리고 endPacket 메서드를 호출하여 패킷을 전송합니다.

udp.endPacket();

시리얼 모니터에도 전송하였음을 출력합시다.

Serial.println("Send Message");

}

delay(10);

}

다음은 시연화면입니다.

여기에서는 윈도우즈 콘솔 응용 프로그램으로 만들었습니다. 이 부분에 관한 설명은 생략할게요.

//UDP 통신 - PC 용 콘솔 응용 프로그램

//    UDP 프로토콜 사용

//    문자열을 입력받아 메시지 전송 후 서버가 보낸 메시지 수신

#pragma warning(disable:4996)

#include <stdio.h>

#include <process.h>

#include <stdlib.h>

#include <WinSock2.h>//윈속 2 사용시 포함할 헤더

#pragma comment(lib,"ws2_32") //윈속 2.2 라이브러리 참조

#define MY_IP       "192.168.219.140" //PC IP주소-자신의 환경에 맞게 수정하세요.

#define MY_PORT  10200

#define ADU_IP     "192.168.219.109"  //아두이노 IP 주소-아두이노 시리얼 모니터의 출력값으로 수정하세요.

#define ADU_PORT 10200

#define UDP_TX_PACKET_MAX_SIZE  24

int main(void)

{

WSADATA wsadata;

WSAStartup(MAKEWORD(2, 2), &wsadata);//윈속 초기화

SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //1. 소켓생성

if (sock == SOCKET_ERROR) //SOCKET_ERROR는 -1

{

fprintf(stderr, "소켓 생성 실패");

return 0;

}

//2. 소켓과 로컬 소켓 주소 결합(생략 가능)

int re = 0;

SOCKADDR_IN local_addr = { 0 };//IPv4 소켓 주소 구조체 변수 선언

local_addr.sin_family = AF_INET; //네트워크 주소 체계 설정

local_addr.sin_addr.s_addr = inet_addr(MY_IP);//서버 IP 주소 설정

local_addr.sin_port = htons(MY_PORT);//포트 설정

re = bind(sock, (SOCKADDR*)&local_addr, sizeof(local_addr));

//3. 서버에 연결 요청

re = 0;

SOCKADDR_IN adu_addr = { 0 };//IPv4 소켓 주소 구조체 변수 선언

adu_addr.sin_family = AF_INET; //네트워크 주소 체계 설정

adu_addr.sin_addr.s_addr = inet_addr(ADU_IP);//아두이노 IP 주소 설정

adu_addr.sin_port = htons(ADU_PORT);//포트 설정

int len = sizeof(adu_addr);

//4. 아두이노와 송수신

char buf[UDP_TX_PACKET_MAX_SIZE];

while (1)

{

gets_s(buf, sizeof(buf));

re = sendto(sock, buf,strlen(buf)+1,

0,(SOCKADDR *)&adu_addr,sizeof(adu_addr));

printf("%d\n", re);

if (strcmp(buf, "exit") == 0)

{

break;

}

re = recvfrom(sock, buf, sizeof(buf), 0,(SOCKADDR*)&adu_addr,&len);

buf[re] = 0;

printf("수신:%s\n", buf);

}

//5. 소켓 닫기

closesocket(sock);

WSACleanup();//윈속 해제화

return 0;

}