Tanuki_Bayashin’s diary

電子工作を趣味としています。最近はラズベリーパイPicoというマイコンを使って楽しんでいます

【金魚用】自動エサやり装置の改良

※なにか気になる点がありましたらコメント欄にご記入ください。また、工作や回路を製作する場合には、細かい作業などに対して、細心の注意を払われるようお願いいたします。


2024年11月21日午後8時ごろ、この装置を運転中に、本来動くはずのない時刻に動作を開始しました。幸い私がそばにいるときだったので事なきを得ましたが、金魚等の飼育をされている方にとっては危険極まりない不祥事が発生したことをここにとどめておきます。安全が確認されるまでこのコメントはこのままにしておきます。(2024/11/21)

12月4日に修理を行いました。ラズベリーパイと接続しているケーブルのコネクタが接続不良を起こしていたので直しました。修理後2週間経ち、安全に運転が続いていることから、安全な動作が確認できたものと判断することとしました。
ただ、動くべきでない時刻に動作した原因は判明していないので、引き続き経過観察を続けたいと思います。(2024/12/17)


【目次】

1.はじめに

4月ごろに製作した、金魚のための自動エサやり装置が故障しました。(下の記事を参照)

「自動エサやり装置」の記事
tanuki-bayashin.hatenablog.com

どこが悪いのか分からないままXiaoのソースコードを再度書き込もうとしたところ、ライブラリの更新があったため、言われるがまま更新しました。

すると、生成されたプログラムの容量がXiaoの記憶領域からオーバーしてしまい、アップロードができなくなりました。

結果、今度は水温モニターで使っているラズベリーパイを使えば解決するだろうという結論に達し、今回の取り組みへとつながりました。

「水温モニター」の記事
tanuki-bayashin.hatenablog.com

写真1 完成した自動エサやり装置


ソースコードや回路図のダウンロード先です。
(回路図はPDFファイルです)
https://github.com/Myuu1967/autoFeeder2
ご自由にダウンロードしてください

2.構成

