編集履歴一覧に戻る
Fukaのアイコン画像

Fuka が 2026年01月31日22時16分51秒 に編集

内容追記

本文の変更

## はじめに 1月も終わりに差し掛かってきたところではありますが、まだまだ寒い日が続きます。 温度を見ながら暖房をつけることが多いと思いますが、その際に現在の温度だけでなく、直前の温度変化がどのように変わっているのかも見れたらよいだろうと感じました。 そこで、今回は SPRESENSEを使って簡易温度モニターを作成してみました。 液晶を使用して温度の表示を行うだけでなく、直前の履歴をグラフ化することで温度の変化量を確認できるように工夫しました。 ## 使用するもの 今回の製作では以下の部品を使用しました。 | 部品 | 数量 | |:---:|:---| | Spresense メインボード | 1 | | Spresense 拡張ボード | 1 | | 温度センサ(DHT11) | 1 | | 液晶モジュール | 1 | | 配線類 | 適宜 | | 筐体(自作) | 1 | Spresense メインボード、Spresense 拡張ボードについては機材提供をしていただきました。ありがとうございます。 その他、センサ、ディスプレイについては市販品のものを使用。 筐体については3Dをプリンタを使用して製作を行いました。 ## 配線と接続について SPRESENSEボードに対してディスプレイとセンサを接続していきます。 それぞれの接続先は以下のとおりです。 ### 液晶の接続 | 液晶ピン番号 | SPRESENNSE側ピン番号 | |:---:|:---| | GND | GND | | VCC | 3.3V | | SCL | D13 | | SDA | D11 | | RES | D8 | | DC | D9 | | CS | D10 | | BLK | 3.3V | ### 温度センサの接続 | DHT11側ピン | SPRESENSE側ピン | |:---:|:---| | DATA | D5 | | VCC | 3.3V | | GND | GND | ## ソースコード プログラムコードは以下のようになります。 ```arduino:SPRESENSE #include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_ST7789.h> #include <DHT.h> #define COLOR_GRAY 0x8410 // RGB565 グレー /* ===== ピン定義 ===== */ #define TFT_CS 10 #define TFT_DC 9 #define TFT_RST 8 #define DHT_PIN 5 #define DHT_TYPE DHT11 /* ===== オブジェクト ===== */ Adafruit_ST7789 tft(TFT_CS, TFT_DC, TFT_RST); DHT dht(DHT_PIN, DHT_TYPE); /* ===== 設定 ===== */ #define HISTORY_SIZE 5 float tempHistory[HISTORY_SIZE]; int historyIndex = 0; unsigned long lastMeasure = 0; const unsigned long interval = 300000; // (1分なら60000) static float lastValidTemp = NAN; /* ===== ディスプレイ描画 ===== */ void drawHeader(float temp) { tft.fillRect(0, 0, 240, 40, ST77XX_BLACK); tft.setTextColor(ST77XX_WHITE); tft.setTextSize(2); tft.setCursor(8, 8); tft.print("ONDO : "); tft.setTextSize(3); tft.setCursor(150, 5); if (temp > -90) { tft.print(temp, 1); tft.print("C"); } else { tft.print("--.-C"); } tft.drawFastHLine(0, 39, 240, COLOR_GRAY); // 区切り線 } void drawGraph() { const int graphX = 40; const int graphY = 235; const int graphW = 195; const int graphH = 190; // === min / max 自動算出 === float minT = 1000.0; float maxT = -1000.0; int valid = 0; for (int i = 0; i < HISTORY_SIZE; i++) { if (!isnan(tempHistory[i])) { minT = min(minT, tempHistory[i]); maxT = max(maxT, tempHistory[i]); valid++; } } if (valid < 2) { minT = 20; maxT = 30; } float margin = max(1.0, (maxT - minT) * 0.2); minT -= margin; maxT += margin; // グラフエリアクリア なるべく大きく tft.fillRect(0, 40, 240, 200, ST77XX_BLACK); // 枠 tft.drawRect(graphX, graphY - graphH, graphW, graphH, ST77XX_WHITE); // === Y軸(温度)=== tft.setTextSize(1); for (int i = 0; i <= 6; i++) { float t = minT + (maxT - minT) * i / 6.0; int y = graphY - (graphH * i / 6); tft.drawFastHLine(graphX - 5, y, 5, ST77XX_WHITE); tft.drawFastHLine(graphX, y, graphW, COLOR_GRAY); tft.setCursor(2, y - 4); tft.print(t, 1); } // === データ描画 === int prevX = -1, prevY = -1; for (int i = 0; i < HISTORY_SIZE; i++) { int idx = (historyIndex + i) % HISTORY_SIZE; float temp = tempHistory[idx]; if (isnan(temp)) continue; int x = graphX + i * (graphW / (HISTORY_SIZE - 1)); int y = graphY - map(temp * 100, minT * 100, maxT * 100, 0, graphH); tft.fillCircle(x, y, 4, ST77XX_RED); if (prevX >= 0) { tft.drawLine(prevX, prevY, x, y, ST77XX_RED); } prevX = x; prevY = y; } } /* ===== init ===== */ void setup() { Serial.begin(115200); delay(500); dht.begin(); delay(2000); // DHT安定動作のおまじない tft.init(240, 240); tft.setRotation(3); // ディスプレイの表示向き tft.fillScreen(ST77XX_BLACK); // 履歴初期化 for (int i = 0; i < HISTORY_SIZE; i++) { tempHistory[i] = NAN; } drawHeader(-99); drawGraph(); } /* ===== メインループ ===== */ void loop() { unsigned long now = millis(); if (now - lastMeasure < interval) return; lastMeasure = now; float temp = dht.readTemperature(); if (!isnan(temp)) { lastValidTemp = temp; } if (isnan(lastValidTemp)) return; Serial.print("Temp: "); Serial.print(lastValidTemp); Serial.println(" C"); tempHistory[historyIndex] = lastValidTemp; historyIndex = (historyIndex + 1) % HISTORY_SIZE; drawHeader(lastValidTemp); drawGraph(); } ``` 計測した値をディスプレイに表示しつつ、直近の温度変化をグラフとして表示するようにしています。 ## 製作時の様子 ブレッドボードで動作確認をした後、すべての部品を内部に収められるつくりとしまた。 ↓筐体印刷時の画面 ![3Dプリンタでの製作過程](https://camo.elchika.com/784e8183d775c0ea4fd9e57e4e6ab27203b69291/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33313639316266322d353532392d343163372d383035302d6631303634653461393532652f34303336313065382d666232622d343763352d393164642d313161376461326465643931/) ↓部品全体の様子

