고급 예제

다양한 도구들을 가지고 마음껏 응용해보세요.

thingspeak API사이트-센서값 모니터링 하기

2014-12-02 03:35:25

개요


출처 : helloworld.naver.com

open API라고 아시나요?

안드로이드폰에서 지도를 띄우고 싶으면 구글 지도 API를 사용하여 띄웁니다.
이처럼 어떤 기업, 국가가 보유한 데이터 들을 누구나 쉽게 사용하여 웹, 앱을 개발할 수 있도록 지원한 것이 open API입니다.
웹, 앱 개발 뿐만이 아니라 아두이노를 사용하는 데 있어서도 OPEN API는 많이 사용됩니다.
예를 들어 오늘 날씨를 예상해서 불빛이나 LCD로 알려줄수도 있습니다.

출처 : https://thingspeak.com/

아두이노를 사용하면서 어려운 점 중 하나가 값을 체크하고 측정한 값을 저장하고 웹이나 앱으로 보여주는 점입니다. 
일반 사용자가 아두이노로 무엇인가 만드는 것부터 웹이나 앱까지 만들기는 쉬운일이 아닙니다.
이럴 때 thingspeak과 같은 사이트를 이용하면 좋습니다.
thingSpeak과 같은 사이트에서는 open API를 제공하여 자신들의 사이트에서 쉽게
값을 모니터링 할 수 있도록 해줍니다.



본문에서는 다음과 같은 과정을 진행하겠습니다.
아두이노에 온도센서를 연결한 후 스케치에서 그 값을 thingSpeak에서
제공하는 open API를 이용하여 와이파이 쉴드로 thingSpeak으로 보냅니다.
그러면 위와 같이 thingSpeak의 자신의 채널에서 자동으로 값에 대한 그래프를 실시간으로 그려줍니다.

미리보기 동영상

 

 

부품목록

NO 부품명 수량 상세설명
1 오렌지 보드 1  
2 브레드 보드 1  
3 온도 센서 1  termistor 10K를 사용했습니다.
4 330 ohm 저항 1  
5 와이파이 쉴드 1 WizFi250-EVB를 사용했습니다.
6 점퍼 케이블 3  

 

부품명 오렌지 보드 브레드 보드 온도 센서 330 ohm 저항 점퍼 케이블
사진 x1 x1 x1 x1 x3

 

 

부품명 와이파이 쉴드
사진 X1

 

하드웨어 Making

회로도

브레드 보드 레이아웃

소프트웨어 Coding

아래의 스케치를 업로드 하세요.
 

/*
 본 스케치는 http://webofthink.tistory.com/category/Web_App_Development (온도센서 측정)과
 WizFI250 라이브러리 예제를 응용하여 만든 스케치입니다.
*/

#include <Arduino.h>
#include <SPI.h>
#include <IPAddress.h>
#include "WizFi250.h"                 //WizFi250 라이브러리를 설치   
#include "WizFi250_tcp_client.h"
#include <avr/pgmspace.h>             //PROGMEM 지시자를 사용하기 위한 라이브러리

#define APIKEY "자신의 채널 API KEY를 입력하세요."   //thingSpeak 자신의 채널 API KEY

#define SSID	"와이파이 이름을 입력하세요."
#define KEY	"비밀번호를 입력하세요."
#define AUTH	""   //WEP 방식 경우 입력

#define  REMOTE_PORT    80
#define  LOCAL_PORT     5004

#define THERM_PIN   0

int sensorValue = 0;

//만약 충돌이 나시면 네트워크 설정을 참고하시고 바꿔주세요.
IPAddress ip		(192,168,4,1);
IPAddress destIP	(64,94,18,120);
IPAddress gateway	(192,168,4,1);
IPAddress mask		(255,255,255,0);

char server[] = "api.thingspeak.com";
unsigned long lastConnectionTime = 0;               //마지막 연결 시간
const unsigned long postingInterval = 10*1000;      //upload 간격
boolean Wifi_setup = false;
boolean lastConnected = false;
boolean isFirst = true;

