プログラミングの芽

面白そうな技術を使って、楽しいことやりたい

ArduinoとPython間のシリアル通信によるDHT22を使った温度湿度リアルタイム表示

良いタイトルが思い浮かびませんね。
正直Matplotlibのグラフ表示練習みたいな感じでした。

準備

必要なもの

Arduino Uno
10kΩ抵抗
DHT22(AM2302)
ブレッドボード(必要ならユニバーサル基盤等)
※ジャンパワイヤ等は省略
記事内で使ってるやつ


回路(メモ程度)
f:id:atarms:20190213154932j:plain

Arduinoの必要ライブラリ

GitHub - adafruit/DHT-sensor-library: Arduino library for DHT11, DHT22, etc Temperature & Humidity Sensors
GitHub - adafruit/Adafruit_Sensor: Common sensor library
上記2つをArduinoのライブラリフォルダに入れてください。

以上で準備は終わりです。

ソースコード

Arduino

#include <DHT.h>

#define DHTTYPE DHT22
#define DHT22_PIN 7
DHT dht(DHT22_PIN, DHTTYPE);

void setup() {
  pinMode(DHT22_PIN, INPUT);      
  Serial.begin(9600);
}

char ch[4];
char ct[4];

void loop()
{
  float h  = dht.readHumidity() ;
  float t  = 5.0/9.0*(dht.readTemperature(true)-32.0); // fahrenheit -> celsius
  dtostrf(h, 3, 1, ch); //数列tを文字列(全3文字の小数点以下1文字)に変換してchに代入
  dtostrf(t, 3, 1, ct);
  if (isnan(h) || isnan(t)){
    return;
  }
  Serial.println(t);
  Serial.println(h);
  delay(1000);
}

Python

import numpy as np
import matplotlib.pyplot as plt
import serial

def main():
    ser = serial.Serial("COM4")  # COMポート(Arduino接続)
    temps = [0]*300
    humidities = [0]*300
    t = np.arange(0,300,1)
    h = np.arange(0,300,1)
    plt.ion()

    while True:
        temp = float(ser.readline().rstrip().decode(encoding='utf-8'))
        humidity = float(ser.readline().rstrip().decode(encoding='utf-8')) 
        # 温度データのリスト更新
        temps.pop(299) #299番目の要素を削除
        humidities.pop(299)
        temps.insert(0,float(temp)) #0番目にfloat型で要素を挿入
        humidities.insert(0,float(humidity))
        
        fig, ax1 = plt.subplots()
        ax1.plot(t, temps, "r-", label="Temperature[C]")
        ax2 = ax1.twinx()
        ax2.plot(h, humidities, "b-", label="Humidity[%]")
        
        plt.title("AM2302-M.Value")
        ax1.set_xlabel("Time [s]")
        ax1.set_ylabel("Temperature [Celsius]")
        ax2.set_ylabel("Humidity [Percent]")
        
        h1, l1 = ax1.get_legend_handles_labels()
        h2, l2 = ax2.get_legend_handles_labels()
        ax1.legend(h1+h2, l1+l2, loc='upper right')
        
        plt.grid()
        plt.xlim([1, 300]) #5分
        ax1.set_ylim([0, 40])
        ax2.set_ylim([0, 100])
        
        plt.pause(.01)

if __name__ == '__main__':
    main()

実行結果(GIF)

https://i.gyazo.com/5e38f08ec81fd76ba94f116d24e4cacc.gif
1秒間隔で更新されます。
盛り上がってるところは口でハーってやりました。湿度も温度も上がっているので正常に動いてそうですね。
それにしても湿度が低い・・・。
Pythonでデータの読み書きができれば後は煮るなり焼くなりって感じです。

次やりたい事

サーボモータ(具体的にはSG90)を2つ使って、物体を自動追尾するWebカメラArduinoで作りたいなと考えています。
最初はRaspberryPiでやろうと考えていたのですが、処理速度とSSH接続等の手間を考えて辞めました。
今回やったシリアル通信で、サーボモータの制御だけをArduinoにやらせようかなと。