知的好奇心 for IoT

IoT関連の知的好奇心を探求するブログです

ThingSpeakのArduinoライブラリを使ったデータの送信方法

以前、BlynkのWebHookを使ってThingSpeakにデータを送る方法の記事を書きましたが、ThingSpeakにはArduinoライブラリが用意されているので、今回は素直にライブラリを使ってみたいと思います。

 

ハードウェア

Machinistにデータを送る記事と同じものを使いました。

簡単に説明すると、使ったパーツはこれです。

配線はこんな感じです。

f:id:IntellectualCuriosity:20191002163452p:plain

 

ソフトウェア

ライブラリ

肝心のThingSpeakのArduinoライブラリはこれです。

f:id:IntellectualCuriosity:20191002202948p:plain

このライブラリを使うとThingSpeak.setField([フィールド番号], [値])でデータをセットした後、ThingSpeak.writeFields([チャネル], [書き込み用APIキー])を実行することで簡単にデータをThingSpeakに送ることができます。

他にはBME280用のAdafruitのライブラリを2つ使ってます。

f:id:IntellectualCuriosity:20191002170925p:plain

f:id:IntellectualCuriosity:20191002171352p:plain

スケッチ

スケッチはMachinistにデータを送るのに使ったプログラムのデータを送信するファンクションだけを入れ替えています。該当部分のコードが37行から16行と半分以下になっているほか、JSONデータを作る必要もなく簡単さを実感できます。

/*
 * BME280 sensor program for ThingSpeak using ESP8266
 * October 02, 2019
 * By Hiroyuki ITO
 * https://intellectualcuriosity.hatenablog.com/  
 * MIT Licensed.
 */
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <Adafruit_BME280.h>
#include <ThingSpeak.h>

#define DS_INTERVAL         1 // Deep Sleep Interval Time (minutes)
#define WIFI_SSID           "YourNetworkName"
#define WIFI_PASS           "YourPassword"
#define THING_SPEAK_CHANNEL YourChannelID
#define THING_SPEAK_API_KEY "YourWriteAPIKey"
#define VCC_PIN             13 // Sensor VCC Pin

// Global Objects
Adafruit_BME280 bme; // I2C
String temperature;
String humidity;
String pressure;

/*
 * Get Sensor Data
 */
void GetSensorData() {
  // Sensor Power ON
  pinMode(VCC_PIN, OUTPUT);      
  digitalWrite(VCC_PIN, HIGH);

  // Initialize BME280
  delay(10);
  bme.begin(0x76); // SDO GND(Open):0x76 VDD:0x77

  // Sensor Measurement
  temperature = String(bme.readTemperature(), 1); // xx.xC
  humidity = String(bme.readHumidity(), 1);       // xx.x%
  pressure = String(bme.readPressure()/100.0, 0); // xxxxhPa
  Serial.println("Temperature:" + temperature);
  Serial.println("Humidity   :" + humidity);
  Serial.println("Pressure   :" + pressure);

  // Sensor Power OFF
  digitalWrite(VCC_PIN, LOW);
}

/*
 * Send Sensor Data
 */
void SendSensorData() {
  // Initialize ThingSpeak
  WiFiClient client;
  ThingSpeak.begin(client);

  // Set the fields with the values
  ThingSpeak.setField(1, temperature.toFloat());
  ThingSpeak.setField(2, humidity.toFloat());
  ThingSpeak.setField(3, pressure.toInt());

  // Write to the ThingSpeak channel
  int res = ThingSpeak.writeFields(THING_SPEAK_CHANNEL, THING_SPEAK_API_KEY);
  if (res == 200) {
    Serial.println("Channel update successful.");
  } else{
    Serial.println(String("Problem updating channel. HTTP error code ") + res);
  }
}

void setup() {
  Serial.begin(74880);

  // Connect to WiFi
  Serial.print("Connecting to " WIFI_SSID);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);     
    Serial.print(".");
  } 
  Serial.println("\nWiFi connected");

  GetSensorData();
  SendSensorData();

  // Go to deep sleep
  delay(1000);
  Serial.println(String("Go to sleep for ") + DS_INTERVAL + " minutes");
  ESP.deepSleep(DS_INTERVAL*60*1000*1000, WAKE_RF_DEFAULT);
}

void loop() {
}

 

ThingSpeakからデータを読み出す

Machinistはデータを書き込むことしかできませんが、ThingSpeakにはデータを読み出すAPIも用意されています。

PCでこのブログを見ている方は右側のサイドバーにベランダや部屋の温湿度などが表示されていることに気付いたかも知れないですね。サイドバーの表示はThingSpeakのAPIを利用して表示しているんです。

f:id:IntellectualCuriosity:20190921204815p:plain

チャンネルの「API Keys」タブに表示されている「Read API Key」と「Channel ID」があれば、次のようなJavaScriptでデータを表示することができます。

<div id="bme280_time">時刻取得中...</div>
<div id="bme280_temperature">温度取得中...</div>
<div id="bme280_humidity">湿度取得中...</div>
<div id="bme280_pressure">気圧取得中...</div>

<script type="text/javascript">// <![CDATA[
getBME280Data();

var ret_interval_getBME280Data = setInterval(getBME280Data, 60000); // Millisecond

function visibilityChangeHandlerGetBME280Data() {
  if (document.hidden) {
    clearInterval(ret_interval_getBME280Data);
  } else {
    location.reload(false);
  }
}
document.addEventListener('visibilitychange', visibilityChangeHandlerGetBME280Data, false);

function getBME280Data() {
  var readAPIKey = "YourReadAPIKey"; // ThingSpeak Read API Key
  var channelID  = "YourChannelID";  // ThingSpeak Channel ID
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        var json = JSON.parse(this.responseText);
	      var t = parseFloat(json.feeds[0].field1);
	      var h = parseFloat(json.feeds[0].field2);
	      var p = parseFloat(json.feeds[0].field3);
	      var dt = new Date(json.feeds[0].created_at);
	      var str = dt.toLocaleString();
        document.getElementById("bme280_temperature").innerHTML = "  温度:" + t.toFixed(1) + "℃";
        document.getElementById("bme280_humidity").innerHTML    = "  湿度:" + h.toFixed(1) + "%";
        document.getElementById("bme280_pressure").innerHTML    = "  気圧:" + p.toFixed(0) + "hPa";
        document.getElementById("bme280_time").innerHTML = str.slice(0,-3) + "現在";
      }
    }
  }
  xhr.open("GET", "https://api.thingspeak.com/channels/" + channelID + "/feeds.json?api_key=" + readAPIKey + "&results=1", true);
  xhr.send();
}
// ]]></script>

このスクリプトを実行すると、次のような表示でデータが1分毎に更新されます。

f:id:IntellectualCuriosity:20191002213224p:plain

データを取り出す用途がある場合はThingSpeakがいいですね。

 

おしまい