한 걸음 두 걸음

아두이노 IoT ] 유선 연결(Ethernet) 원격 통신 본문

Arduino

아두이노 IoT ] 유선 연결(Ethernet) 원격 통신

언제나 변함없이 2020. 9. 9. 18:48
반응형

Ethernet을 사용하여 인터넷과 통신을 해봅시다.


이더넷 연결, usb포트 연결 후 실행시키면 됨.

 

최종코드

#include<Ethernet.h>
#include<SPI.h>
#include<IoTStarterKit_Eth.h>

//KT Wow 모듈 정보
IoTStarterKit_Eth g_im;
#define deviceID "gkskfhD1599538792044"
#define authnRqtNo "x4ntyp34s"
#define extrSysID "OPEN_TCP_001PTL001_1000007512"

//맥주소 등록
EthernetClient client;
const char mac[] = {0x70, 0xB3, 0xD5, 0x6A, 0x60, 0x01};

//센서정의
#define LIGHT A3
#define TAG_ID "Light"

//IoT Makers 접속을 초기화 하는 함수
void init_iotmakers()
{
  int tryCount = 0; //각 접속 시도 횟수를 저장하는 변수

  while(1)
  {
    // Ethernet 접속 시도
    Serial.print("Begin the Ethernet...");
    tryCount = 0;
    while( (Ethernet.begin(mac) == 0) && tryCount < 5 )
    {
      Serial.println(F("retrying."));
      delay(2000);
      tryCount++;
    }
    if(tryCount < 5)
    {
      Serial.println("success");
    }
    else
    {
      Serial.println("fail");
      continue;
    }

    // 인자값으로 받은 정보로 KT IoT Makers 접속
    g_im.init(deviceID, authnRqtNo, extrSysID, client);

    // IoTMakers 플랫폼 연결
    Serial.print("Connect to Platform... ");
    tryCount = 0;
    while ( (g_im.connect() < 0) && tryCount < 5 ){
      Serial.println("retrying.");
      delay(1000);
      tryCount++;
    }
    if(tryCount < 5)
    {
      Serial.println("success");
    }
    else
    {
      Serial.println("fail");
      continue;
    }

    //IoTMakers 플랫폼 인증
    Serial.print("Auth... ");
    if(g_im.auth_device() >= 0)
    {
      Serial.println("success ");
      return;
    }
    Serial.println("fail");
  }
}


void setup() {
   Serial.begin(9600);
   pinMode(LIGHT, INPUT);
   init_iotmakers();
}

void loop() {
  static unsigned long tick = millis();
  if( (millis() - tick) > 1000){ //1초에 한 번씩 실행되도록 설정
    send_light();
    tick = millis();
  }

  g_im.loop();

}

int send_light(){
  int value = analogRead(LIGHT);
  int data = map(value, 0, 1023, 1023, 0);
  Serial.print("Light : ");
  Serial.println(data);

  if(g_im.send_numdata(TAG_ID, (double)data) <0){
    Serial.println(F("fail"));
    return -1;    
    }
    return 0;  
}

데이터 전달 모습(시리얼 모니터는 깜박하고 꺼버림)

 

 


ethernet통신 관련 라이브러리인 Ethernet에 대한 정보는 공식 홈페이지 라이브러리에서 확인할 수 있습니다.

 

https://www.arduino.cc/reference/en/libraries/

 

표준 라이브러리의 일종으로, Arduino Ethernet Shield, Arduino Ethernet Shield 2 및 Arduino Leonardo ETH를 사용하여 인터넷에 연결하기 위해 사용된다. 가지고 있는 아두이노가 이더넷 기능을 탑재하고 있거나(아두이노 윤) 이더넷 쉴드를 끼고 있어야 사용할 수 있습니다.

Ethernet 라이브러리는 아두이노 보드로 인터넷 연결을 할 수 있도록 돕고 서버로서 동작하거나 클라이언트 역할을 할 수 있도록 돕습니다. (최대 8개의 동시 연결을 지원하므로 작은 테스트 서버 정도로만 사용하기 좋겠네요.)

