2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RaspberryPiでIHコンロを制御して低温調理器を作ってみた

Last updated at Posted at 2021-02-19

#はじめに
最近、低温調理をすることが多いのですが、温度計と見ながらIHコンロの火力調整を自力でやるのが面倒になってきました。
そこで、RaspberryPiに「温度センサ」と「サーボモータ」をつないでIHコンロの火力調整を自動化できるのではないかと思い、簡易的な低温調理器を実際に作ってみました。

#低温調理器の概要
低温調理の方法としては水を張った鍋を使用し、その鍋の中に低温調理する食材を入れておく。鍋の水温が調理温度を維持し続けられるようIHコンロの火力を調整する。
この制御をRaspberryPiに「温度センサ」と「サーボモータ」を接続することで実現する。
「温度センサ」と「サーボモータ」のそれぞれの役割は以下の通り。

  • 温度センサの役割 → 温度センサで水温を監視するために使用する。
  • サーボモータの役割 → サーボモータでIHコンロの火力を調整するために使用する。水温が低ければ火力を上げて、逆に水温が高ければ火力を下げる。
    全体像.jpg

#必要機材
必要機材については以下の通り。機材はインターネット通販や100均で機材は購入した。

  • IHコンロ
  • RaspberryPi2B
  • 温度センサ(型番:DS18B20 防水タイプ)→ インターネット通販で購入
  • サーボモータ(型番:SG90)→ インターネット通販で購入)
  • ブレッドボード → インターネット通販で購入
  • 抵抗(4.7kΩ)→ インターネット通販で購入
  • ジャンパーワイヤー(5本)→ インターネット通販で購入
  • 耐震マット → 100均で購入

#ソフトウェア
使用するソフトウェアは以下の通り。

#####RaspberryPi

  • RaspberryPi OS
  • Python

#####開発PC

  • Teraterm(RaspberryPiとのSSH接続で使用)

#機器の接続方法
RaspberryPiの端子と、それぞれの機器の接続イメージは以下の通り。
回路図.jpg
※抵抗は10kΩだと温度センサが正常動作しなかった。そのため4.7kΩを使用した
※温度センサは3.3Vに接続すること。自分は誤って5Vに接続して温度センサが壊れた

参考までに実際に機器を接続したときのブレッドボードの写真は以下の通り。
ブレッドボード.jpg

#実装内容
RaspberryPi上で実行するプログラム(低温調理プログラム)について説明する。
プログラミング言語は、温度センサ、サーボモータのどちらも手軽に制御できるPythonを使用する。

###温度センサの制御
温度センサ(DS18B20)との通信で1-wireを使用するため、事前にRaspberryPi OSの1-wire設定を有効化する必要がある。
/boot/config.txtをエディタで開き、下記の内容を追記する。

/boot/config.txt
dtoverlay=w1-gpio

###サーボモータの制御
サーボモータはPWMで制御する。パルス波のデューティー比を変化させることでサーボモータの回転角を制御する。なお、PWMは特に前準備をする必要なく使用することが可能である。
参考までにサーボモータの回転角をデューティー比に変換する式は以下の通り。

dutyCycle = 2.5 + (12.0 - 2.5) / 180 * (degree + 90)

※dutyCycleはデューティー比として設定する値、degreeは回転角

###低温調理プログラムの概要
低温調理プログラムの処理の流れを簡単に説明する。

1.サーボモータ、温度センサの初期化
2.調理時間の取得(Teratermからの入力待ち)
3.調理温度の取得(Teratermからの入力待ち)
4.調理温度になるまで水温監視
5.調理温度になったらサーボモータでIHコンロの火力を最小にする
6.水温を監視し、調理温度の±3℃の範囲を超えたらサーボモータで火力を調整する

###ソースコード
低温調理プログラムのソースコードは以下の通り。

low_temp_cooking.py
import os
import glob
import time
import subprocess

GPIO_PORT_SERVO = 12
PWM_FREQ_SERVO = 50
PUSH_LEFT_BUTTON = 45
PUSH_RIGHT_BUTTON = -45
RELEASE_BUTTON = 0
DEFAULT_IH_FIREPOWER = 5
TEMPERATURE_MARGIN = 2

