WiFi 를 통한 아두이노 활용(3) : 무선 접속 기본 예제

2017. 7. 14. 16:59

Arduino/Wireless

Adafruit Feather M0 WiFi - ATSAMD21 + ATWINC1500

WiFi Connect Examples

이번 글에선 두 가지 예제를 통하여 아두이노를 이용한 인터넷 활용 연재를 본격적으로 시작합니다. 첫 번째는 무선 공유기 등 기존 무선 네트워크에 접속하는 예제이고, 그 다음, 클라이언트로 서버에 접속하여 메시지를 응답 받는 예제를 다룹니다.

Connect with WPA

이번 글에선 다루는 예제는 WiFi101 라이브러리에서 제공하는 것이고, 클라이언트 요청이나 서버 서비스 제공 등의 기능 없이 단순히 무선 네트워크에 접속하여 기본적인 네트워크 관련 정보를 출력하는 세 개의 예제가 있습니다. 접속 암호가 없는 개방형 WiFi망에 접속하려면 3개중 첫번째 ConnectNoEncryption 예제를 사용하고, 아니라면 암호화 방식에 따라 ConnectWithWEP, ConnectWithWPA 중 인증 방식에 맞게 골라 주시면 됩니다. 저는 앞으로도 사용할 방식이라서 WPA 방식으로 접속해 보겠습니다.

예제 화면입니다. 1번행부터 14번행까지는 예제에 대한 소개가 주석으로 들어가 있고, 2개의 헤더 파일이 include 되고 있습니다. 보드에 와이파이 모듈이 SPI 방식으로 병합되어 있기 때문에, SPI.h 파일이 필요하고, 또 WiFi101.h 헤더 파일도 당연히 포함되구요!

그 다음, 접속하려는 무선망 정보 즉, SSID name과 해당 Password 를 입력합니다. 개방형 네트워크라면 패스워드 부분이 필요 없고, WEP 방식이면 key값 등의 추가적인 정보가 더 필요 하겠죠.

그 다음 줄에 정수형 변수 status가 선언되고 WL_IDLE_STATUS 값으로 초기화되었습니다. status변수는 WiFi.status()함수를 이용해서 네트워크 연결에 대한 상태값을 받아 체크할 때 사용합니다. 초기값은 IDLE 이니 쉬고 있는 상태라는 뜻 같습니다. 위에서 include 된 두번째 헤더파일 WiFi101.h 파일을 열어 보면 어떤 상태값이 있는지 볼 수 있습니다.

해당 라이브러리가 있는 폴더로 이동하시면 그림과 같이 헤더파일을 찾을 수 있습니다. 저 같은 경우 문서 폴더에 들어 있네요! 위 그림 참고하세요!

typedef enum {
WL_NO_SHIELD = 255,
WL_IDLE_STATUS = 0,
WL_NO_SSID_AVAIL,
WL_SCAN_COMPLETED,
WL_CONNECTED,
WL_CONNECT_FAILED,
WL_CONNECTION_LOST,
WL_DISCONNECTED,
WL_AP_LISTENING,
WL_AP_CONNECTED,
WL_AP_FAILED,
WL_PROVISIONING,
WL_PROVISIONING_FAILED
} wl_status_t; 

WiFi101.h 헤더파일 위쪽에 위와 같이 열거형 타입으로 선언되어 있습니다. 열거형이므로 각 상태값은 정수형 값에 해당하고, WL_NO_SHIELD = 255, WL_IDLE_STATUS = 0 처럼 직접 정수값이 없다면 바로 위 값에서 1씩 증가하며 값이 할당됩니다. 아래 표를 참고 하세요!

WiFi module Status Value in WiFi101.h
Enum Value Enum Value
WL_NO_SHIELD 255 WL_DISCONNECTED 6
WL_IDLE_STATUS 0 WL_AP_LISTENING 7
WL_NO_SSID_AVAIL 1 WL_AP_CONNECTED 8
WL_SCAN_COMPLETED 2 WL_AP_FAILED 9
WL_CONNECTED 3 WL_PROVISIONING 10
WL_CONNECT_FAILED 4 WL_PROVISIONING_FAILED 11
WL_CONNECTION_LOST 5

위 부분은 시리얼 모니터 관련이니 따로 설명 않구요, 다만 WiFi module 이 SPI 방식으로 연결되어 있는데, Arduino WiFi101 shield나 MKR1000 보드와 핀 설정이 달라서 핀설정 명령을 넣어 주어야 한다고 이전 글에서 설명했었습니다. 한번만 실행하면 되니 setup() 함수에 들어가는데, 다른 와이파이 관련 코드 이전에 들어가야 하므로, 위에 표시한 부분 위쪽이나 바로 아래쪽에 넣으셔야 합니다.

void setup() {
  //Configure pins for Adafruit ATWINC1500 Feather
  WiFi.setPins(8,7,4,2);
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
}

저는 위쪽에 관련 코드를 삽입했습니다.

위 코드는 와이파이 쉴드가 있는지 체크하는 부분입니다. Feather 보드는 와이파이 모듈이 같은 보드에 통합된 상태이니 없을리는 없지만, 혹시나 와이파이 모듈만 나갈 수도 있으니 지우지 않고 그냥 두었습니다. 쉴드가 연결되지 않은 상태라면 더이상 진행하지 않기 위해서 while (true); 행을 통해 무한루프로 들어 갑니다.

