2020年2月25日火曜日

温室の温度をAmbientに投稿しつつ、時刻でLED照明を制御する(Ras Pi Zero⇔Arduino連動)

以前に温室の温度制御を追加したが、その温度データをリアルタイムでモニタリングしたくなった。
また、温度だけでなく日照不足も補うため、LED照明を追加した。
24時間点灯は植物の負担になるらしいので朝夕に手動でON/OFFしているが、
このON/OFFを自動化したい。(ときどき付け忘れるので…)

(↑こんな感じ 見た目はめちゃくちゃ怪しいけど、健全な草花なのでご安心を)


温度モニタリングと時間での照明ON/OFFを実現するため、
Raspberry Pi Zero WとArduino Nanoを連携させてシステムを構築した。

仕様は以下2つ。
・照明の12V電源を朝7時にON、夜19時にOFFする
・温室内の4点の温度をAmbient.ioに毎分送信する

先にAmbientの表示結果を載せる。
こんな風に4点がグラフ化できる。何か月分もさかのぼって見ることもできる優れもの。

環境検討

ESP32とかPi Zeroなら単独でもできないこともないが、
安いArduino Nano互換機を大量に持っているので2ボード構成を選択した。
わざわざ2つを繋ぐのは少しダサいけど、いくつかメリットもある。
ArduinoはAnalog INで直接読めるからLM35やLM61のような安い温度計測ICを使えるが、
Piから直接読めるセンサはお値段が高め。
ESP32はADCの誤差が大きい。また、ESP32自体がPi Zero Wより高い。
対して、Pi+Arduinoなら、Internet部分をPythonで簡単に書けるうえに安く作れる。
その代わり、PiとArduinoのSerial通信を書く必要がある。

簡単に表にまとめるとこんな感じ。
Arduino + PiPiのみESP32
主要部品Arduino Nano
Pi Zero W
LM61 *4
Pi Zero W
DS18B20 *4
ESP32
LM61 * 4
概算費用400円
1,320円
60円*4
1,960円

1,320円
320円*4
(2,540円)

2,200円
60円*4
(2,240円)
開発言語C/C++
Python
※ボード間通信有
PythonC/C++
(Nanoが互換品前提なので少しずるい気もする)

ソース

本日はソースの掲示のみ。
中身の説明とハードウェアは後日掲載します。

・Raspberry Pi
#! /usr/bin/python3
import serial as sl
import ambient
from datetime import datetime as dt

am = ambient.Ambient(<AmbientのID>, "<AmbientのKey>")

tim = dt.now()
count = 0
acc = [0.0, 0.0, 0.0, 0.0]

s = sl.Serial("/dev/ttyUSB0", 9600)
while True:
    try:
        txt = s.readline()
        ary = txt.decode().strip().split(" ")
        if len(ary) != 11:
            continue
        else:
            t = [float(x) for x in [ary[1], ary[4], ary[7], ary[10]]]
            count += 1
            for idx in range(4):
                acc[idx] += t[idx]

            if (dt.now() - tim).total_seconds() >= 60:
                t = [x / count for x in acc]
                count = 0
                acc = [0.0, 0.0, 0.0, 0.0]
                tim = dt.now()
                tmp = {'d1':t[0], 'd2':t[1], 'd3':t[2], 'd4':t[3]}
                am.send(tmp) ## Ambientへ送信

                # DC12VのON/OFF
                if 7 <= tim.hour and tim.hour <= 19:
                    s.write(b"t")
                else:
                    s.write(b"f")
    except Exception as e:
        print(e)

s.close()

・Arduino
void sendTemp();
bool serialFlag = false;
unsigned long tim = 0;
const unsigned char PWR = 3; // D3

void setup(){
  Serial.begin(9600);
  delay(20);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(PWR, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(PWR, HIGH);
}

void loop(){
  if(millis() - tim > 1000){
    sendTemp();
    tim = millis();
  }
}

void serialEvent(){
  while(Serial.available()){
    char c = Serial.read();
    switch(c){
      case 'T': case 't': // AC12V ON
        digitalWrite(LED_BUILTIN, HIGH);
        digitalWrite(PWR, HIGH);
        break;
      case 'F': case 'f': // AC12V OFF
        digitalWrite(LED_BUILTIN, LOW);
        digitalWrite(PWR, LOW);
        break;
      default:
        break;
    }
  }
}

void sendTemp(){
  float t[4];
  t[0] = analogRead(A7) * 500.0/1024 - 60;
  t[1] = analogRead(A6) * 500.0/1024 - 60;
  t[2] = analogRead(A5) * 500.0/1024 - 60;
  t[3] = analogRead(A4) * 500.0/1024 - 60;
  Serial.write("S0: ");
  Serial.print(t[0]);
  Serial.write(" / S1: ");
  Serial.print(t[1]);
  Serial.write(" / S2: ");
  Serial.print(t[2]);
  Serial.write(" / S3: ");
  Serial.println(t[3]);
}

以上。続きは後編へ。

0 件のコメント:

コメントを投稿