DreamerDreamのブログ

夢想家の夢です。〜揚げたてのモヤっとしたものをラフレシアと共に〜

RaspberryPiと炊飯器で低温調理器を自作してみた⑫ 機器改造

前回、実際に調理をしてみましたが結果は散々でした。

dreamerdream.hateblo.jp

 

やはり、センサーの位置が悪そうです。

一応アルミテープやグラスウールで覆ってはいましたが、釜の底の一部の温度では正確な実際の水温は読めないですね。

正規の温度センサーは釜の周囲をぐるっと回って総合的に温度を取得しているようです。

テストは室内で行ない、実際の調理はもしもの火災を心配して屋外の風のよく通る場所で行なったのも要因なのかもしれません。

いろいろ反省点がありますが、温度センサーを防水加工して水に直づけすることにしました。

f:id:DreamerDream:20190918142350p:plain

 

何か防水出来る金属の筒のようなものは無いだろうかと探りましたら、発見!

油性マジックの本体!

溶剤すら通さないカンペキな防水!アルミなので熱伝導率も申し分無さそうです。 

f:id:DreamerDream:20190918223242p:plain

ペンの先を切り取って中身を綺麗に除去したらセンサーがピッタリ収まります。

f:id:DreamerDream:20190918223259p:plain

 

しかし中でセンサーが浮いていては反応が悪いので、CPU用の熱伝導グリスを注入してセンサーと入れ物の温度の反応を良くします。温度反応を良くするようにマーカーの塗装も一部削りました。

f:id:DreamerDream:20190919125811p:plain

パテでシーリングして完了!

何度かパテ埋めして見た目最悪だけどorz

f:id:DreamerDream:20190919125822p:plain

 

で、反応は温度計70℃のとき

f:id:DreamerDream:20190919125833p:plain

こちらも約70℃!!良さそうです!

f:id:DreamerDream:20190919125843p:plain



しかし、設定65.0℃なのに70℃ってのはやはり温度上がりすぎ。

グラフを見るとこんな感じ。

(ガタガタしているのは、温度計刺したりイロイロしたのがモロに出てしまっているようです)

f:id:DreamerDream:20190919130302p:plain


制御は単純に設定温度の一歩手前から反比例するようにタイミングを組んでいましたが制御はイマイチなようです。
ということで、次回はソフトウェアの改造です。

 

 

dreamerdream.hateblo.jp

 

RaspberryPiと炊飯器で低温調理器を自作してみた⑪ 鹿肉を低温調理してみた(失敗)

前回、うまく温度制御が出来ました。

dreamerdream.hateblo.jp

ですので早速実戦してみます。

 

※注意

鹿肉や猪肉などのジビエは元々野生栄物なので養殖と違って抗生物質や予防薬などの薬剤を投与されていません。ですので体内に寄生虫がいないとも限りません。

必ず一度冷凍させたものを使いましょう。

冷凍ではウイルス、菌は死滅しませんが、寄生虫は冷凍すると大概死滅するとされています。

通常、食肉用の塊に菌類は表面、消化管(ホルモン)に多く、筋肉内部には無菌とされていますがそれは食肉用の肉の切った直後の話で、天然物は特に注意が必用です。

有害な大腸菌は肉塊中心温度が75℃1分以上の過熱で死滅すると言われています。

二枚貝など、ノロウイルス汚染の可能性のあるものは85℃1分以上の過熱推奨)

それと同等の殺菌効果と言われているのが。

様々な資料を見た結果、

64.5℃では16分以上

63℃では30分以上

55℃では60分以上

というのが大まかな温度、今回は65℃を設定値としているので中心が65℃まで達するのに最低限30分以上の過熱は必要そうです。

肝炎ウイルスは70℃30分以上の過熱、98℃2分の過熱が推奨されています。

 

そして、低温調理の目安温度は50℃〜65.5℃

これは、お肉(筋肉)内部のタンパク質であるミオシンが変性するのが50℃以上アクチン(アクシン)が変性するのが65.5℃以上とされているからで、このアクチンが変性すると水分が抜けてボソボソになってしまうのです。