-

![キャプションを入力できま](https://camo.elchika.com/5390293cde209aa821d22f26058112f29b6f0ca4/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33313639316266322d353532392d343163372d383035302d6631303634653461393532652f35333237386164622d303062652d346238662d396334652d616235316564656130666666/)

+

![使用る部品](https://camo.elchika.com/5390293cde209aa821d22f26058112f29b6f0ca4/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33313639316266322d353532392d343163372d383035302d6631303634653461393532652f35333237386164622d303062652d346238662d396334652d616235316564656130666666/)

↓部品をすべて入れたところ ![内部に部品を入れたところ](https://camo.elchika.com/24c1c97a32a16a37090686659d0e5f40f7b7c77f/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33313639316266322d353532392d343163372d383035302d6631303634653461393532652f30393833333932392d376664362d343563362d383366362d386662373931653834326437/) ## 出来上がったもの 最終的に出来上がったものは写真のとおりです。 現在の温度と過去の温度変化を赤線で示して可視化を行いました。 また、別途持っている温度計を比較してみたところ、測定温度は近似値であり普段使いでは問題ないことも確認ができました。 ![比較](https://camo.elchika.com/1c204769f24dcdf2a83923e4b9a1ad3bb7549248/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33313639316266322d353532392d343163372d383035302d6631303634653461393532652f63653165663564362d376234332d343239612d383636632d323065613563386632653233/) ## まとめ 今回はSpresenseを使用して”温度”という状態の可視化を行いました。 他にも様々なセンサを使用することで身の回りの情報を可視化、生活を豊かにできる工夫があると思うので、いろいろ試していきたいと感じました。