契機
趣味でやっているプラモデルの塗装用にエアーコンプレッサーを購入しました.
エアーコンプレッサーを使用していると本体の温度がガンガン上昇します.
(ほんと触れないくらいになっちゃう)
この温度上昇はエアコンプレッサーに負荷のかかるもので故障の原因になります.
なので塗装中はエアコンプレッサーを定期的に冷却する必要があります.
少なくとも私はそうしています.
でも,塗装中エアコンプレッサーがアチアチになっていることにほとんど気づきません.
そこでエアコンプレッサーが熱くなったらお知らせしてくれるようなものを作ろうと思い立ちました.
ついでに冷却が終了したことも知らせてくれるやつを作ろう!と...
できた!
できました.作りました.
音声が流れます!
温度が上昇し,指定した上限温度に達するとピタゴラスイッチの音が鳴るようにしました.
冷却モードでは指定した温度以下になるとピタゴラスイッチの音が鳴ります.
動画は冷却終了検知モードでの様子です.
エアコンプレッサーの温度が室温と同じくらいなので鳴っています.
最後に赤いLEDが光ったのは温度上昇検知モードになったことを知らせています.
(青は冷却終了検知モード)
以降のページではこの装置で使った部品であったり,スクリプトについて書いていきます.
Components
この装置を作るのに以下の部品たちを使いました.
・Raspberry pi pico
・RGB LED
・電池ボックス
・温度センサ
・DC/DCコンバータ(昇圧型)
・スライドスイッチ
・ブザー
基盤
はんだ付けした基盤や部品は次のようになってます.
青,白,緑の配線の先には温度センサがくっついています.
温度センサを二つ使用して二か所の温度を測定します
100V ACから電力を引いているのでAC/DCコンバータを使って5Vに降圧しています.
温度センサ
温度センサは次のものを使いました.あまり精度は高くありません.
(むしろ悪い)
・温度センサ概要
・データシート
温度センサを使うにあたって次のサイトを参照しました.
・Raspberry Pi Pico MicroPython アナログ入力 テスト
・Raspberry Pi Pico(MicroPython)で温度センサを使う
・Raspberry Pi Pico Wの温度センサー(アナログ値を温度に変換する)
この温度センサの
分解能は 19.5mV/dig
測定可能温度は 40~125deg
出力電圧は 200mV~3V
でした.
データシートを見るとこの温度センサは最小の出力が200mVなのですが,温度に変換する式を簡単にするために最小電圧を0Vとして計算しました.
関数で表すと次です.valは16進数で取得した温度センサからの値です.
def cal(val):
adc_vol=(val/65535)*3.3
#16bitでの出力をvoltageに変換
temp_vol=adc_vol-0.4
#0degにおける出力が0.5v equation4-1 ref
temp=(temp_vol/19.5)*1000
#19.5は温度センサの分解能[mV/dig]
return temp
温度センサから値を取得する
温度センサから値を取得するにあたってはじめ,次のコードを使用していました.
今回温度の取得に温度センサーを二つ使用し,別々の箇所の温度測定を考えていました.
from machine import ADC,Pin
import utime
adc0=machine.ADC(0)
adc1=machine.ADC(1)
def cal(val):
adc_vol=(val/65535)*3.3
temp_vol=adc_vol-0.4
temp=(temp_vol/19.5)*1000
return temp
while True:
return0=adc0.read_u16()
return1=adc1.read_u16()
print("0:",cal(return0)," 1:",cal(return1))
utime.sleep(1)
結論として上記のコードでは2つの温度センサの値をうまく取得できません.
(詳しく言うと片方のセンサの値は正しいのですが,もう片方はあり得ない値が返ってきます)
原因はPinをINかOUTに設定していないことにありました.
参考にしたサイトは次です.
・Raspberry Pi Pico MicroPython アナログ入力(ADC)テスト
修正したコードは次です.
from machine import ADC,Pin
import utime
#########################ここが必要!
Pin(26,Pin.IN)
Pin(27,Pin.IN)
#########################
adc0=ADC(0)
adc1=ADC(1)
def cal(val):
adc_vol=(val/65535)*3.3
temp_vol=adc_vol-0.4
temp=(temp_vol/19.5)*1000
return temp
while True:
return0=adc0.read_u16()
return1=adc1.read_u16()
print("0:",cal(return0)," 1:",cal(return1))
utime.sleep(1)
ブザーを鳴らしたい
温度上昇,冷却を知らせる方法として圧電ブザーを用いました.
ピタゴラスイッチの音が鳴ります.
音楽的な知識は皆無なので完全にサイトのをコピーしました.
参考にしたサイトは次です.
・PWM信号でスピーカーでメロディー演奏
気づいたこと
Picoへの電力供給方法として単4電池2本で約3Vとしていました.
Picoには電圧レギュレータがついているので供給電圧が1.8V~であれば3v3Pinには3.3Vが来るはずです.
(と思っていた.)
この3.3Vで温度センサを動かそうとしていました.
しかし,実際テスターで測定していると供給した電圧をそのまま出力しているようで3.3Vに昇圧されていなかった.
これは,OfficialなPicoではない中国製のものを使用したからなのか,単にPicoがそういう使用なのかは謎です.
結局前の記事でも書いたようにまた,供給電力小さすぎ問題です.
解決方法として,100V AC(家庭用電源)に手を出すことにしました.
それについて次のページで詳しく書きます.
100V AC(交流)
前の記事では怖くて100V ACを使用するのを諦めました.
原因は供給電力が少ないというものでした.
そして今回またすぐ出会った.同じ問題.
電力足りない....
もう,可能な限り安全に気を付けて100V ACを使ってみることにしました.
もちろん,ACアダプターを買って供給すればPicoには十分です.
しかしそれではいけない(したくない)理由が以下です.
・塗装するときにコンセントをコンプレッサーに使って数が足りない.
・長いケーブルが増えるのでごちゃごちゃする.(主にこっち)
ということで100V ACを使います.
100V AC使用
まず,感電したくないので400Vに耐えられる安全手袋買いました.
(これでうっかり接触感電はないと思いたい.)
次に,100V ACはどこから引っ張ってくるのか.
コンプレッサーから引っ張ります.
このエアコンプレッサーはコンセントに差し込んで使用するので内部で100V ACをどうにかしているはずです.
なので,コンプレッサーを少し分解...
ありました.この水色のマルで囲った半透明部分がコンセントから直接来たACの先みたいです.
確認するとちゃんと100V 50Hz来ていました.
(写真取り忘れた...)
で,ここから100V ACを引っ張りたいので半透明の絶縁を剥いでケーブルをはんだ付けします(左).
このまま配線むき出しではショートして怖い思いするので絶縁します(右).
素手で触っていますが電流は流れていない状態です.
AC/DC コンバータ
Picoへの給電は1.8V~5VくらいのDC(直流)です.
なのでこの100V ACをそのまま接続すると確実に壊れます
AC/DCコンバータを使いましょう.
所謂ACアダプターです.
しかし100V ACが得られるのは普段使っているようなコンセントプラグではなく2本の銅線からです.
ということでACアダプターを分解します.
皆さんご存知のこいつです
いつもスマホとか充電する時にお世話になってます.
分解すると中身はこんなのが入っています.
AC/DCコンバータですね.名前の通りAC(交流)をDC(直流)に直してくれます.
しかも100Vから5Vに降圧もしてくれる!
素晴らしいですね!はんだ付けして組み込みましょう.
ACが入ってくるところはこんな感じにしました.
もちろん次は降圧下側をPicoとつなぎます.
最後にビニールテープで絶縁(できているか?)して終わり.
装着
実際に装着するとこんな感じになりました.
なんか不格好だなぁ
この記事は終わりです.
(もっと早く記事書けるようにならないかな...既に2時間以上書いてる)
あ,最後に全体のコードを載せておきます.
from machine import ADC,Pin,PWM,Timer
import utime
#settings
pin6=Pin(0,Pin.IN,Pin.PULL_UP)#sw hot
pin7=Pin(2,Pin.IN,Pin.PULL_UP)#sw cool
Pin(26,Pin.IN)#thermomater0
Pin(27,Pin.IN)#thermomater1
adc0=ADC(0)
adc1=ADC(1)
ther_v0=Pin(4,Pin.OUT)#thermomater電源,3v3を給電
ther_v1=Pin(5,Pin.OUT)
ther_v0.value(1)
ther_v1.value(1)
#RGBLED
pin1=12
pin2=11
pin3=10
Pin(pin1,Pin.OUT)
Pin(pin2,Pin.OUT)
Pin(pin3,Pin.OUT)
pwms=[PWM(Pin(pin1)),PWM(Pin(pin2)),PWM(Pin(pin3))]
for pwm in pwms:
pwm.freq(1000)
def map_color(color):
return int(color*65535/255)
def set_color(red,green,blue):
pwms[0].duty_u16(map_color(red))
pwms[1].duty_u16(map_color(green))
pwms[2].duty_u16(map_color(blue))
#電源が入ったことを知らせる
set_color(0,255,0)
utime.sleep(0.5)
set_color(0,0,0)
utime.sleep(0.5)
#ブザー
speaker=PWM(Pin(15,Pin.OUT))
#ピタゴラ音
A4 = 440
B4 = 493.883
C5 = 523.251
C5s= 554.365
D5 = 587.330
E5 = 659.255
F5 = 698.456
F5s= 739.989
G5 = 783.991
A5 = 880
B5 = 987.767
C6 = 1046.502
mspb = 156 # 6.4bpsの逆数 = 0.156ms これが8分3連符ひとつ分の音の長さ、音の間隔となる
# ピタゴラスイッチのメロディーを配列で作成。1要素が8分3連符ひとつ分の音の長さになる。0は無音(休符)
melody = [D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,C6,B5,0,G5,A5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,B4,A4,0,B4,C5,0,C5s,D5,0,0,D5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,C6,B5,0,G5,A5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,B4,A4,A4,A4,A4,A4,A4,A4,A4,A4,0,0,F5,E5,0,E5,F5s,E5,F5s,G5,G5,G5,D5,0,B4,C5,0,C5,D5,C5s,D5,B4,B4,B4,0,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,C6,B5,0,0,G5,0,0,0,0,0,0,0,0,0,0,0,0,0,D5,E5,0,D5,E5,0,C6,B5,0,0,G5]
i=0#メロディーを進めるための変数
def beat(timer):
global i
global melody
global speaker
if i >= len(melody): # メロディーを最後まで演奏し終えたら
speaker.deinit() # スピーカーのPWMを破棄して
timer.deinit() # タイマーを破棄して終了
elif int(melody[i]) == 0: # メロディー音が0、つまり無音(休符)の場合
speaker.duty_u16(0) # PWMのDutyを0とすることで波形は出力されずLOWとなり、音は出ない
else:
speaker.freq(int(melody[i] + 0.5)) # PWMの周波数を次のメロディー音の周波数に変更する。整数で渡す必要があるので、+0.5してから小数点以下切り捨て(thanks @naohiro2g)
speaker.duty_u16(0x8000) # PWMのDutyを50%に戻し、音を出す。Dutyは0~0xFFFFつまり65535までの間の値で設定
i += 1 # メロディーを次に進めて終わり
def sw():#スイッチがどっちに入っているか取得
if pin6.value()==0:
return "hot"
elif pin7.value()==0:
return "cool"
def cal(val):
adc_vol=(val/65535)*3.3#16bitでの出力をvoltageに変換
temp_vol=adc_vol-0.4#0degにおける出力が0.5v equation4-1 ref
temp=(temp_vol/19.5)*1000
return temp
def get_temp():#平均温度取得
temp_list=[]
for i in range(11):
return0=adc0.read_u16()
return1=adc1.read_u16()
temp0=cal(return0)
temp1=cal(return1)
temp_list.append(temp0)
temp_list.append(temp1)
utime.sleep(0.1)
# print(temp_list)
temp_list.sort()#昇順にソート
median_temp=temp_list[5]#中央値を取得する
# print(median_temp)
# ave_temp=(cal(return0)+cal(return1))/2 #平均が欲しいとき
return median_temp
# while True :
# get_temp()
# utime.sleep(1)
max_temp=50
min_temp=40
def hot_checker():
while True:
temp=get_temp()
print("now",temp)
global i
if temp>max_temp:
print(0)
tim = Timer()
tim.init(period=mspb, mode=Timer.PERIODIC, callback=beat)
utime.sleep(30)#メロディーが終わるまで待機
i=0#進んだメロディーをはじめに戻す
break
else:
sw_check=sw()
if sw_check=="cool":
print("switched")
break
utime.sleep(30)
def cool_checker():
while True:
temp=get_temp()
print("now",temp)
# for j in range(temp):
# set_color(0,255,255)
# utime.sleep(0.15)
# set_color(0,0,0)
# utime.sleep(0.15)
global i
if temp<min_temp:
tim = Timer()
tim.init(period=mspb, mode=Timer.PERIODIC, callback=beat)
utime.sleep(30)
i=0#進んだメロディーをはじめに戻す
break
else:
sw_check=sw()
if sw_check=="hot":
print("switched")
break
# set_color(0,255,255)
# utime.sleep(0.15)
# set_color(0,0,0)
# utime.sleep(0.15)
utime.sleep(30)
while True:
sw_value=sw()
if sw_value=="hot":
set_color(255,0,0)
utime.sleep(1)
set_color(0,0,0)
# print("hot mode")
# temp=get_temp()
# print("Current temp is",temp)
hot_checker()
elif sw_value=="cool":
set_color(0,0,255)
utime.sleep(1)
set_color(0,0,0)
# print("cool mode")
# temp=get_temp()
# print("Current temp is",temp)
cool_checker()
utime.sleep(1)