つまり、低温調理は筋肉繊維のミオシンのみ変性させる調理なのです。

 

ということで、安全に安全を期してアクチンの変性温度上限ギリギリの水温65℃到達後後から2時間半の調理をすることにします。

 

<参考>

https://www.fsc.go.jp/sonota/hazard/H21_19.pdf

https://www.fsc.go.jp/sonota/shokutyudoku_kanetu.pdf

63度30分と同等な加熱条件420パターン一覧

低温調理 63℃30分と同等の加熱温度と時間 | 減塩、低温調理はじめました。

http://kanpoken.pref.yamaguchi.lg.jp/jyoho/page5/syoudoku_4.html

 

鹿肉を味付けして軽く炙って投入!

f:id:DreamerDream:20190918133935p:plain

 

スイッチ入れて65℃で2時間温めてみます。

(実験の様子)

f:id:DreamerDream:20190918134042p:plain

 

お!グラフはイイ感じに65℃をキープしています。 

ここで判明したのですが、長時間温めるほど炊飯器自体の保温が効いて追加で温める必用が無くなるようです。

青色:水温

赤色:ヒーター過熱時間

f:id:DreamerDream:20190918132513p:plain



 
 が!!

途中水温を測ってみると68℃ですと???アクチンが変性するー!まあ表面だけなら大丈夫かぁ?

f:id:DreamerDream:20190918134053p:plain

おや?ラズパイは64℃を示しています。

誤差なのか?まあ誤差5℃程度までは良しとします。

f:id:DreamerDream:20190918134103p:plain

そのまま続けていると

 

 

え???

水温85℃です!これは完全にアウトです!

f:id:DreamerDream:20190918134119p:plain

ラズパイの温度は65℃を示しています。

f:id:DreamerDream:20190918134131p:plain

 

お湯から上げてしばらく経つ物の、お肉の中心温度はなんと83℃!!完全にアウトー!!

f:id:DreamerDream:20190918134142p:plain

Noooooo!!!

大失敗です。

 

しっかり中まで火が通っています。アクチンが変性して水分が抜けている状態です!

f:id:DreamerDream:20190918134153p:plain

これはこれで安全!

美味しかったんですけれど、目指しているものとは全く違います。

 

 

あ〜ん(泣)

おそらく、温度計の位置が悪いのでしょう。
分解して改造することにします。

 

dreamerdream.hateblo.jp

 

RaspberryPiと炊飯器で低温調理器を自作してみた⑩ 動作テスト

ひとまず完成しましたので動作実験を行ないます。

 

<使用プログラム一覧>

dreamerdream.hateblo.jp

 

 

まず、60℃で10分保温テストです。

過熱中、ディスプレイは43℃を示しています。

f:id:DreamerDream:20190918132943p:plain

赤外線温度計は約43℃!カンペキです!

f:id:DreamerDream:20190918132958p:plain

 

次に60℃のとき

f:id:DreamerDream:20190918133012p:plain

赤外線温度計も約60℃

f:id:DreamerDream:20190918133022p:plain

 

結果的に63℃を超えた辺で落ち着いてグラフのようになりました。
青い線が温度グラフ、赤い線がヒーターのON時間のグラフです。
f:id:DreamerDream:20190918132431p:plain
 

はてさて、この10分そこらの結果に大満足して早速お肉の準備をしたのが間違いでした・・・

次回、このシステムのまま実際に調理してみます。

 

dreamerdream.hateblo.jp

 

RaspberryPiと炊飯器で低温調理器を自作してみた⑨ 「ヒーター制御デーモン」

現在の温度を取得、設定温度と比較してヒーターの制御を行なう、実際に調理を行なうするための主要プログラムです。

f:id:DreamerDream:20190918164220p:plain


<heaterd.py>

 

#!/usr/bin/python2

import RPi.GPIO as GPIO
import time
import sys
import atexit
import file_mng as file
import datetime

heater = 17

set_heat_time = 10.0

#出力値をストック

