아두이노 코딩-77: Cactus Micro ESP8266WiFi 클라이언트 ThingSpeak 코딩: II

codingart(66)
Published in
#kr
Words
772
Reading
4 min
Listen
Play
8y

noname01.png

이 코딩 예제는 바로 앞의 ThingSpeak 사이트 예제 I(https://steemit.com/kr/@codingart/75-cactus-esp8266wifi-thingspeak-i-thingspeak)에서 ThingSpeak 무료 회원 가입 문제를 해결하였고 ThingSpeak에서 제공하는 url을 사용한 GET 명령을 검토하였다. 그 내용은 아두이노 NodeMCU/WeMos 사물인터넷 웹서버 코딩에서의 GET 사용법과 어느 정도 유사성이 있다. 물론 이번 블로그에서 응용 예제는 Cactus Micro 초소형 보드를 사용하여 ThingSpeak에 데이터를 보내지만 차후에 별도로 NodeMCU/WeMos 보드를 사용하는 방법도 간단하게 언급할 계획이다. 사용하는 라이브러리와 약간의 코딩이 다르긴하나 그 전체적인 코딩 구조는 거의 같은 편이다.

Cactus Micro 모듈 코딩에 반드시 필요한 와이파이 지원 라이브러리는 아래 인터넷 url 주소의 Github로부터 다운 받도록 한다.

https://github.com/tuanpmt/espduino

espduino 폴더가 Cactus Micro 보드 코딩에 필요한 라이브러리이다. 반드시 자신이 잘 아는 경로에 다운 받아서 압축을 풀면 espduino-master 폴더가 생성된다. 아두이노 편집기 스케치 탭에서 라이브러리 포함하기 탭에서 .ZIP 라이브러리 추가 명령을 클릭한 후 espduino-master 디렉토리 경로를 정확하게 설정하도록 한다.

noname02.png

라이브러리 내부를 보면 mqtt, pushbullet, rest 및 thingspeak 폴더들이 들어 있다. 본 코딩에서는 특별한 센서 사용 없이 구하기 쉬우며 배선이 가장 단순한 가변 저항만을 사용한 rest를 사용하는 코드를 제시하기로 한다. thingspeak 폴더 내용은 디지털 온습도 센서인 DTH11을 사용하는 내용인데 가변저항에서 아날로그 전압 데이터가 나온다는 점을 제외하면 프로그램 구조는 대단히 유사하다.

noname03.png

espiduino 라이브러리 속 Examples 폴더에 예제 코드들이 들어 있는데 아래에 제시된 코드는 가변저항에서 생성되는 아날로그 전압 값을 ThingSpeak에 전송할 수 있도록 약간 수정된 코드이다. //Catus_thingspeak_resistor_03

noname04.png

NodeMCU/WeMos에서 ESP8266WiFi.h 하나의 라이브러리 사용과는 대조적으로 두 개의 라이브러리가 필요하다. Cactus 보드는 원천적으로 13번 핀을 소프트웨어적으로 digitWrite() 명령을 사용 LOW 상태로 즉 Enable 상태로 만든 후 ESP8266 칩을 작동시키게 되어 있다.

SSID에 자신의 스마트폰 핫 스팟 ID를 PASS에 비밀번호를 입력한다. 연이어 ThingSpeak에서 부여 받은 Write API 키 값을 입력한다. InputAnalog = 0 은 아날로그 채널 A0 에 해당하는 변수 선언으로서 0번 채널에서 전압 값을 읽게 된다.

noname05.png

setup() 이전에 즉 wifiConnected 라는 boolean 변수를 거짓(false) 로 설정하고 wifiCb 루틴을 호출하여 접속 후 setup()으로 넘어간다.

setup()에서 2종류의 통신 속도를 설정해야 하는데 19200이며 NodeMCU의 115200과는 크게 차이가 나고 있다. 그 이유는 Cactus Micro의 클럭 속도가 8MHz임에 반해 NodeMCU는 80MHz임을 상기하자. 특히 Serial1은 Cactus 보드와 ESP8266 칩과의 시리얼 통신 설정이며 Serial은 PC와의 통신설정이다.

noname06.png

위의 박스는 Cactus Micro가 클라이언트로서 ThingSpeak에 데이터를 전송하는 핵심 코딩이다. 이 부분을 잘 기억했다가 NodeMCU/WeMos 보드에서 ThingSpeak에 데이터를 전송하는 코딩 시에도 거의 바뀔 부분이 없기 때문에 참조하도록 하자.
C 명령 dtostrf() 에 대해서 알아보자. dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf)에서 floatvar 는 ThingSpeak에 보내려고 하는 온도라든지 전압과 같은 아날로그 형 실수형 변수 값을 뜻한다. StringLengthIncDecimalPoint는 실수형 변수의 자리수를 뜻하며 아두이노 응용에서 4자리로 설정하면 충분하다. numVarsAfterDecimal는 4자리수로 표현되는 변수 값에서 소숫점 이하 자리수를 지정한다.
charbuf는 인터넷 url을 통해 송신하기위한 ASCII로 처리된 문자를 저장하는 버퍼이다.
이러한 내용을 감안하여 아래와 같이 코딩하였다.

 dtostrf(temp, 4, 1, strTemp);