아두이노 쉴드와 SPI버스를 이용하여 통신하며, 이 통신은 우노의 경우 11,12,13번 핀 메가의 경우 50,51,52 핀을 사용하여 이뤄집니다.

이 라이브러리를 사용하기 위해서는 #include <SPI.h> #include <Ethernet.h> 헤더를 등록시켜주어야합니다.


위의 헤더를 등록시켰을 때 사용할 수 있는 이더넷 클래스의 함수를 살펴볼까요?

네트워크 세팅을 도와줍니다. 각자 필요한 것을 사용하면 되는데, 저는 아래 중에서 begin을 보도록 하겠습니다.

Ethernet.begin ()

이더넷 실드가 DHCP를 통해 라우터로부터 자동으로 IP주소를 얻을 수 있도록 도와주는 함수입니다. 이더넷 실드에는 MAC주소 스티커가 붙여져 있을 것이므로 이를 스케치에서 입력해주면 됩니다.

const char mac[] = {0x70, 0xB3, 0xD5, 0x6A, 0x60, 0x01};

Ethernet.begin(mac) == 0

저는 이처럼 MAX주소에 0x를 붙여 16진수임을 표현했고, 이를 char배열에 담아 begin함수에 넣어주었습니다. 여기서 DHCP연결 성공 시 1을 반환하고, 실패시 0을 반환하므로 위와같이 판단등호와 함께 사용하시면 됩니다.


저는 KT 모듈을 사용하고 있어 이 다음부터는 KT에서 제공하는 라이브러리인 #include<IoTStarterKit_Eth.h>를 사용하여 IoT 구현에 도움을 받았습니다. IoTStarterKit_Eth클래스의 객체 g_im를 만들어 g_im.init(deviceID, authnRqtNo, extrSysID, client);으로 KT IoT Makers에 접속하였습니다. (사전에 디바이스 등록을 하면 받을 수 있는 값입니다.)

init함수는 init(deviceId, devicePasswd, gatewayId, client)를 매개변수로 받는 함수로, IoTMakers 클라이언트의 인스턴스를 초기화해줍니다.

 

 

char * 자료형 매개변수를 받으므로, 문자열을 건네면 됩니다. client의 경우엔 EthernetClient클래스의 객체를 전달해야합니다. (EthernetClient 클래스 라이브러리 www.arduino.cc/en/Reference/ClientConstructor)


위에서 Makers에 접속 성공했다면, 이제 플랫폼과 연결할 차례인데요, IoTMakers 플랫폼 연결을 위해 IoTStarterKit_Eth클래스에 있는 connect함수를 사용했습니다.

 

 

매개변수는 받는게 없고 성공이면 0을 반환합니다.


플랫폼과도 연결이 되었다면 이제 디바이스 인증을 해주어야하는데, IoTStarterKit_Eth클래스에 있는 auth_device()함수를 사용했습니다.

 

 

인증에 성공하면 0을 반환하며, 인증 성공시에는 현재 채널에 대한 인증번호(authNum)를 받아 내부적으로 처리합니다.


//IoT Makers 접속을 초기화 하는 함수
void init_iotmakers()
{
  int tryCount = 0; //각 접속 시도 횟수를 저장하는 변수

  while(1)
  {
    // Ethernet 접속 시도
    Serial.print("Begin the Ethernet...");
    tryCount = 0;
    while( (Ethernet.begin(mac) == 0) && tryCount < 5 )
    {
      Serial.println(F("retrying."));
      delay(2000);
      tryCount++;
    }
    if(tryCount < 5)
    {
      Serial.println("success");
    }
    else
    {
      Serial.println("fail");
      continue;
    }

    // 인자값으로 받은 정보로 KT IoT Makers 접속
    g_im.init(deviceID, authnRqtNo, extrSysID, client);

    // IoTMakers 플랫폼 연결
    Serial.print("Connect to Platform... ");
    tryCount = 0;
    while ( (g_im.connect() < 0) && tryCount < 5 ){
      Serial.println("retrying.");
      delay(1000);
      tryCount++;
    }
    if(tryCount < 5)
    {
      Serial.println("success");
    }
    else
    {
      Serial.println("fail");
      continue;
    }

    //IoTMakers 플랫폼 인증
    Serial.print("Auth... ");
    if(g_im.auth_device() >= 0)
    {
      Serial.println("success ");
      return;
    }
    Serial.println("fail");
  }
}