stock_power =

#温度をストック
stock_temp =

#ストックするサイズ

size_list = 12

#10秒中、何秒ヒーターをONにするか
power_on = 10.0

#ログデータのファイル名

file_log = None

 

#ログデータ保存 

def save_log( now_temp, power_on ):
  global file_log
  if file_log is None:
    now = datetime.datetime.now()
    file_log = now.strftime("%Y%m%d-%H%M%S")
    file.log( file_log, now_temp, power_on )

 

#ヒーター出力ピン設定
def init():
  GPIO.setmode(GPIO.BCM)
  GPIO.setup(heater,GPIO.OUT)
  atexit.register(end)

#異常終了時にGPIOをリセット

def end():
  GPIO.cleanup()
  print "cleanup"

 

#ヒーターのON,OFF

def on():
  GPIO.output(heater,1)
def off():
  GPIO.output(heater,0)

 

#ヒーターをON、OFFにして指定時間待機
def heat( tim_on ):
  tim_off = set_heat_time - tim_on
  if 0.0 < tim_on:
    on()
    file.save_row_4('heating...' + str( tim_on ) +'sec' )
    time.sleep( tim_on )
  if 0.0 < tim_off:
    off()
    file.save_row_4('cooling...' + str( tim_off ) +'sec' )
    time.sleep( tim_off )

 

 

def main():
  global stock_power, stock_temp ,power_on

  #設定温度を読み出し

  set_temp = float( file.get_temp_set() )

  #温度制御開始は設定温度の半分に達してから
  start_temp = set_temp *0.5
  now_temp = file.load_temp()

  #現在温度を読み込む  

  try:
    now_temp = float(now_temp)
  except:

  #読み込み失敗したらストッカーの最新の温度で代用
    if 0 < len(stock_temp):
      now_temp = stock_temp[ len(stock_temp) -1 ]
    else:
      now_temp = 0.0

 

  #設定温度以上ならヒーターOFF 

  if set_temp <= now_temp:
    power_on = 0.0

 

  #制御開始温度以上であればヒーターON時間を計算する

  elif start_temp < now_temp :

    #温度に反比例するように制御(廃案)

    #wari = 1.0 - ( ( now_temp - start_temp ) / ( set_temp - start_temp ) )

    #sinカーブを利用して制御(採用)
    d = 90 * ( set_temp - now_temp ) / ( set_temp - start_temp )
    wari = math.sin( math.radians( d ) )


    if 0 < wari:

      power_on = set_heat_time * wari

      if size_list <= len(stock_temp):
        sum_temp = 0
        sum_power = 0
        count_heat = 0
        for i in range( 1, len(stock_temp) ):
          sum_temp = sum_temp + ( stock_temp[ i ] - stock_temp[ i -1 ] )
          sum_power = sum_power + stock_power[ i -1 ]
        avl_temp = sum_temp / ( len( stock_temp ) -1 )
        avl_power = sum_power / ( len( stock_power ) -1 )

        if avl_power > 0.0:
          #ターボモード、温度が勢いよく下がったらヒーター時間を長くする
          tarbo = ( avl_temp / avl_power )
          if tarbo < 0.0:
            power_on = power_on * ( 1 - tarbo *100 )

 

      #リレーの反応時間を考慮して細かすぎる制御は省く(最低0.5秒)
      if power_on < 0.5:
        power_on = 0.5
      if set_heat_time - 0.5 < power_on:
        power_on = set_heat_time

    else:
      power_on = 0.0

 

  #温度が制御開始温度以下ならヒーターを最高出力

  else:
    power_on = set_heat_time

 

  #ヒーター温度と制御時間を新しい情報にして保存
  stock_power.append( power_on ) 
  stock_power = stock_power[-size_list:]
  stock_temp.append( now_temp )
  stock_temp = stock_temp[-size_list:]

 

  heat( power_on )
  save_log( now_temp, power_on )


