概要
ネットワーク時計のロギング先をAmbientに変更したソフト変更編です。H/Wは全く変わっておりません。前回データーロガーとして、ネットワークを経由してGoogleSheetsにデーターを書き込んだのですが、無料のデータロギングのサービスを探して『Ambient』を発見しました。
- 8ch
- 1ch当たり 8種のData、8個のチャート, 3000data/1日
- data保存期間 4ヶ月
というサービスです。8ch以上は有料。
当方の目的にピッタリなので、elchikaで『Ambient』を検索してみました。すると当方の書いた投稿『obniz + SensorTag + Ambientによる気象状況ロギング』(2021年5月)が見つかりました。
書いた本人がすっかり忘れていました。年をとると物忘れが激しくて、情けない・・・・・
構成
H/Wについては前回の投稿を見て下さい。
動作状況
Ambientの表示状況です。
10分間隔でロギングした結果です。AmbientではDataを送付すればグラフは簡単に作成できます。
プログラム
簡易timer割込み、Tickerを3個使用して、定期イベントを処理しています。
Ambient登録後、「チャネルID」と「ライトキー」を設定します。
ネットワーク時計Withデータロガー
// DvKit88watchAmbient
// ロギングはAmbientに行う
#include <Arduino.h>
#include <MD_MAX72xx.h>
#include <MD_Parola.h>
#include <SPI.h>
#include <Ticker.h>
#include <WiFi.h>
#include <time.h>
#include <Wire.h>
#include <Adafruit_BME680.h>
#include <Ambient.h>
#define channelId XXXXX // 生成したAmbientチャネルID
#define writeKey "XX12345XX" // Ambient のライトキーをセット
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CLK_PIN 18 // or SCK = 18
#define DATA_PIN 23 // or MOSI = 23
#define CS_PIN 5 // or SS = 5
WiFiClient client;
MD_Parola P = MD_Parola(HARDWARE_TYPE,DATA_PIN,CLK_PIN, CS_PIN, MAX_DEVICES);
MD_MAX72XX dot = MD_MAX72XX(HARDWARE_TYPE, 25, 26, 27, 1); //秒表示用 Blue unit
Adafruit_BME680 bme;
Ambient ambient;
// wifiの設定
const char* ssid = "自分のWiFi SSID";
const char* password = "自分のWiFi パスワード";
#define JST 3600*9
const int oneSecond = 1000;
Ticker tkSec;
Ticker tkMin;
Ticker tkAmbient;
static uint16_t y = 0;
static uint8_t x = 0;
int seccount = 0;
String week[] = {"Sun","Mon","Teu","Wed","Thu","Fri","Sat"};
char szTime[9]; // mm:ss\n
char szMsg[35] = "";
char ledDate[10]; // mmddFri\n
char ledTime[9]; // mm:ss\n
char ledBME[50];
char ledMsg[80] = "";
void dotSecSet();
void minuteDisplay();
void initNTPTime();
void initBME680();
void waitZeroSec();
void getBME680();
void sendAmbient();
void setup() {
Serial.begin(115200);
delay(500) ;
P.begin();
P.setIntensity(0);
P.displayText(
"Waiting 0sec",
PA_LEFT, // 目的の場所 (PA_LEFT, PA_CENTER, PA_RIGHT)
100, // 指定ms毎にスクロールする
50000, // 目的の場所に来てから指定msだけ立ち止まる
PA_SCROLL_LEFT, // この効果を使って来る
PA_SCROLL_DOWN // この効果を使って帰る
);
P.displayAnimate();
initNTPTime();
initBME680();
getBME680();
dot.begin();
dot.control(MD_MAX72XX::INTENSITY,0);
waitZeroSec(); //00秒になるまで待つ
dot.clear();
dot.setPoint(0,0,true);
ambient.begin(channelId, writeKey, &client); // チャネルIDとライトキーを指定してAmbientの初期化
tkSec.attach_ms(oneSecond,dotSecSet); //timer割込みー>秒針表示
tkMin.attach_ms(oneSecond*60,minuteDisplay); //timer割込みー>分毎の表示
tkAmbient.attach_ms(600500,sendAmbient); //10分+500msec毎にAmbient書き込み
}
void loop() {
P.displayAnimate();
}
void initNTPTime(){
// WiFiを通して NTPサーバーと同期
WiFi.mode(WIFI_STA);
if (String(WiFi.SSID()) != String(ssid)) {
WiFi.begin(ssid, password);
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
configTime( JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
}
void initBME680(){
//+++++++++++++++ BME680 setup;
Wire.begin(21,22); //I2C SDA=21 SCL=22
if (!bme.begin()) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
while (1);
}
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
}
void waitZeroSec(){
struct tm localTime;
if (!getLocalTime(&localTime)) {
Serial.println("Failed to get the time");
}
while(localTime.tm_sec != 0){
delay(100);
getLocalTime(&localTime);
}
}
void dotSecSet(){
// Serial.println(seccount);
seccount ++;
if (seccount >=60){
seccount = 0;
dot.clear();
x=0;y=0;
dot.setPoint(0,0,true);
} else {
x ++;
if (x==8){
x=0;
y++;
}
dot.setPoint(x,y,true);
}
}
void minuteDisplay(){
struct tm t;
x=0;y=0;
dot.clear();
dot.setPoint(0,0,true);
getLocalTime(&t);
getBME680();
sprintf(ledDate,"%02d/%02d %s",t.tm_mon+1,t.tm_mday,week[t.tm_wday]);
sprintf(ledTime,"%02d:%02d",t.tm_hour,t.tm_min);
sprintf(ledMsg,"%s %s %s ",ledDate,ledBME,ledTime);
Serial.println(ledMsg);
// bug Fix 以下のコードでは 秒針の表示に遅れが発生する
// P.displayText(ledMsg,PA_LEFT,100,48000,PA_SCROLL_LEFT,PA_SCROLL_DOWN);
// こちらが正解
P.displayReset();
P.setTextBuffer(ledMsg);
}
void getBME680(){
if (! bme.performReading()) {
Serial.println("Failed read BME680");
return;
}
sprintf(ledBME,"%02.0fC %04ldhPa %02.0f%% %.0fkOhms ",bme.temperature,bme.pressure/100,bme.humidity,bme.gas_resistance/1000.0);
}
void sendAmbient(){
getBME680();
ambient.set(1,bme.temperature);
ambient.set(2,bme.humidity);
ambient.set(3,bme.pressure/100.0);
ambient.set(4,bme.gas_resistance/1000.0);
ambient.send();
Serial.println("Ambient send");
}
以下にライブラリー設定状況=PlatformIO.iniを記載します。
PlatformIO.ini
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
majicdesigns/MD_MAX72XX@^3.5.1
majicdesigns/MD_Parola@^3.7.3
adafruit/Adafruit BME680 Library@^2.0.4
ambientdatainc/Ambient ESP32 ESP8266 lib@^1.0.5
ambientのライブラリー設定は、PlatformIOの場合は、Library設定画面で『Ambient』で検索すると山のように出てきますので、『ambientdatainc』で検索するのが良いかと思います。
感想
- Ambient
登録も設定も非常に簡単。なんでこれを忘れていたのか!!
気象条件のロギングには最適のサービスかと思います。
前回のGooglesheetsとは応用範囲が異なります。
今後の課題
前回の課題と同じですが、再度記載します。
- LED表示フォント
日本人なら曜日は”月火水木金・・・”としたい。
温度=℃、kOhms=kΩ としたい。ツールはあるので作って組み込むだけなのだが・・・ - ネットワーク環境がない場合の対応
ネットワークが無いと何も出来ない時計になってしまったので、デモなどで外に持ち出すと動作できない。アクセスポイントモードでESP32を立ち上げ、スマホなどから時刻合わせを出来るようにしたい。 - ESP-Nowによる他の部屋のモニタリング
いっぱい使っていないESP32があるので、各部屋に設置してモニタリングとデータロギングをしたい。今のネットワーク時計がセンターマシンとなる。冬の北海道は換気のモニタリングと水道凍結対策のモニタリングが重要なので、どちらも臨界値を超えたらアラームを出すようにしたい。
投稿者の人気記事
-
HakoHiro
さんが
2024/06/11
に
編集
をしました。
(メッセージ: 初版)
-
HakoHiro
さんが
2024/06/20
に
編集
をしました。
(メッセージ: ソースコード Bug Fix)
ログインしてコメントを投稿する