WizFi250 		wizfi250;
WizFi250_TCP_Client	myClient(server, REMOTE_PORT);     //서버 연결

//플래시 메모리의 온도 값 저장
const int temps[] PROGMEM = { 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
    15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
	34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 68, 
	69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 
	87, 88, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 
	102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 
	115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 126, 127, 
	128, 129, 130, 131, 132, 133, 134, 134, 135, 136, 137, 138, 139, 140, 
	141, 142, 143, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 
	153, 154, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 164, 165, 
	166, 167, 167, 168, 169, 170, 171, 172, 173, 174, 175, 175, 176, 177, 
	178, 179, 180, 181, 182, 182, 183, 184, 185, 186, 187, 188, 189, 190, 
	190, 191, 192, 193, 194, 195, 196, 197, 197, 198, 199, 200, 201, 202, 
	203, 204, 205, 205, 206, 207, 208, 209, 210, 211, 212, 212, 213, 214, 
	215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 225, 226, 227, 
	228, 228, 229, 230, 231, 232, 233, 234, 235, 235, 236, 237, 238, 239, 
	240, 241, 242, 243, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 
	252, 253, 254, 255, 256, 257, 258, 259, 260, 260, 261, 262, 263, 264, 
	265, 266, 267, 268, 269, 269, 270, 271, 272, 273, 274, 275, 276, 277, 
	278, 279, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 289, 
	290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 301, 302, 
	303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 315, 
	316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 
	330, 331, 332, 333, 334, 335, 335, 336, 337, 338, 339, 340, 341, 342, 
	343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 
	357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 
	371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 
	385, 386, 387, 388, 389, 390, 392, 393, 394, 395, 396, 397, 398, 399, 
	400, 401, 402, 403, 404, 405, 406, 407, 408, 410, 411, 412, 413, 414, 
	415, 416, 417, 418, 419, 420, 422, 423, 424, 425, 426, 427, 428, 429, 
	430, 432, 433, 434, 435, 436, 437, 438, 439, 441, 442, 443, 444, 445, 
	446, 448, 449, 450, 451, 452, 453, 455, 456, 457, 458, 459, 460, 462, 
	463, 464, 465, 466, 468, 469, 470, 471, 472, 474, 475, 476, 477, 479, 
	480, 481, 482, 484, 485, 486, 487, 489, 490, 491, 492, 494, 495, 496, 
	498, 499, 500, 501, 503, 504, 505, 507, 508, 509, 511, 512, 513, 515, 
	516, 517, 519, 520, 521, 523, 524, 525, 527, 528, 530, 531, 532, 534, 
	535, 537, 538, 539, 541, 542, 544, 545, 547, 548, 550, 551, 552, 554, 
	555, 557, 558, 560, 561, 563, 564, 566, 567, 569, 570, 572, 574, 575, 
	577, 578, 580, 581, 583, 585, 586, 588, 589, 591, 593, 594, 596, 598, 
	599, 601, 603, 604, 606, 608, 609, 611, 613, 614, 616, 618, 620, 621, 
	623, 625, 627, 628, 630, 632, 634, 636, 638, 639, 641, 643, 645, 647, 
	649, 651, 653, 654, 656, 658, 660, 662, 664, 666, 668, 670, 672, 674, 
	676, 678, 680, 683, 685, 687, 689, 691, 693, 695, 697, 700, 702, 704, 
	706, 708, 711, 713, 715, 718, 720, 722, 725, 727, 729, 732, 734, 737, 
	739, 741, 744, 746, 749, 752, 754, 757, 759, 762, 764, 767, 770, 773, 
	775, 778, 781, 784, 786, 789, 792, 795, 798, 801, 804, 807, 810, 813, 
	816, 819, 822, 825, 829, 832, 835, 838, 842, 845, 848, 852, 855, 859, 
	862, 866, 869, 873, 877, 881, 884, 888, 892, 896, 900, 904, 908, 912, 
	916, 920, 925, 929, 933, 938, 942, 947, 952, 956, 961, 966, 971, 976, 
	981, 986, 991, 997, 1002, 1007, 1013, 1019, 1024, 1030, 1036, 1042, 
	1049, 1055, 1061, 1068, 1075, 1082, 1088, 1096, 1103, 1110, 1118, 1126, 
	1134, 1142, 1150, 1159, 1168, 1177, 1186, 1196, 1206, 1216, 1226, 1237, 
	1248, 1260, 1272, 1284, 1297, 1310, 1324, 1338, 1353, 1369, 1385, 1402, 
	1420, 1439, 1459, 1480, 1502 
};