if __name__=='__main__':
  init()
  while True:

    #スタートファイルが存在していれば過熱開始
    if file.is_start():
      main()

    #スタートファイルが無ければスタンバイ
    else:
      time.sleep( 2 )
      file.save_row_4('standby...')
      file_log = None

 

<全プログラム内部構造一覧>

dreamerdream.hateblo.jp

 

RaspberryPiと炊飯器で低温調理器を自作してみた⑧ 「タイマーデーモン」

設定温度に達したらタイマーをスタート、カウントアップさせてディスプレイに表示させる。

f:id:DreamerDream:20190918164155p:plain

タイマーが設定時間を超えたらスタートファイルを削除する。

スタートファイルが削除されるので、ヒーターデーモンはヒーターの過熱を停止する。

 

<timerd.py>

 

#!/usr/bin/python
#coding:utf-8

import file_mng as file
import datetime
import time

tim_start = False

start_time = None

set_temp = 0.0
now_temp = 0.0

 

#桁「00」表示に揃える

def keta( num ):
  res = '0' + num
  return res[-2:]

#秒を「00:00:00」時間表示に変換

def get_view_time( sec ):
  sec = int( sec )
  hour = keta( str( sec / 3600 ) )
  min = keta( str( ( sec % 3600 ) / 60 ) )
  sec = keta( str( sec % 60 ) )
  return hour + ':' + min + ':' + sec

 

def main():
  global tim_start, start_time, set_temp, now_temp

  #スタートファイルがある場合
  if file.is_start():

    if tim_start:
      if start_time == None:
        str_time = file.load_start_time()
        start_time = datetime.datetime.strptime(str_time, "%Y/%m/%d %H:%M:%S")

       #現時刻とスタート時の時刻の差分を取得
        now = datetime.datetime.now()
        delta = now - start_time
        sec = delta.total_seconds()
        file.save_time( get_view_time( sec ) )
        set_time = float( file.get_time_set() )

        #設定時間をタイマーが超えたらスタートファイルを削除して終了
        if set_time <= sec/60 :
          file.save_row_0('Complete')
          file.stop()

    else:
      r_now_temp = file.load_temp()
      r_set_temp = file.get_temp_set()
      try:
        r_now_temp = float( r_now_temp )
        r_set_temp = float( r_set_temp )
        now_temp = r_now_temp
        set_temp = r_set_temp
      except:
        pass

      #設定温度に達したらスターとファイルを現日時に置き換えてタイマースタート
      if set_temp <= now_temp:
        tim_start = True
        now = datetime.datetime.now()
        now_str = now.strftime("%Y/%m/%d %H:%M:%S")
        file.start( now_str )
        file.save_row_0(now_str)

 

  #スタートファイルが無い場合
  else:
    tim_start = False
    start_time = None


if __name__=='__main__':
  while True:
    main()
    time.sleep(0.5)

<全プログラム内部構造一覧>

dreamerdream.hateblo.jp

 

RaspberryPiと炊飯器で低温調理器を自作してみた⑦ 「温度、タイマー設定デーモン」

設定ボタンによって温度とタイマーの設定を行なうデーモン

f:id:DreamerDream:20190918164113p:plain

物理ボタン操作で温度とタイマーの設定を変更するためのデーモン。

少しチャタリング対策に難があり、あまりスムーズに動かないorz。まあ、とりあえず動く。

このプログラムが無くても直書きでシステムの動作は可能。
  

<setting.py>

 

#!/usr/bin/python
#coding:utf-8

import RPi.GPIO as GPIO
import time
import os
import datetime
import file_mng as file

Sw_up = 27
Sw_dn = 22
Sw_select = 23

select = 'temp' # temp or time

 

#桁表示を「00」表示に整えるメソッド
def keta( num ):
  sum = '0' + num
  return sum[-2:]

 

#分を時間に直すメソッド

def review_time( tim ):
  tim = int( tim )
  hour = keta( str( tim / 60 ) )
  min = keta( str( tim % 60 ) )
  return hour + ':' + min + ':00'

 

#設定された項目をディスプレイに表示する

