ラズベリーパイで温度制御を極めたい
文章が下手すぎるのでチャッピー(神)に文章校正してもらいました(笑)
概要
温度計 DS18B20 で温度を取得し、ラズベリーパイの GPIO ピンからソリッドステートリレー(SSR)を ON / OFF して加熱を制御するシステムです。
PID制御に頼らず、できるだけ汎用的に温度制御できるプログラム を目指しました。
「人が常に温度の変化を予測しながら、加熱出力を微調整していく」そんなイメージの制御方式です。
もともとは、蒸気で大きな庫内を温める際、PID制御では安定させるのが難しい ため、
「ラズベリーパイで何とか温度制御できないか」と依頼されて開発を始めたものです。
約2か月、電気ケトルとにらめっこしながら試行錯誤を重ね、ようやく形になりました。


主な仕様
プログラムを起動するとGUIが立ち上がります(仕事で使ってるので詳細は伏せます)
CSVファイルから工程読み込み

経過秒数と温度とセンサー番号を指定したcsvファイルを読み込ませます

グラフにSVがプロットされ、スタートボタンを押すことで温調が開始します

これは温泉卵を作ったときのグラフ
温度が上がるほど必要な出力は増え、逆に、同じ温度でも加熱対象が温まってくるほど必要な出力は減っていきます。
このように条件によって加熱特性が変化するため、係数が固定された PID 制御では柔軟な対応が難しい のです。
さらに、蒸気加熱の場合は バルブの開度によって加熱力そのものが変わる ため、状況に応じた柔軟な制御が必要になります。
仕組み
粘土をこねるように試行錯誤しながら作ったため、「どんな技術を使っているのか」といった説明はできませんが、仕組みの大まかな部分ならお話しできます。
温度予測
プログラムは常に N秒後(ここでは30秒) の温度を予測しながら加熱をコントロールします。
これは、加熱を開始してから実際に温度が変化として現れるまでに、それくらいの タイムラグ があるためです。
- 50%出力 → 30秒後 → 温度が上がり始める
この遅れが、温度制御を非常に難しくする要因となっています。
目標温度に到達してから加熱を止めていては、温度が大きく オーバーシュート してしまいます。
そのため、プログラムでは「出力に対して何℃上昇したか」をリアルタイムに計算し、これを 加熱力(℃/min) として扱っています。
ただし、この加熱力はあくまで概算であり、冷却による損失分は含まれていません。
また、加熱力は出力が高いほど正確になる傾向があるため、過去に観測された 最大の加熱力 を基準として利用します。
さらに、予測が オーバーシュート気味 のときは +10%、逆に 加熱が追いついていない ときは -10% といったように、リアルタイムで補正を加えることで、算出の精度を高めています。
温度予測は、過去30秒間の温度変化(傾斜)から 60秒後の温度 を推定し、その値と60秒後のSV値との差を算出します。
そして、その温度差を埋めるために必要な出力を、先ほどの加熱力を使って計算しています。
これは人間が温度予測しながらつまみを調整する感覚を再現したものです。
出力
出力は 10 秒サイクルで制御していて、たとえば出力 50% なら「10 秒のうち 5 秒だけ加熱する」という動きになります。
この方式のおかげで、電磁弁を使った蒸気加熱でも、電気ケトルのような電気加熱でも、状況に合わせて柔軟に加熱できるようになっています。
保温制御
温度差による出力制御では、SVとPVが一致すると温度差がゼロとなり、出力もゼロになります。
すると、冷却によって出力が増える → オーバーシュートして出力が止まる というサイクルを繰り返し、温度がいつまでも波打ってしまいます。
そこで登場するのが、この保温制御です。
この仕組みこそが本システムの真骨頂であり、ハンチング(過剰な上下振動)を極限まで抑える ために設計されています。
具体的には、過去数分間の平均出力を「保温出力」として記録し、
PV(現在温度)がSV(目標温度)より低いときには、その値を下回らないよう出力を維持する という制御を行います。
これも、人間が今までの流れを保ちつつ+αで微調整する感覚をプログラムにしたようなイメージです。
これは、メモリに余裕のあるラズベリーパイだからこそ実現できる方式です。

1500Wの電気ケトル+間欠加熱では、どうしても小刻みなブレは出てしまいます。
更なる安定を目指して
昨日は、急激な温度上昇から保温モードになるときに、温度予測がオーバーシュートして急ブレーキが掛かる問題をどうにかしようと試行錯誤してました。
蒸気加熱の場合、この20秒程度の停止で、温度が急落してしまいます。
人間だったら温度がオーバーしそうだからと突然出力をゼロにはしないですよね。
そこで30秒前の出力の半分以下にはしないという処理を追加してみました。

ドヤァ。ってくらいに精度が増しました。
副次的な効果ですが、通常の温度制御の精度も増しています。
チャッピー(神)にグラフを貼って評価してもらいました

べた褒め頂きました🎉(ハルシネーションとか言わないで)
ならば出力を30秒前より10%以上上がらないようにしたらどうなるか試してみたところ

ダメダメな結果になりました
これは、強加熱のあとに出力が 0% になり、温度が下がり始めると 10% → 20% → 30% …と再び出力が増えていき、また強加熱でブレーキが掛かる──という悪循環が起きている状態です。
80℃→95℃の温度上昇は驚くほど綺麗なんですけどね
初期の頃
4年前の今頃、悪戦苦闘しながら作っていたときのグラフです

最大加熱力のログを取ってリアルタイムに調整する──この方法自体は初期の頃から使っていたのですが、温度差が開かないと調整が掛からない仕組みだったので、次第に加熱が追いつかなくなって……そのあたりで頭を悩ませていたんですよね。
その後、実際の現場で動かしてみたときも、相手が“蒸気”という魔物だけにまったく歯が立たず、「これはさすがに無理なんじゃないか…」と思ったくらいです。
蒸気が出ているときと止まっているときとで温度が数℃も乱高下して、制御どころではありませんでした。
そこで思いついたのが、保温出力 というアイデアです。
試運転のときと実践投入のときの精度があまりに違いすぎて、「結果を改ざんしてるんじゃないか?」と疑われたほどでした。
その後も、セッティング次第で乱高下を抑えられる方法を見つけたりと、改良を重ねることで、最終的には 0.1℃ 精度 で制御できるところまで仕上げました。
目標
最終的には、加熱する量が違っても、外気温が変わっても、さらには熱源そのものが違っても、同じ感覚で制御できる“万能”の制御プログラムに仕上げられたら理想ですね。
もちろん、人の動きを真似ている以上は限界はあると思いますが、それでもできるところまでは追求したいところです。
おわりに
丁寧な喋り方が──こそばゆい
最近のコメント