드론 고도 유지용 기압센서로 알려진 BMP 180 센서에 의해 온도 및 압력 값을 측정해 보기로 하자. 측정된 기압 값을 고도(Altitude)로 환산하는 공식이 있으나 정확도를 믿기 어려우므로 단지 대기의 온도와 대기압 값을 측정해서 일차적으로 시리얼 모니터에서 관찰하고 이차적으로 WiFi 기능을 활용하여 Thingspeak 사이트에 2개의 그래프를 작성하기로 한다.
이미 블로그에서 Cactus Micro WiFi 예제를 제공하면서 ThingSpeak.com 사이트 활용을 위한 준비가 이루졌다면 즉각 본 프로그램의 데모가 가능할 것이다.
만약 Thingspeak이 무엇인지 이해가 가지 않으면 반드지 이전에 제시된 예제들을 확인하기 바란다.
BMP 180 센서는 3V3 전원 및 GND 와 아울러 I2C 인터페이스에 의해 센서 데이터를 읽어 들인다. I2C 인터페이스를 이용하는 센서들의 경우는 발매 시에 자체 고유의 헥사 형태의 주소가 할당되어 있다. 이는 BMP 180 뿐만 아니라 드론에서 흔히 사용되는 지자기장 센서 HMC5883L의 경우도 마찬가지라 할 것이며 서로 중복이 되지 않도록 설정이 되어 있다.
아두이노의 I2C 인터페이스는 보드에 SDA 및 SCL 핀이 이미 지정되어 있어 이들을 사용해도 되며 또는 일반적으로 아날로그 데이터 핀 A4와 A5로 대체해 사용해도 무방하다. 이 정보는 아두이노 우노 보드 사용에 있어서 알고 있어야 기본적인 상식에 해당한다.
그렇다면 Cactus Micro 보드를 사용할 경우는 어떻게 대처할 것인가 알아보기로 한다. Cactus Micro 보드의 핀 배치를 참조해 보면 아두이노 우노처럼 아날로그 데이터 핀 A4와 A5가 아예 없으며 그냥 숫자로 0에서 21번 까지 번호가 매겨져 있다. 따라서 제대로 배선을 하기 위해서는 핀 배치 다이아 그램 참조가 필수적이다.
다이아그램에 따르면 2번 및 3번에 해당하는 핀들이 SDA 와 SCL 임을 알 수 있다.
BMP 180센서는 3.3V를 사용하므로 Vcc와 GND를 사용하여 배선한다. 필자의 경험에 의하면 RAW에 외부의 휴대용 소형 리튬이온 폴리머 배터리 전원 3.7V 내지는 4.2V를 공급하면 3.3V가 나옴을 이미 확인하였다.
#include <SoftwareSerial.h>
#include <espduino.h>
#include <rest.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
위 프로그램에서 SoftwareSerial.h는 아두이노 Cactus Micro가 BMP 180 센서와 RX 및 TX 통신을 위한 일종의 UART를 설정하는 역할을 하며 프로그램 내에서 11번 및 12번 핀을 설정하게 될 것이다. 참고로 핀 다이아 그램에서 11번,12번 및 13번 핀을 볼 수 없는데 이는 내부에서 결선되어 사용됨을 의미한다. 특히 13번 핀은 소프트웨어적으로 내부에서 항상 High 상태를 잡아 주어야 Enable 상태가 된다.
espduino.h와 rest.h는 Cactus Micro의 WiFi 기능을 지원하기 위해 필수적인 라이브러리이다.
Wire.h는 I2C 인터페이스를 사용하는 프로그램에 반드시 설치되어야 한다. 그밖에 Adafruit_Sensor.h와 Adafruit_BMP085_U.h 라이브러리는 시리 모니터 창까지 데모를 보여주는 인터넷 예제들에서 흔히 발견할 수 있는 필수 라이브러리이다. 이 Adafruit 사의 라이브러리에 의해 제공되는 명령어를 사용하므로 인해서 지속적으로 갱신된 데이터들을 읽어 올 수 있다.
#define PIN_ENABLE_ESP 13
#define SSID "AndroidHotspot1234"
#define PASS "00000000"
// replace with your channel's thingspeak API key
String apiKey = "0XKP89L3Y0DTYESP";
위 프로그램에서 보면 자신의 스마트 폰 핫 스팟 ID와 비밀번호를 입력해야 한다. 아울러 Thingspeak 사이트의 API Write 키값을 반드시 입력해둔다. 예제의 값들은 임의의 값이므로 반드시 자신의 것들을 확인 입력하기 바란다.
Cac_thingspeak_barometer_03
/**
* \file
* ESP8266 RESTful Bridge example
* \author
* Tuan PM <tuanpm@live.com>
*/
#include <SoftwareSerial.h>
#include <espduino.h>
#include <rest.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#define PIN_ENABLE_ESP 13
#define SSID "AndroidHotspot1994"
#define PASS "00000000"
// replace with your channel's thingspeak API key
String apiKey = "0DKP99L3Z0DXYESP";
// For Cactus micro model, Use 11,12 for RX,TX
SoftwareSerial ser(11, 12); // RX, TX
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
void displaySensorDetails(void)
{
sensor_t sensor;
bmp.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" hPa");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" hPa");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" hPa");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
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");
/* Initialise the sensor */
if(!bmp.begin())
{
/* There was a problem detecting the BMP085 ... check your connections */
Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!");
while(1);
}
/* Display some basic information on this sensor */
displaySensorDetails();
}
void loop() {
char response[266];
esp.process();
sensors_event_t event;
bmp.getEvent(&event);
if(wifiConnected) {
if (event.pressure)
{
/* Display atmospheric pressue in hPa */
Serial.print("Pressure: ");
Serial.print(event.pressure);
Serial.println(" hPa");
float temperature;
bmp.getTemperature(&temperature);
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
Serial.print("Altitude: ");
Serial.print(bmp.pressureToAltitude(seaLevelPressure,
event.pressure));
Serial.println(" m");
Serial.println("");
// convert to float temp & float pressure
float temp = temperature;
float pressure= event.pressure;
char buff[64];
char strTemp[6];
char strPressure[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);
if(rest.getResponse(response, 266) == HTTP_STATUS_OK){
// Serial.println("ARDUINO: GET successful");
Serial.println(response);
}
delay(16000);
dtostrf(pressure, 4, 1, strPressure);
// Serial.println(buff);
sprintf(buff, "/update?api_key=0DKP99L3Z0DXYESP&field2=%s", strPressure);
rest.get((const char*)buff);
Serial.println(strPressure);
if(rest.getResponse(response, 266) == HTTP_STATUS_OK){
// Serial.println("ARDUINO: GET successful");
Serial.println(response);
}
delay(16000);
}
else {
Serial.print("error,\r\n");
}
}
}
시리얼 모니터를 보면 이상한 값들이 초기 데이터들로 출력되나 그 다음부터는 제대로 값이 나옴을 알 수 있다.
동시에 Thingspeak 사이트에 로그인하여 Channel Settings에서 2개의 field를 하나는 온도 다른 하나는 대기압으로 지정하고 반드시 저장한다.
다시 그래프로 돌아 와서 그래프 Y축 눈금 및 샘플 수를 지정한다.
2017년 2월 3일 저녁
실측 결과를 요약하자. 실내에서 바깥 주차장으로 이동하자 서서히 온도가 6.1도까지 하강했다. 압력은 그다지 변화가 없었다.
외부 주차장에서 엘리베이터를 이용 7층 건물 높이로 이동 후 실내 온도는 5도로 상승했으며 대기 압력은 실내나 바깥 주차장의 1014 hPa에서 1009.9 hPa로 하강했다.
다시 실내로 돌아 오자 온도 및 압력이 원 상태로 회복되었다.
이 실험에서 온도 센서는 알다시피 반응이 상당히 느린 편이나 그에 반하여 압력 센서는 훨씬 민감한 편이다.
압력 측정의 민감함을 측정하려면 이전 블로그 예제 중에서 NodeMCU웹서버와 실시간 그래픽스 프로그램을 사용하면 엘리베이터 상승에 따른 압력 변동을 기록할 수 있을 것이다. 아마도 이런 특성으로 인해 드론 호버링을 위한 센서로서의 역할이 가능할 것이다.
이 점에 관해서는 앞으로 실험이 이루어지면 블로그에 올리도록 할 예정이다.
'아두이노프로세싱 프로그래밍' 카테고리의 다른 글
아두이노NodeMCU에서 DHT11 센서 를 적용한 온습도 모니터링 II (0) | 2017.02.06 |
---|---|
아두이노 Adafruit DTH11 센서 vs 아두이노 Cactus Micro BMP180 온도 측정 벤치마킹 (0) | 2017.02.06 |
PixyMon프로그램에 의한 아두이노 비전센서 Pixy 및 Pan/Tilt 메카니즘 설치 I (0) | 2017.02.03 |
아두이노 RF 스프링 안테나 설치 (0) | 2017.02.02 |
단일 리튬이온 폴리머 배터리에 의한 포터블 아두이노 NodeMCU 보드 전원공급 (0) | 2017.01.31 |