def view():
  file.save_row_1( ('> ' if select=='temp' else ' ') + 'SET TEMP: ' + file.get_temp_set() )
  file.save_row_2( ('> ' if select=='time' else ' ') + 'SET TIME: ' + review_time( file.get_time_set() ) )

 

#設定項目が温度の場合

def push_temp( val ):
  file.save_temp_set( str( int( file.get_temp_set() ) + val ) )

 

#設定項目が時間の場合

def push_time( val ):
  file.save_time_set( str( int( file.get_time_set() ) + val ) )

 

#「時間」「温度」切り換えボタン操作の場合

def change_select():
  global select
  if select == 'temp':
    select = 'time'
  else:
    select = 'temp' 

 

#スイッチが押された場合の処理

def switch(gpio_pin):

  time.sleep(0.5)

  if GPIO.input( gpio_pin ) == 0:

    if gpio_pin == Sw_up:
      if select == 'temp':
        push_temp( 5 )
      elif select == 'time':
        push_time( 10 )
    if gpio_pin == Sw_dn:
      if select == 'temp':
        push_temp( -5 )
      elif select == 'time':
        push_time( -10 )

    if gpio_pin == Sw_select:
      change_select()

    view()
    while GPIO.input( gpio_pin ) == 0:
      time.sleep( 0.1 )

 

#スイッチピンの設定プルアップで0V入力時にスイッチ操作
def standby():
  GPIO.setmode(GPIO.BCM)
  GPIO.setup(Sw_up, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  GPIO.add_event_detect(Sw_up, GPIO.FALLING)
  GPIO.setup(Sw_dn, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  GPIO.add_event_detect(Sw_dn, GPIO.FALLING)
  GPIO.setup(Sw_select, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  GPIO.add_event_detect(Sw_select, GPIO.FALLING)
  GPIO.add_event_callback(Sw_up, switch)
  GPIO.add_event_callback(Sw_dn, switch)
  GPIO.add_event_callback(Sw_select, switch)

  view()

  while True:
    time.sleep(60)

 

if __name__=='__main__':
  standby() 

<全プログラム内部構造一覧>

dreamerdream.hateblo.jp

 

RaspberryPiと炊飯器で低温調理器を自作してみた⑥ 「スタート/ストップデーモン」

スタートボタンが押されたら/dev/shm/領域にスタートファイルを生成、ファイルが存在している場合はスタートファイルを削除するデーモン

 

f:id:DreamerDream:20190918164030p:plain

スタートファイルに日時を保存する。

このスタートファイルが存在することを確認したら、ヒーター制御デーモンが指定温度になるようヒーターを制御します。

スタートファイルは、このデーモンの他にタイマーデーモンからも参照、追記、削除されます。

 

<start_stop_btnd.py>

 

#!/usr/bin/python
#coding:utf-8

import RPi.GPIO as GPIO
import time
import os
import datetime
import file_mng as file

Switch = 10

 

#スイッチが押されたときの処理

def switch(gpio_pin):
  time.sleep(0.2)
  if GPIO.input(Switch) == 0:
    time.sleep(0.2)

    #既にスタートファイルがあるときは
    if file.is_start():

      #スタートファイルを消す
      file.stop()
      file.save_row_0('-- STOP --')

    #スタートファイルが無い場合は
    else:
      now = datetime.datetime.now()

      #現在日時をスタートファイルに書き込む
      file.start( now.strftime("%Y/%m/%d %H:%M:%S") )
      file.save_row_0('-- START --')

  while GPIO.input(Switch) == 0:
  time.sleep( 1 )

 

#スタートスイッチをプルアップしておいて、プッシュ時(ピン電圧0V時)にswitchメソッドを読むよう設定

def standby():
  GPIO.setmode(GPIO.BCM)
  GPIO.setup(Switch, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  GPIO.add_event_detect(Switch, GPIO.FALLING)
  GPIO.add_event_callback(Switch, switch)

  while True:
    time.sleep(60)


if __name__=='__main__':
  standby()

 

<全プログラム内部構造一覧>

dreamerdream.hateblo.jp

 

kampa.me