무선망에 연결을 시도하는 부분입니다.

while ( status != WL_CONNECTED) {

WL_CONNECTED 열거자는 연결이 성공하면 반환되는 값으로 정수값 3을 가집니다. status 는 현재 연결 상태값을 가지고 있고, 연결이 성공한 상태가 아니라면 연결을 시도한다는 의미입니다. 물론 이 예제에서는 이 부분이 필요 없습니다. setup() 함수 내에서 해당 코드가 있기 때문에, setup() 함수의 특성상 한번만 실행하니까요. 게다가 status 변수는 선언하고 초기값을 준 이후로 변경된 적이 없습니다. 여전히 WL_IDLE_STATUS 값 상태입니다. 물론 실제 프로젝트에 적용할 때엔 계속해서 연결 상태에 있어야 하고, 접속이 끊기면 상태 체크해서 다시 연결해야 하니, loop() 함수에 구현하고 위와 같은 부분이 필요합니다.

// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);

네트워크에 연결하는 코드입니다. 맨 위쪽에서 미리 정해준 SSID, Password 값을 인수로 해서 begin() 함수를 호출합니다. WiFi.begin() 함수도 WiFi.status()와 같은 반환값을 가집니다.

연결을 위한 while()문의 마지막 코드입니다. 연결에 성공했든 실패했든 이 문장을 만나서 10초동안(밀리초 단위, 1000이 1초) 기다립니다. 10초를 기다린 후, 다시 while() 문 입구로 돌아가 status 값을 비교합니다. 연결에 성공했다면 statusWL_CONNECTED 값을 갖고 있을 것이므로 while 조건에 위배되어 루프를 탈출할 테고, 연결에 실패했다면 루프로 들어가서 다시 연결을 시도합니다. 연결에 성공할 때까지 무한루프를 돌게 되고, 매번 10초씩 기다립니다. 연결에 대해서 여러번 테스트 할 생각이라면 1초로 줄여주는게 좋을 듯 합니다!!

여기 까지 왔다면, 연결에 성공해서 while() 루프를 탈출했을 테고, 이제 연결됐다는 메시지를 출력하고 연결된 네트워크 정보와 와이파이 관련 데이터를 출력하는 두 개의 함수를 실행합니다.

설명하느라 길어졌지만, 처음 예제를 불러와서, SSID, Password 값 두 개 넣어주고, SPI 핀 설정 명령 한 줄 넣어주면 바로 실행 가능 합니다.

최종적으로 실행한 모습입니다.

아두이노를 클라이언트로 서버에 접속하는 예제

같은 라이브러리 예제에서 WiFiWebClient 예제를 불러 옵니다. 이 예제는 클라이언트 역할로 구글에 접속해서 arduino 에 관한 검색 결과를 받아서 시리얼 모니터에 출력해 줍니다. 서버에 접속해서 데이터를 전송받는 예제는 다음 글에서 자세히 다루고, 여기서는 수정없이 구동해서 결과 확인만 하겠습니다. 위에서 이미 설명한 부분은 다시 언급하지 않겠습니다.

예제 도입부의 주석 부분은 건너 뛰고, 앞선 예제와 마찬가지로 네트워크 접속 정보를 입력해 줍니다. 그림에 표시된 부분은 WEP 방식에 필요한 부분이므로 무시합니다. 그 다음 줄은 역시 앞선 예제와 동일한 코드가 반복 되고 있습니다.

접속할 서버에 대한 주소를 지정합니다. DNS 명을 넣었는데, 숫자로된 IP주소값을 직접 넣어도 된다는 설명입니다.

WiFiClient 클래스 변수를 client 이름으로 선언합니다.

그리고 바로 setup() 함수가 시작되는데, 함수 앞 부분은 wifi 연결과 관련된 내용으로 중복되어 언급 없이 넘어 갑니다. setup() 함수 시작할때 SPI 핀 설정 꼭 잊지말고 넣어 주세요!!

연결이 성공하면 메시지를 출력하고, printwiFiStatus() 함수를 이용해 접속한 네트워크 관련 정보를 출력합니다.

이 부분이 미리 지정한 서버에 접속해서 웹 데이터를 전송 받는 부분입니다.

if (client.connect(server, 80)) { 

server 는 www.google.com 으로 지정했고, 80 포트로 연결합니다. IF 문으로 감쌌기 때문에, 연결이 성공해야 나머지 코드를 실행 하며, 실패할 경우 프로그램은 그냥 종료 됩니다.( setup() 함수이기 때문에...)

client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host: www.google.com");
client.println("Connection: close");
client.println();

웹 요청을 하는 코드입니다. 첫째줄과 둘째줄을 합시면 우리가 웹브라우저 주소창에 "http://www.google.com/search?q=arduino" 라고 입력하는 것과 동일합니다.

loop() 함수에서는, 서버에서 보내준 데이터를 시리얼 모니터에 그대로 출력하는 부분이 먼저 나오고, 이 상태는 서버와의 접속이 종료되기 전까지 계속 됩니다. 접속이 종료되면 메시지를 출력하고, 무한루프로 들어가 대기 상태가 됩니다. 간단한 예제라서 연결을 다시 설정하는 부분은 없구요.

실행 한 후의 결과입니다. 더 좋은 예제로 자세히 설명하기 위해 이번 예제는 간단히 짚고 넘어 갑니다.

이상입니다.


Comments