여기까지가 init_iotmakers()함수를 이해하는데 필요한 것들입니다.

void setup() {
   Serial.begin(9600);
   pinMode(LIGHT, INPUT);
   init_iotmakers();
}

setup함수로 보드레이트 9600 설정하고 A3로부터 조도값 입력받은 후 네트워크 설정을 해주었습니다.


void loop() {
  static unsigned long tick = millis();
  if( (millis() - tick) > 1000){ //0.1초에 한 번씩 실행되도록 설정
    send_light();
    tick = millis();
  }

  g_im.loop();

}

그 다음은 loop함수 부분입니다.

 

 

millis함수는 아두이노에서 헤더를 추가하지 않아도 사용할 수 있는 시간 함수 중 하나입니다. 아두이노 보드를 켜고 난 후로 지난 밀리초를 반환하는 함수로, 1000ms마다 send_light()함수가 실행됩니다.

int send_light(){
  int value = analogRead(LIGHT);
  int data = map(value, 0, 1023, 1023, 0);
  Serial.print("Light : ");
  Serial.println(data);

  if(g_im.send_numdata(TAG_ID, (double)data) <0){
    Serial.println(F("fail"));
    return -1;    
    }
    return 0;  
}

send_light함수는 A3로부터 조도 값을 읽은 후, 직관적으로 이해하기 쉽도록 데이터를 map()으로 바꿔줍니다.(원래는 어두울수록 높은 값을 반환하고, 밝을 수록 낮은 값을 반환하나 반대가 되도록 설정해주었습니다.)

 

 

map함수 또한 스케치에서 별도의 헤더 없이 바로 사용할 수 있는 수학 함수로 map(value, fromLow, fromHigh, toLow, toHigh) 형식으로 사용합니다. 그렇게 해서 가져온 data값을 시리얼 모니터에 찍어주고 g_im객체의 send_number()함수를 를 통해 KT서버로 data값을 전달해줍니다. 이 때 태그스트림은 미리 홈페이지에서 등록해놨던 Light를 그대로 사용합니다.

 

trxid값은 반드시 명시하지 않아도 되는 듯 합니다. 

 

숫자형의 데이터를 전달하는 함수로 성공하면 0을 반환합니다. 성공했을 경우, KT IoTMakers 홈페이지에서 변화하는 데이터 값을 확인할 수 있습니다.(그래프나, 수치, json등) 이 데이터를 모바일로 보내면 앱으로도 활용가능하고, 내가 만든 웹이나 서버로 보내면 꼭 KT페이지가 아니어도 표시가 가능하겠죠.

마지막으로 g_im.loop()함수를 호출하여 내부처리 loop() 접속유지 및 제어데이터를 수신하는 상태가 됩니다. 정확히는 IoTMakers 내부작업을 수행하는 함수로 먼저 디바이스와 IoTMakers 플랫폼과의 연결유지를 위하여 Keepalive 메시지를 매 30 초간격으로 전송하고 IoTMakers 플랫폼으로 부터 전송된 제어 데이터가 있는지 확인한 후 제어데이터가 수신되었을 경우 사용자가 등록한 핸들러(콜백함수)를 호출하는 함수입니다. 수행할 작업이 없으면 즉시 리턴합니다.


여기까지 유선 IoT를 구현해보고, 동작 방식을 이해해보았습니다.

다음엔 WiFi를 이용하여 아두이노 무선 연결 IoT 구현을 자세히 살펴보고 제어실습까지 해볼 예정입니다.

이후 IoTMakers아두이노가 아닌 Arduino Yun을 이용하여 통신하는 연습을 하고

Spring으로 만든 서버를 AWS에 등록하여 사용해볼 예정입니다.

AWS 이후 DB연동하여 데이터를 쌓고 S3활용도 도전해보겠습니다.

서버가 완성되면 직접 만든 프론트앤드 웹/하이드리드웹앱 네이티브 앱에 표현하는 것으로 개발 준비를 마치겠습니다.

반응형