測定データをAmbientで公開しています。
https://ambidata.io/ch/channel.html?id=10090
過去に書いた記事ではプログラムについて書いていなかったのでこちらに書いておこうと思います。
##参照
プログラムについてはAmbientサイトの以下を参考にさせていただきました。
「Arduino ESP8266で温度・湿度を測定し、Ambientに送ってグラフ化する」
https://ambidata.io/docs/esp8266/
ハードウェアについては以下をご参照下さい。
「ESP8266にBME280 をつないで温度、湿度、気圧測定」
https://qiita.com/UchiwaFuujinn/items/c4369460d181dfe10ab8
Arduino IDEを使った開発環境については以下をご参照下さい。
「ESP8266 Arduino 開発環境」
https://qiita.com/UchiwaFuujinn/items/96ce018777a3ffe78353
##準備
Ambient のサービスをESP8266から使うには、ライブラリを追加する必要があります。GithubからAmbient_ESP8266_libをZip形式でダウンロードし、Arduino IDEのライブラリに追加しておきます。
##アルゴリズム
測定装置は電池駆動です。なるべく電池を長持ちさせたかったので、Deep Sleep ModeとRTCメモリーを使っています。(単四電池4本で40日間運用できました。)Deep Sleep Modeは、ESP8266の省電力モードで一定時間間隔でリセットをかけるようになっています。RTCメモリーは、スリープ中もデータを保持しているメモリーです。
「ESP8266 RTCMemory」
https://qiita.com/UchiwaFuujinn/items/c8db045c48dc3ebd0b24
「ESP8266 RTC memoryを使う」
https://qiita.com/UchiwaFuujinn/items/9eda65654e5587c6377a
本プログラムでは、ESP8266は10分に1回立ち上がり、BME280の測定が実行されます。Ambientへデータをアップするのは1時間に1回としています。
Setupではまず、RTCメモリを読み込みます。RTCメモリには何回立ち上がったかを示すカウンター(Count)、温度、湿度、気圧を平均するためのレジスタ(temp_sum,hum_sum,press_sum)が保存されています。RTCメモリがintegerのレジスタですので、測定値を100倍して保存しています。
次の、BME280から温度、湿度、気圧の現在値(temp_act,hum_act,press_act)を読み込みます。読み込んだ値は、平均するためのレジスタに加算されます。
Count を Decrements し、もしゼロならAmbientへデータを転送します。判定はゼロ以下で行っています。一番最初に立ち上がった時、RTCメモリーの状態が不定だとまずいと思ってこのようになっています。Ambientへの転送後、Countとレジスタをクリアします。
最後にレジスタをRTCメモリに保存し、Deep Sleep Modeへ移行します。
プログラム
プログラムはGithubに置いておきます。
https://github.com/UchiwaFuujinn/ESP8266
#include <ESP8266WiFi.h>
#include "Ambient.h"
/* ---------------------------------------- */
/* for RTC Memory */
/* ---------------------------------------- */
extern "C"{
#include "user_interface.h"
}
typedef struct{
int data1;
int data2;
} rtcStore;
rtcStore rtcMem;
#define RTCMEMORYSTART 64
#define RTCMEMORYLEN 128
int rtcBuffer[RTCMEMORYLEN]={0};
/* ---------------------------------------- */
/* for BME280 */
/* ---------------------------------------- */
#define BME280_ADDRESS 0x76
#define SENDCOUNT 6
double temp_act = 0.0, press_act = 0.0,hum_act=0.0;
extern void initBME280();
extern void readBME280(double *temp_act, double *press_act, double *hum_act);
/* ---------------------------------------- */
/* Wifi */
/* ---------------------------------------- */
const char *ssid = "XXXXXXX-X-XXXX";
const char *password = "YYYYYYYYYYYY";
WiFiClient client;
/* ---------------------------------------- */
/* Ambient */
/* ---------------------------------------- */
unsigned int channelId = 99999;
const char* writeKey = "12345678901234567890";
Ambient ambient;
/* ---------------------------------------- */
/* Setup */
/* ---------------------------------------- */
void setup()
{
/* ---------------------------------------- */
/* RTC Read */
readRTCdata();
int count = rtcBuffer[0];
int sendfrag=0;
double temp_sum =(double)rtcBuffer[1]/100.;
double press_sum=(double)rtcBuffer[2]/100.;
double hum_sum =(double)rtcBuffer[3]/100.;
/* ---------------------------------------- */
/* Read Data from BME280 */
readBME280(&temp_act, &press_act, &hum_act);
temp_sum = temp_sum + temp_act;
press_sum = press_sum + press_act;
hum_sum = hum_sum + hum_act;
/* ---------------------------------------- */
/* send Data to Ambient */
count=count-1;
if(count<=0){
sendfrag = 1;
}
if(sendfrag){
openWifi();
openAmbient();
temp_act =temp_sum/SENDCOUNT;
press_act =press_sum/SENDCOUNT;
hum_act =hum_sum/SENDCOUNT;
sendBME280();
count = SENDCOUNT;
temp_sum = 0.;
press_sum = 0.;
hum_sum = 0.;
}
/* ---------------------------------------- */
/* RTC Write */
rtcBuffer[0] = count;
rtcBuffer[1] = (int)(temp_sum*100.);
rtcBuffer[2] = (int)(press_sum*100.);
rtcBuffer[3] = (int)(hum_sum*100.);
readRTCdata();
/* ---------------------------------------- */
/* RTC Sleep */
ESP.deepSleep(10*60e6); //10minitus
delay(100);
}
void loop()
{
}
void openWifi()
{
/* ---------------------------------------- */
/* Wifi */
int i = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
if(i>100){
ESP.deepSleep(10*60e6); //10minitus
delay(100);
}
}
}
void openAmbient()
{
/* ---------------------------------------- */
/* Ambient */
int irtn =false;
int i=0;
while(irtn!=true){
irtn = ambient.begin(channelId, writeKey, &client);
delay(100);
i++;
if(i>100){
ESP.deepSleep(10*60e6); //10minitus
delay(100);
}
}
}
void sendBME280()
{
ambient.set(1, temp_act);
ambient.set(2, hum_act);
ambient.set(3, press_act);
ambient.send();
}
void writeRTCdata()
{
int buckets = sizeof(rtcStore)/sizeof(int);
int i, rtcPos;
for(i=0; i<RTCMEMORYLEN/buckets; i++){
rtcPos = RTCMEMORYSTART+i*buckets;
rtcMem.data1 = rtcBuffer[i*buckets];
rtcMem.data2 = rtcBuffer[i*buckets+1];
system_rtc_mem_write(rtcPos,&rtcMem,buckets*4);
}
}
void readRTCdata()
{
int buckets = sizeof(rtcStore)/sizeof(int);
int i, rtcPos;
for(i=0; i<RTCMEMORYLEN/buckets; i++){
rtcPos = RTCMEMORYSTART+i*buckets;
system_rtc_mem_write(rtcPos,&rtcMem,sizeof(rtcStore));
rtcBuffer[i*buckets] = rtcMem.data1;
rtcBuffer[i*buckets+1] = rtcMem.data2;
}
}