sprintf() 명령은 C 언어 문법에서 그 사용법 및 내용을 확인해 보도록 한다.
API-Key 는 코딩 초반 부에 정의 되어 있다.

REST방식에 의한 통신에서 Cactus Micro 클라이언트가 데이터를 전송하면 즉 GET 하면 이에 상응하여 데이터 수신 성공 여부를 회신해 준다. response, 266에서 266 메세지는 서버가 즉 ThingSpek 서버가 전달된 리소스 중에서 헤더에 의해 지정된 일부 정보만 서버가 성공적으로 받았다는 메시지이다.

마지막으로 한 번 데이터 전송 후 15초 지연 시켜 샘플링 시간 간격을 지켜주도록 한다.

noname07.png

아두이노 편집기에서 보드는 LilyPad Arduino USB로 지정후 COM 포트가 인식이 되면 업로딩한다. 아래와 같은 메시지를 시리얼 모니터에서 볼 수 있다.

noname08.png

코드가 실행되면 시리얼 모니터 창에서 핫스팟에서 할당된 IP를 출력하고 가변 저항에 걸린 전압 값을 출력한다.

준비가 되었으면 ThingSpeak 사이트에 로그인한 상태에서 Private View에서 지금의 경우 483 이라는 데이터가 나옴을 확인한 후에 가변저항을 돌려서 좀 느리긴 하지만 실시간 데이터를 그래프 처리해 보기로 한다. 가장 간단한 예제로서 0∼1023 사이의 값을 왕복해 보도록 한다.

noname09.png

실제 코드에서 16초의 샘플링 지연을 주었으나 ThingSpeak에서의 처리 주기는 30 초였다.

NodeMCU Web Server 예제를 참고로 Cactus 모듈도 Web Server 예제로 전환하기 위해서는 서로 사용하는 라이브러리가 다르므로 프로그래밍이 다소 어려울 수 있겠지만 관심 있는 분들의 코딩을 권장하는 바이다.

//Catus_thingspeak_resistor_03
#include "espduino.h"
#include "rest.h"

#define PIN_ENABLE_ESP 13
#define SSID "android1234"
#define PASS "dddddddddd"

int InputAnalog = 0;

// replace with your channel's thingspeak API key
String apiKey = "0DKP99L3Z0DXYESP";

ESP esp(&Serial1, &Serial, PIN_ENABLE_ESP);
REST rest(&esp);

boolean wifiConnected = false;

void wifiCb(void* response)
{
uint32_t status;
RESPONSE res(response);

if(res.getArgc() == 1) {
res.popArgs((uint8_t*)&status, 4);
if(status == STATION_GOT_IP) {
Serial.println("WIFI CONNECTED");

  wifiConnected = true;
} else {
  wifiConnected = false;
}

}
}

void setup() {
Serial1.begin(19200);
Serial.begin(19200);
esp.enable();
delay(500);
esp.reset();
delay(500);
while(!esp.ready());

Serial.println("ARDUINO: setup rest client");
if(!rest.begin("api.thingspeak.com")) {
Serial.println("ARDUINO: failed to setup rest client");
while(1);
}

/setup wifi/
Serial.println("ARDUINO: setup wifi");
esp.wifiCb.attach(&wifiCb);
esp.wifiConnect(SSID, PASS);
Serial.println("ARDUINO: system started");
}

void loop() {
char response[266];
esp.process();
if(wifiConnected) {

// read the value from InputAnalog.
int val = 0;
val= analogRead(InputAnalog);
// convert to float temp: temp value is in 0-1023 range
float temp = val;

  char buff[64];
  char strTemp[6];
  dtostrf(temp, 4, 1, strTemp);

// Serial.println(buff);
sprintf(buff, "/update?api_key=0DKP99L3Z0DXYESP&field1=%s", strTemp);

  rest.get((const char*)buff);
  Serial.println(strTemp);

// Serial.println("ARDUINO: send get");

  if(rest.getResponse(response, 266) == HTTP_STATUS_OK){

// Serial.println("ARDUINO: GET successful");
Serial.println(response);

  delay(16000);

} 
else {
  Serial.print("error,\r\n"); 
}

}
}//끝