void setup()
{

	pinMode(13, OUTPUT);
        Serial.begin(19200);
	Serial.println("\r\nSerial Init");

        //wizfi250 초기화 
	wizfi250.begin();
	wizfi250.setDebugPrint(4);
	wizfi250.hw_reset();

	wizfi250.sync();
	wizfi250.setDhcp();

	for(int i=0; i<10; i++)		// Try to join 30 times
        {
          if( wizfi250.join(SSID,KEY,AUTH) == RET_OK )
          {
            Wifi_setup = true;
            break;
          }
        }
}

void loop()
{
  int therm;   
  therm = analogRead(THERM_PIN) - 238;     //값 측정
  therm = pgm_read_word(&temps[therm]);    //실제 온도 값으로 변환
  
  float temp = (float)therm / 10.0;        //inf ->  float
  char buffer[10];                         //float를 string으로 변환하기 위한 임시 char 배열 선언 
  dtostrf(temp, 4, 1, buffer);             //float -> char로 변환 
  String temper = (String)buffer;          //최종 온도값(문자열)
  delay(3000);
  
  String dataString = "field1=" + temper;  //서버로 보낼 데이터
  
   if( Wifi_setup )
	{
		wizfi250.RcvPacket();

		if( myClient.available() )
		{
			char c = myClient.recv();
			if( c != NULL)
				Serial.print(c);
		}
		else
		{            
			if( !myClient.getIsConnected() && lastConnected )
			{
				Serial.println();
				Serial.println("disconnecting.");
				myClient.stop();
			}
                        
                        //보낸 후 일정기간이 지난 상태라면
			if(!myClient.getIsConnected() && (millis() - lastConnectionTime > postingInterval))
			{
				sendData(dataString);    //데이터 보내기
			}

			lastConnected = myClient.getIsConnected();    //최근 연결상태 업그레이드
		}
	}
}

//http 프로토콜에 맞춰서 데이터 만들어서 보내기 함수
void sendData(String thisData)
{
  String TxData;

  if(myClient.connect() == RET_OK)  // RET_OK
  {
     Serial.println("connecting..");

     TxData += "POST /update HTTP/1.1\n";     //post 방식
     TxData += "Host: api.thingspeak.com\n";
     TxData += "Connection: close\n";
     TxData += "X-THINGSPEAKAPIKEY: ";
     TxData += APIKEY;
     TxData += "\n";
     TxData += "Content-Type: application/x-www-form-urlencoded\n";
     TxData += "Content-Length: ";
     TxData += thisData.length();
     TxData += "\n\n";
     TxData += thisData;

     myClient.send((String)TxData);       //최종 데이터 보내기
 
     lastConnectionTime = millis();       //보냈을 때 시간 저장
   }
}
  

소프트웨어 및 하드웨어 설명

- 채널 형성하기


맨 처음에 가입을 하신 후 채널을 생성해야 합니다.
상단 메뉴에 channel의 my channel을 선택하셔서 들어갑니다.
그 후 new channel을 클릭하시면 됩니다. 
더 자세한 사항이 궁금하신 분은 다음 링크를 참조하세요.

소프트웨어 설명

#include "WizFi250.h"                 //WizFi250 라이브러리를 설치   
#include "WizFi250_tcp_client.h"
#include <avr/pgmspace.h>             //PROGMEM 지시자를 사용하기 위한 라이브러리


