ESP8266とBME280で温度・湿度・気圧を測定、Ambientで表示

測定データをAmbientで公開しています。
https://ambidata.io/ch/channel.html?id=10090

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58417/ca4d8872-f9c1-9de7-4881-6220eca2f2e2.png)

過去に書いた記事ではプログラムについて書いていなかったのでこちらに書いておこうと思います。

##参照
プログラムについては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](https://ambidata.io/) のサービスをESP8266から使うには、ライブラリを追加する必要があります。Githubから[Ambient_ESP8266_lib](https://github.com/AmbientDataInc/Ambient_ESP8266_lib)をZip形式でダウンロードし、Arduino IDEのライブラリに追加しておきます。

##アルゴリズム
測定装置は電池駆動です。なるべく電池を長持ちさせたかったので、Deep Sleep ModeとRTCメモリーを使っています。（単四電池４本で４０日間運用できました。）Deep Sleep Modeは、ESP8266の省電力モードで一定時間間隔でリセットをかけるようになっています。RTCメモリーは、スリープ中もデータを保持しているメモリーです。

「ESP8266 RTCMemory」
https://qiita.com/UchiwaFuujinn/items/c8db045c48dc3ebd0b24

「ESP8266 RTC memoryを使う」
https://qiita.com/UchiwaFuujinn/items/9eda65654e5587c6377a

本プログラムでは、ESP8266は10分に１回立ち上がり、BME280の測定が実行されます。Ambientへデータをアップするのは１時間に１回としています。

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へ移行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58417/ee6845b1-d40a-0e3b-a6af-dfe9b5d5c7e9.png)

## プログラム

プログラムはGithubに置いておきます。
https://github.com/UchiwaFuujinn/ESP8266


``` bme280_ambient.ino
#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;
  }    
}
```