Ruby初心者がラズパイに書く換気扇制御プログラム -入口編-

Ruby初心者がラズパイに書く換気扇制御プログラム -入口編-

部屋がどうしようもなく暑い。

という訳でこの夏、2階の部屋に屋根裏換気扇を付けました。

三菱電機 換気排熱ファン V-20MEX2

V-20MEX2-SW|三菱電機WIN2K

主に天井に取り付け、熱せられた屋根裏の熱を室内の空気ごと建屋外に排熱する換気扇。
裏側のファン部分が丸ごと上下し、OFF時には完全に通気口を塞ぐ気密を落とさない構造になっています。

20160810-01

天井に穴を開ける勇気がなくて点検口のフタを繰り抜いてとりつけ。また電気工事士の資格もないため、ながーいAC100Vコードをくっつけてそれの抜き差しでOFF/ONする仕組み。

20160810-03

取り付けて早速回してみましたが、今ひとつ換気の効果が出ていません。

これは恐れていたというかむしろなんとなくそんな気はしていた屋根裏密閉構造なのかもしれない・・・。そうなるともう工事屋さんの世界ではあるけれどどのみち屋根裏換気は必要だから良しとしよう。

OFF/ONはラズパイで

換気扇の改善はおいおい考えるとして、換気扇のOFF/ONはRaspberry Piでやろうと決めてました。

余っていたRaspberry Pi 1 Model B+(タブン)に同じく余っていたRaspberryHabuと(略)Corega CG-WLUSB300GNMと(略)DHT11でこんな感じに組みました。

20160810-02

今回タクトスイッチでの入力を行うためTC4050BPを追加しています。
GPIOと物理デバイスの配線は以下のとおり。

GPIO No.(MODE) Device
0(Input) タクトスイッチ
3(Output) LED
5(Input) DHT11
7(Output) リレー

換気扇から伸びる100Vケーブルの片側をカットし、リレーを間にはさみます。。

プログラム

何を実現するコードかといいますと

  • テキストにONって書いてあったらリレーをONにする
  • タクトスイッチを押すとOFF←→ONをトグルできる

だけです。

require 'wiringpi'
require 'fileutils'

#init

flag_file = "/dev/shm/flag_file.dat"

io = WiringPi::GPIO.new do |gpio|
  gpio.pin_mode(3, WiringPi::OUTPUT)
  gpio.pin_mode(7, WiringPi::OUTPUT)
  gpio.pin_mode(0, WiringPi::INPUT)
end

io.digital_write(3, WiringPi::LOW)
io.digital_write(7, WiringPi::LOW)

f_chk_code = "ON"


# FLAG READ
def flag_read
        flag_file = "/dev/shm/flag_file.dat"
        File.open(flag_file, "r:UTF-8") do |f|
                f_chk = f.gets
                return f_chk.chomp!
        end
end

# FLAG WRITE
def flag_write(fw)
        flag_file = "/dev/shm/flag_file.dat"
        File.open(flag_file, "w:UTF-8") do |f|
                if f.flock(File::LOCK_EX|File::LOCK_NB)
                        if fw >= 1 then
                                f.puts("ON")
                    puts "push botton ON"
                        else
                                f.puts("OFF")
                    puts "push botton OFF"
                        end
                        return 0
                else
                        return 1
                end
        end
end


# Main loop

loop do
        now = flag_read

        #button check
        buttom_state = io.digital_read(0)
        if buttom_state == 1 then
                sleep(0.4)
                buttom_state = io.digital_read(0)
                if buttom_state == 1 then
                        if now == f_chk_code
                                res = flag_write(0)
                        else
                                res = flag_write(1)
                        end
                end
        end

        #Relay Switch
        if now == f_chk_code then
                io.digital_write(3, WiringPi::HIGH)
                io.digital_write(7, WiringPi::HIGH)
                puts "flag is HIGH"
        else
                io.digital_write(3, WiringPi::LOW)
                io.digital_write(7, WiringPi::LOW)
                puts "flag is LOW"
        end

        sleep(0.5)
end

解説というより自分メモ

4-17行目

初期化。8-12行目はGPIO各ピンの動作モードを指定。書式はWiringPiの公式(?)より。

GitHub – WiringPi/WiringPi-Ruby: Version 2.x of Gordon Henderson’s Arduino-like WiringPi GPIO functions, wrapped up for Ruby.

20-27行目

flag_readというメソッドを定義しています。

フラグを書いたテキストファイル(/dev/shm/flag_file.dat)=フラグファイルを読み込んで変数に入れます。その後.chomp!メソッドを使って改行コードを取り除いています。これをやらないとただ単にif f_chk == ONとやっても必ずfalseになります。解るまで正直かなりかかりました。

flag_file =は各所に書いてありますが、メソッドの中で書かないとエラーになった為。何か手があるんでしょう。きっと・・・

29-46行目

flag_writeというメソッドを定義しています。

フラグファイルを作成するのですが、このファイルは他プログラムが書く可能性もあるので.flockメソッドを使ってロックファイルによる排他制御を行っています。その競合により書き込めなかった場合は1を戻り値に返しますが、特にノーアクション。ループしてるのでまた押せばいいかという運用。

今後は初期のフラグファイル作成もここでやる予定

49-80行目

メインのループ

55-66行目はタクトスイッチが押されているかを読み取り、押されている場合0.4秒まってもう一度読み込みます。それでも押されている場合は現在のフラグファイルと比較し今がONならOFFへ、今がOFFならONへリレーをトグルします。
メソッドを呼び出すときの引数は数字だそうですよ。最初ONとか書いて止まってました。

68-77行目でフラグファイルの読み出し結果とチェックコードを比較して、一致すればリレーとステータスLEDをONへ、不一致であれば両方をOFFのにします。

これはメソッドで書けたら良さそうなものですが、io.digital_writeはメソッド内では使えないようで。

実行結果と今後

putsで0.5秒おきにメッセージを出しつつ、ボタンが押されるのを待ちます。チャタリング防止に0.4秒ほど押し続けた時のみフラグファイルの中身が変わるようにしました。その後ポーリングでフラグファイルをチェックし、ONと書いてあればGPIOをONにします。

flag is LOW
flag is LOW
flag is LOW
flag is LOW
push botton ON
flag is LOW
flag is HIGH
flag is HIGH
flag is HIGH
flag is HIGH
flag is HIGH
push botton OFF
flag is HIGH
flag is LOW
flag is LOW
flag is LOW
flag is LOW

テキストファイルに希望のステータスを書いてから読み取って変更する手間を組んだため長くなりました。その代わり今後Ruby以外(ex.コマンドの実行結果によってシェルスクリプトから)でも変更指示をかけられます。

CでかかれたDHT11温度読み取りの結果をテキストに吐いて、Wgetで取得したWeb上の気温との差分を出して換気扇を動作。そんな事がやりたいなと思っています。もしテキスト公開している外気温データがなければ、別の涼しい場所においているもう一つのラズパイから温度データを取得して温度差を動作条件としてもいいかもしれません。

2016/08/17 追記
続編はこちら

Raspberry Piカテゴリの最新記事