今回はこの保温器をスタンドアロンにします。現在WebのHPで行っている操作を止めて、下記の様な簡単な作業で保温出来ようにします。
- 電源を入れたらスタンバイ状態になる
- 缶内の温度と湿度を表示
- 保温温度を入力しボタンを押したらスタート
- ボタンをもう一度押したらストップ
必要部品
前回と重なる部分が多いですが、主な部品を挙げると
- ESP32(本体)
- 今回は、ESP32 Development Board WiFi+bluetoothを使用しました。
- USBケーブルを繋ぐだけでArduinoで開発出来ます。
- 以前使用したログを ここ にまとめています。参照下さい。
- AQM1248A(LCD表示器)
- I2C接続のLCD表示器です。解像度 48×128ドット。
- 以前使用したログを ここ にまとめています。参照下さい。
- AM2320(温湿度測定素子)
- 2C接続の温湿度測定素子です。缶内温湿度測定用。
- 以前使用したログを ここ にまとめています。参照下さい。
- ADT7410(温度測定素子)
- インターフェイスは、I2C。ヒーター温度測定用。
- 温度のみ測定出来るが測定範囲はAM2320より広い。( -55°C~+150°C)
- 以前使用したログが ここ に有ります。参照下さい。
- ソリッド・ステート・リレー(SSR)キット 25A(20A)タイプ
- ヒーターのオンオフに使用
- DIPロータリースイッチ 10ポジション 0~9 正論理
- 今回新たに追加した部品。これを2個使って保温温度を指定します。
- 秋月さんで売っているロータリースイッチです。
- その他
- ヒューズ
- コンセント
- 基板
- 配線コード
- ヘッダーピン
- など
回路と配線
- 保温器の側面に小さい棚を作り、そこに全てを乗せました
- 回路図の水色四角部分(SSR、ヒューズ、USB ADアダプター等)を棚の下に、それ以外は上に配置しています
- 缶内温湿度測定用にAM2320をヒーター温度測定用にADT7410を使用しています。
- AQM1248には、缶内の温度、湿度、経過時間(分)が表示されます。
- 操作は下記の要領、
- ACプラグをコンセントに接続。
- 棚の上のスイッチで電源ON。
- これで動作しますが、念の為にリセットスイッチを追加しています。
- AQM1248に温湿度が表示。
- ローターリースイッチで保温温度を設定します。
- Stat/Stopボタンを押すとパイロットLEDが点灯して保温開始。
- 動作時、ヒーターがオンの時にヒーターLEDが点灯。
- 表示は5秒に1回更新されます。
- 画面の PT:XXXX は経過時間です。開始からの経過時間を分で表示します。
- もう一度、Stat/Stopボタンを押すとパイロットLEDが消灯して保温終了。
プログラムの変更
WebのHP、RTC、SDカードへのデーターの保存を止めたので、プログラムは非常に簡単になりました。前回までのメインのプログラム、”Monitor_00.ino” を ”chamber_00.ino” と新しく書き直しています。
chamber_00.ino
#include "Arduino.h"
#include <Wire.h>
#include "AM2320.h"
#include "AQM1248A.h"
#include "ADT7410.h"
// External Interrupt
// Only use GPIO:0,2,4,12-15,25-27,32-39
// Start Stop Bottom
#define St_btn GPIO_NUM_27
// Pilot Lamp
#define Pilot_Lamp 12
// Power Control
#define Power_ctl 13
#define Power_Led 14
// Temp Data
#define dat_L1 35
#define dat_L2 39
#define dat_L4 34
#define dat_L8 36
#define dat_H1 26
#define dat_H2 33
#define dat_H4 25
#define dat_H8 32
// ADT7410_addr
#define ADT7410_addr 0x4b
int int_flg = 0;
int state_flg = 0;
float heat_tmp = 0;
int tm_cnt,past_time = 0;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer()
{
// Timer interrupt
portENTER_CRITICAL_ISR(&timerMux);
int_flg = 2;
}
void IRAM_ATTR Handle_st()
{
// Push Start / Stop Button
portENTER_CRITICAL_ISR(&timerMux);
int_flg = 1;
}
void setup()
{
Wire.begin();
SPI.begin();
Serial.begin(115200);
pinMode(Pilot_Lamp, OUTPUT);
digitalWrite(Pilot_Lamp,LOW);
pinMode(Power_ctl, OUTPUT);
digitalWrite(Power_ctl,LOW);
pinMode(Power_Led, OUTPUT);
digitalWrite(Power_Led,LOW);
pinMode(St_btn, INPUT_PULLUP);
pinMode(dat_L1, INPUT);
pinMode(dat_L2, INPUT);
pinMode(dat_L4, INPUT);
pinMode(dat_L8, INPUT);
pinMode(dat_H1, INPUT_PULLDOWN);
pinMode(dat_H2, INPUT_PULLDOWN);
pinMode(dat_H4, INPUT_PULLDOWN);
pinMode(dat_H8, INPUT_PULLDOWN);
attachInterrupt(St_btn, Handle_st, FALLING);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 5000000, true);
timerAlarmEnable(timer);
Init_LCD();
disp_temp();
}
void loop()
{
float ht_temp;
int a;
while(int_flg == 0) delay(10);
delay(500);
disp_temp();
switch(int_flg)
{
case 1: // Start or Stop
for(a = 0; a< 5; a++)
while(!digitalRead(St_btn)) delay(10);
delay(100);
a = HIGH;
if(state_flg) a = LOW;
else heat_tmp = get_target_temp() * 1.92 - 24.14;
digitalWrite(Power_ctl,a);
digitalWrite(Power_Led,a);
digitalWrite(Pilot_Lamp,a);
tm_cnt = past_time = 0;
state_flg = !state_flg;
portEXIT_CRITICAL_ISR(&timerMux);
break;
case 2: // Interrupt
if(state_flg)
{
ht_temp = ADT7410_get_temp(ADT7410_addr);
a = LOW;
if(ht_temp < heat_tmp) a = HIGH;
digitalWrite(Power_ctl,a);
digitalWrite(Power_Led,a);
}
portEXIT_CRITICAL_ISR(&timerMux);
break;
}
int_flg = 0;
}
int get_target_temp()
{
int a;
a = 0;
if(digitalRead(dat_H1)) a = 1;
if(digitalRead(dat_H2)) a += 2;
if(digitalRead(dat_H4)) a += 4;
if(digitalRead(dat_H8)) a += 8;
a *= 10;
if(digitalRead(dat_L1)) a += 1;
if(digitalRead(dat_L2)) a += 2;
if(digitalRead(dat_L4)) a += 4;
if(digitalRead(dat_L8)) a += 8;
return a;
}
void disp_temp()
{
char c_buf[50];
String buf;
float h_data[2];
LCD_CLS(0);
if(state_flg)
{
tm_cnt ++;
if(tm_cnt == 12) {tm_cnt = 0; past_time ++;}
}
AM2320(h_data);
buf = "T:" + String(h_data[1]) + "'c ";
buf.toCharArray(c_buf, 50);
LCD_Print_Str(0,0,c_buf,1,2);
buf = "H:" + String(h_data[0]) + "% ";
buf.toCharArray(c_buf, 50);
LCD_Print_Str(0,16,c_buf,1,2);
buf = "PT:" + String(past_time) ;
buf.toCharArray(c_buf, 50);
LCD_Print_Str(0,32,c_buf,1,2);
}
- 11行:#define St_btn GPIO_NUM_27
- Start/Stop用ボタンの割り込みに使用
- 14、17,18行:パイロットLED、SSR、ヒーターLED制御用端子
- 21から28行: 温度設定用ロータリースイッチ読み取り用端子
- 31行:ADT7410のI2Cアドレス。今回は、0X4B。
- 38,39、85−88行:タイマーの設定です。
- 今回はRTCを使わずESP32のタイマーで割り込みを行っています。
- Ⅴ. ESP32でのタイマー割り込みによる自動計測を参照しました。
- 割り込み時間を5秒に設定しています。
- これでデータの表示とヒーターの制御をしています。
- 41から46行:タイマー割り込みがかかるとここが実行される
- 48から53行:Start/Stopボタンが押されるとここが実行される
- 73から76行:温度設定用1の位読み取りポートの設定。
- これらのポートはInput専用でかつ、プルダウン無し。
- ハードで(抵抗を付けて)プルダウンしている
- 78から81行:温度設定用10の位読み取りポートの設定
- ソフトでプルダウンを設定
- 83行:Start/Stopボタン割り込み設定
- 103から136行: 割り込みの処理
- 105から121行:スタート、ストップの処理
- 123から134行:ヒーターの制御
- 142から159行:設定温度読み取り
- 161から188行:測定値の表示
その他、AM2320.cpp/.h、AQM1248A.cpp/.h、ADT7410.cpp/.h が必要です。これら全てまとめてここに保存して起きました ー> 今回のソフト
最後に
今回で最後です。面白い保温器が出来たと思います。納豆を作りたくて始めた今回ですが、保温器の製作に時間がかかり本来の納豆はまだ1回しか作っていません。