構成は簡単です。
XiaoのD10から伸びていた線(モータをオンにするTrのベースに入るライン)にラズパイからGPIO20(#38ピン)を接続しました。

またD9につながっていたタクトswからの線は、ラズパイのGPIO21(#40ピン)につなぎました。(テストモード用)

写真2 製作したツイストペア線(エサやり装置は特にいじっていない)

一応ノイズ対策にと、ラズパイからの信号線とGND線をツイストペアとし、エサやり装置側ではGND線はつながないでおきました。
(つないでしまうと電流が流れ、ノイズの発生源となるらしいです)

あとはラズベリーパイ側でうまく制御してあげれば完成です。

3.ハードの部分

図1 回路図

2章で述べたままを回路図にしたものを載せておきます。

3.1 追加要素

水そうに装置を固定するために、写真のように台を設けました。

写真3,4 水そうに設置するための台

4.ソフトの部分

エサやり装置を動かすところのソースコードだけを以下に示します。
(この部分は単独で動きます)

リスト1

import tkinter as tk
from gpiozero import LED, Button
import threading
import time

# GPIO20に接続されたLEDのインスタンスを作成
led = LED(20)
test_mode_enabled = False  # 初期状態はテストモードではない
test_mode_led_ON = False

# GPIO21に接続されたタクトスイッチのインスタンスを作成し、プルアップを有効にする
# pull_up=True によりプルアップ抵抗を有効化
input_button = Button(21, pull_up=True)

# tkinter GUIの設定
root = tk.Tk()
root.title("LED Control with Test Mode")
root.geometry("480x300")

# 切り替えボタンの状態を管理する変数
led_control_enabled = False

# LEDオンオフの切り替えボタンの処理
def toggle_led_control():
    global led_control_enabled, test_mode_enabled
    led_control_enabled = not led_control_enabled
    
    if led_control_enabled:
        # LED制御が可能な状態
        toggle_button.config(text="Running", bg="orange", activebackground="orange")
        test_mode_button.config(state=tk.DISABLED)  # テストモードボタンを無効化
        test_mode_enabled = False
        test_label.config(bg='gray')
        test_mode_button.config(bg="gray", activebackground="gray")
    else:
        # LED制御が不可能な状態
        toggle_button.config(text="Stopped", bg="lightblue", activebackground="lightblue")
        test_mode_button.config(state=tk.NORMAL)  # テストモードボタンを有効化
        test_label.config(bg='yellow')
        test_mode_button.config(bg="lightblue", activebackground="lightblue")

# テストモードボタンの処理(押している間LEDをオン、離したらオフ)
def press_test_mode():
    global test_mode_led_ON
    if not led_control_enabled:
        test_mode_led_ON = True
        test_mode_button.config(text="ON ", bg="orange", activebackground="orange")

def release_test_mode():
    global test_mode_led_ON
    if not led_control_enabled:
        test_mode_led_ON = False
        test_mode_button.config(text="OFF", bg="lightblue", activebackground="lightblue")

# GPIO21ピンからの入力を監視し、LEDを制御するスレッド
def monitor_input():
    global test_mode_led_ON
    while True:
        # テストモードかつ入力があるとき
        if (test_mode_led_ON or input_button.is_pressed)and\
           (not led_control_enabled):
            led.on()
        else:
            led.off()
        time.sleep(0.1)  # チェック間隔を設定

# スレッドを開始してGPIO21の入力を監視
thread = threading.Thread(target=monitor_input)
thread.daemon = True  # メインプログラム終了時にスレッドも終了させるためデーモンにする
thread.start()

# フレームを作成し、その中にラベルとボタンを横並びで配置
frame = tk.Frame(root)
frame.pack()

# "LED"ラベルの設定
led_label = tk.Label(frame, text="Autofeeder", font=("Arial", 10), bg='yellow')
led_label.pack(side=tk.LEFT, padx=5)

# 切り替えボタンを"LED"ラベルの横に配置
toggle_button = tk.Button(frame, text="Stopped", command=toggle_led_control,
                          bg="lightblue", activebackground="lightblue")
toggle_button.pack(side=tk.LEFT)

# "Test Mode"ラベルの設定
test_label = tk.Label(frame, text="Test", font=("Arial", 10), bg='yellow')
test_label.pack(side=tk.LEFT, padx=5)

# テストモードボタンの設定
test_mode_button = tk.Button(frame, text="OFF",bg="lightblue",
                             activebackground="lightblue", state=tk.NORMAL)
test_mode_button.bind("<ButtonPress>", lambda event: press_test_mode())
test_mode_button.bind("<ButtonRelease>", lambda event: release_test_mode())
test_mode_button.pack(pady=20)

# メインループの開始
root.mainloop()

(リスト中、”LED”と表記されているところは”モーター”と置き換えてください)

仕様としては

  • 水温モニターはもとのまま動作する
  • エサやり装置には通常モードとテストモードがある
  • 通常モードでは朝8時と夜7時の1日2回動作する(実際に動かしているときは朝8時のみ)
  • テストモードではタッチパネルからと、装置にある基板上のswの両方から、動作をテストすることができる
  • 水温モニターの仕様を引き継ぎTkinterを用い、エサやり装置の機能もGUIにて動作できるようにした

と言ったところです。

GUIにするためTkinterを使ったので、Tkinterの学習が進みました。

水温モニターの画面の上の部分が空いていたので、そこにモード切替やテスト時のON/OFFスイッチを設けました。

時間が来たらエサを与える機能は、Xiaoの場合とは違い、こちらでは常時運転中のため、そのまま時間を計測し続け、時間が来たらにエサを与えるように、ソースコードを組みました。

写真5 ラズベリーパイのモニター上の表示

通常モード時ではテストモードのON/OFFは選択できないようにしました。(写真5は通常モード時)

5.動画

(1)テストモードの動き

www.youtube.com

(2)朝8時になったときの動き

www.youtube.com

6.あとがき

時間が取れず(気が向かず??)、少しの間筆者が自身でエサを与えていました。

取り組んでみると、わりとうまく作業が進みました。

テスト運転時にモーター音がすると、金魚たちがエサやり装置の周りに集まってきたのには、ほっこりしました。😊



最後までお付き合いくださり、ありがとうございました。