def initServomotor():
    import RPi.GPIO as GPIO
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(GPIO_PORT_SERVO, GPIO.OUT)
    pwmInstance = GPIO.PWM(GPIO_PORT_SERVO, PWM_FREQ_SERVO)
    pwmInstance.start(0.0)
    return pwmInstance

def rotateServomotor(pwmInstance, degree):
    dutyCycle = 2.5 + (12.0 - 2.5) / 180 * (degree + 90)
    print(dutyCycle)
    pwmInstance.ChangeDutyCycle(dutyCycle)
    time.sleep(0.5)
    pwmInstance.ChangeDutyCycle(0.0)

def initOneWare():
    os.system('modprobe w1-gpio')
    os.system('modprobe w1-therm')

def getOneWareFilePath():
    baseDir = '/sys/bus/w1/devices/'
    deviceFolder = glob.glob(baseDir + '28*')[0]
    deviceFile = deviceFolder + '/w1_slave'
    return deviceFile

def readTempRaw(filePath):
    catData = subprocess.Popen(['cat',filePath], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    out,err = catData.communicate()
    outDecode = out.decode('utf-8')
    lines = outDecode.split('\n')
    return lines

def readTemp(filePath):
    lines = readTempRaw(filePath)
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = readTempRaw(filePath)
    equalsPos = lines[1].find('t=')
    if equalsPos != -1:
        tempString = lines[1][equalsPos + 2:]
        temp = float(tempString) / 1000.0
        return temp


# Main
# Initialize servomotor
pwmInstance = initServomotor()

# Initialize thermometer
initOneWare()
oneWareFilePath = getOneWareFilePath()

# Get the temperature
print("input Temperature (e.g. 60 - 80)")
targetTemperature = float(input())

# Get the Minutes
print("input Minutes (e.g. 30 - 120)")
endingTime = float(input()) * 60

# Get the Temperature
currentTemp = readTemp(oneWareFilePath)
print("currentTemp = %f, targetTemp = %f" % (currentTemp, targetTemperature))

# Heating phase
print("Heating phase")
while currentTemp < targetTemperature:
    currentTemp = readTemp(oneWareFilePath)
    print("currentTemp = %f" % (currentTemp))
    time.sleep(1.0)

for i in range(DEFAULT_IH_FIREPOWER - 1):
    rotateServomotor(pwmInstance, PUSH_LEFT_BUTTON)
    rotateServomotor(pwmInstance, RELEASE_BUTTON)

# Calculate low temperature cooking time
currentTime = time.time()
endingTime = endingTime + currentTime

# Insulation phase
print("Insulation phase")
while endingTime > currentTime:
    currentTemp = readTemp(oneWareFilePath)
    print("Temp = %f, Time = %f" % (currentTemp, (endingTime - currentTime)))
    if currentTemp < (targetTemperature - TEMPERATURE_MARGIN):
        rotateServomotor(pwmInstance, PUSH_RIGHT_BUTTON)
        rotateServomotor(pwmInstance, RELEASE_BUTTON)
        print("Push right button")
        time.sleep(30.0)
    elif currentTemp > (targetTemperature + TEMPERATURE_MARGIN):
        rotateServomotor(pwmInstance, PUSH_LEFT_BUTTON)
        rotateServomotor(pwmInstance, RELEASE_BUTTON)
        print("Push left button")
        time.sleep(30.0)
    time.sleep(1.0)
    currentTime = time.time()

print("Finished cooking")

#動作確認
以下の手順で動作確認を実施。

  1. Teratermから$ sudo python low_temp_cooking.pyを入力して低温調理プログラムを実行する。
  2. 温度や時間を聞かれるのでTeratermから値を入力する。今回は、調理温度64度、調理時間60分で動作確認を行う。
  3. IHコンロの電源を入れて調理開始(残念ながらここは手動。。。)
  4. 調理温度まで達するとサーボモータが動作し、IHコンロの温度調整が行われる。
  5. 低温調理開始から60分経過すると調理終了を示すログFinished cookingがTeratermに出力される。このタイミングでIHコンロの電源を切る。(残念ながらここも手動。。。)
    低温調理機.png

#まとめ
とりあえず、RaspberryPiで簡易的な低温調理器を作成することはできた。
サーボモータの固定方法には100均の耐震マットを使用した。しかし、耐震マットだとサーボモータを固定する力が弱く、IHコンロのスイッチを押せない場合があった。
サーボモータの固定方法は、もう少し考えたほうがよさそう。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?