WizFi250을 쉴드를 사용한다면 다음 라이브러리를 다운로드해서 설치해야 합니다.
<avr/pgmspace.h>는 아두이노 플래시메모리에 값을 저장하기 위해 사용하는 라이브러리입니다.
기본 내장 라이브러리 이므로 그냥 입력만 하시면 됩니다.

 

 

#define APIKEY "자신의 채널 API KEY를 입력하세요."   //thingSpeak 자신의 채널 API KEY

#define SSID	"와이파이 이름을 입력하세요."
#define KEY	"비밀번호를 입력하세요."
#define AUTH	""   //WEP 방식 경우 입력

 

 



API KEY는 자기 채널로 들어가신 후 탭 중 API Keys를 선택하신 후 윗 사진에서 복사하라고 한 부분을
복사한 후 붙여넣으시면 됩니다.
 
//플래시 메모리의 온도 값 저장
const int temps[] PROGMEM = { 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 

..........

  int therm;   
  therm = analogRead(THERM_PIN) - 238;     //값 측정
  therm = pgm_read_word(&temps[therm]);    //실제 온도 값으로 변환
  
  float temp = (float)therm / 10.0;        //inf ->  float
  char buffer[10];                         //float를 string으로 변환하기 위한 임시 char 배열 선언 
  dtostrf(temp, 4, 1, buffer);             //float -> char로 변환 
  String temper = (String)buffer;          //최종 온도값(문자열)
  delay(3000);


위 코드는 값을 측정하고 변환하는 부분에 대한 코드를 모아놓은 것입니다.
먼저 센서로 측정된 값을 읽어온 후 값을 변환합니다. 
pgm_read_word함수는 앞에 플래시 메모리에 저장된 값을 읽어오는 함수 입니다.
읽어온 값을 실수형으로 바꾸고 데이터를 보내기 위해서는 문자열 이여야 하므로 문자열로 변환합니다.

 

 

  String dataString = "field1=" + temper;  //서버로 보낼 데이터

 

 

그래프로 표현 할 데이터가 여러 개일 경우 각 필드와 값을 보낼 데이터 문자열로 만들어 줍니다.


참고로 필드는 그래프의 y 축 중에 하나로 채널에서 채널세팅 탭에 가셔서 이름을 수정하실 수 있습니다.
 
                        //보낸 후 일정기간이 지난 상태라면
			if(!myClient.getIsConnected() && (millis() - lastConnectionTime > postingInterval))
			{
				sendData(dataString);    //데이터 보내기
			}

			lastConnected = myClient.getIsConnected();    //최근 연결상태 업그레이드
		}

만약 데이터를 1분마다 보내고 싶다면 처음 postingInterval에 60*000의 값을 저장합니다.
그리고 데이터를 보내기 전에 현재 시각을 측정한 후 마지막 연결시간을 뺀 차가 postingInterval보다 크다면
즉 1분이 지났다면 값을 보냅니다.
 
     TxData += "POST /update HTTP/1.1\n";     //post 방식
     TxData += "Host: api.thingspeak.com\n";
     TxData += "Connection: close\n";
     TxData += "X-THINGSPEAKAPIKEY: ";
     TxData += APIKEY;
     TxData += "\n";
     TxData += "Content-Type: application/x-www-form-urlencoded\n";
     TxData += "Content-Length: ";
     TxData += thisData.length();
     TxData += "\n\n";
     TxData += thisData;

     myClient.send((String)TxData);       //최종 데이터 보내기
 
     lastConnectionTime = millis();       //보냈을 때 시간 저장

위 코드는 http프로토콜과 thingspeak에서 제공하는 http post형식에 맞춰서 데이터를 만든 후 
데이터를 보내는 부분입니다.
 
위는 thingspeak에서 제공하는 post형식 입니다.
더 자세하게 알고 싶은 분은 다음 링크를 클릭하세요.

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!

tingspeak API, 온도센서, 아두이노, 오렌지보드