🌟

M5StackCore2 + ENV2センサユニット + Sqlite3でセンサーデータをデータベースに蓄積してみる

2024/09/08に公開

https://zenn.dev/akihiro_ya/articles/f1576cca66dae8

それでは、続けてSqlite3データーベースを導入する。

Sqlite3Esp32のインストール

ArduinoIDEでSqlite3Esp32をインストールする。
インストール

テーブル

必要なのは気温、湿度、気圧。適当に決める。

temperature(気温)テーブル

温度をINTEGER(整数)かREAL(浮動小数)にするか迷った。
sqlite3_bind_double か sqlite3_bind_intの違いで普通はREALを選ぶ。

測定値は整数部3桁と小数点以下3桁あればいいので、値の範囲は-999.999から999.999まで。
負の方向に999,999通りと正の方向に999,999通り、あと0。
999,999+999,999+1=1,999,999通りを表現できたらいいので、その情報量はlog_2(1,999,999)=20.93ビット。これくらいなら32ビット=4バイトで充分表現できる。
メモリが少ないので、REAL(8バイト=64ビット)はやめておこうかなって。

名前 データ型 制約 説明
id INTEGER 主キー
sensor_id INTEGER NOT NULL 制約 測定したセンサーID
location TEXT 測定した場所
at INTEGER NOT NULL 制約 測定したUNIX時間(time_t)
milli_degc INTEGER NOT NULL 制約 測定値(1/1000℃)

relative_humidity(相対湿度)テーブル

名前 データ型 制約 説明
id INTEGER 主キー
sensor_id INTEGER NOT NULL 制約 測定したセンサーID
location TEXT 測定した場所
at INTEGER NOT NULL 制約 測定したUNIX時間(time_t)
ppm_rh INTEGER NOT NULL 制約 測定値(1/1000 [%RH])

pressure(気圧)テーブル

名前 データ型 制約 説明
id INTEGER 主キー
sensor_id INTEGER NOT NULL 制約 測定したセンサーID
location TEXT 測定した場所
at INTEGER NOT NULL 制約 測定したUNIX時間(time_t)
pascal INTEGER NOT NULL 制約 測定値(Pa)

Arduinoスケッチ

前回のスケッチを改造してこうする。

このスケッチは長いのでたたんでおく

このスケッチをM5Core2に書込んで、測定値をSqlite3データーベースファイルをSDカードに保存する。

メインメモリーからPSRAMへ

M5StackCore2のSRAM領域は512kB。
それをSqlite3データベースに使わせると不足するので、Core2内蔵の疑似SRAM領域をSqlite3が使うようにsqlite3_configで設定する。

/*
 * sqlite3用
 */
const sqlite3_mem_methods DATABASE_CUSTOM_MEM_METHODS{
  /* メモリー割り当て関数 */
  .xMalloc = [](int size) -> void * {
    return heap_caps_aligned_alloc(8, size,
                                   MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
  },
  /* メモリー解放関数 */
  .xFree = heap_caps_free,
  /* メモリー再割り当て関数 */
  .xRealloc = [](void *ptr, int size) -> void * {
    return heap_caps_realloc(ptr, size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
  },
  /* 割り当てサイズを返す関数 */
  .xSize = [](void *ptr) -> int {
    return heap_caps_get_allocated_size(ptr);
  },
  /* 8の倍数に切り上げる関数 */
  .xRoundup = [](int size) -> int {
    return (size + 7) & ~7;
  },
  /* メモリー割り当て初期化 */
  .xInit = [](void *app_data) -> int {
    return 0;  // nothing to do
  },
  /* メモリー割り当て後片付け */
  .xShutdown = [](void *app_data) -> void {
    // nothing to do
  },
  /* xInit() と xShutdown()の引数 */
  .pAppData = nullptr,
};

Discussion