raspberrypiでGUIカウントダウンダイマーを作る
今回作ったもの
今回は設定した時間分カウントダウンをし、画面にGUI表示するソフトをpythonとraspberrypiで作ってみました。
pythonで使えるtkinterというUGI作成パッケージを使用してカウントダウンしたものをターミナル上ではなく、GUIで表示します。
環境
Raspberry pi 3B+
python 3.7.3
tkinter
pillow
準備
sudo apt update sudo apt remove python3-pil sudo apt install python3-tk pip3 install pillow
詰まった部分
画像ライブラリのpillowはpythonをインストールしたときにはじめから入っているのですが、それだと上手く動かなかったので、アンインストールしてから最新版を再インストールしました。
完成品
カウントが10からスタートして0まで表示されます。
ソースコード
import math import json import requests import os from tkinter import * import tkinter.ttk as ttk from datetime import datetime, timedelta from time import sleep target_time = 20 # メインウィンドウ作成 root = Tk() # メインウィンドウサイズ root.geometry("1024x600") # メインウィンドウタイトル root.title("count") # MainFrame クラス class MainFrame(ttk.Frame): # コンストラクタ def __init__(self, master=None, **kwargs): # 親クラスのコンストラクタを呼び出す super().__init__(master, **kwargs) # create_widgets を呼び出す self.create_widgets() # ウィジェットを作成 def create_widgets(self): # フレームを作成 self.frame = Frame(self, bg="white", bd=0, height=460, relief="flat") # タイマーカウント表示 self.wp = Label(self.frame, text="", bg="white", font=("", 40, "bold"), anchor="w") self.wp.place(width=740, x=150, y=350) # フレームを配置 self.frame.grid(row=0, column=0, columnspan=8, sticky="news") self.rowconfigure(0,weight=1) self.rowconfigure(1,weight=1) self.rowconfigure(2,weight=1) self.rowconfigure(3,weight=1) self.rowconfigure(4, weight=1) for i in range(8): self.columnconfigure(i, weight=1) # メインフレームを配置 app = MainFrame(root) app.pack(side=TOP, expand=1, fill=BOTH) # メインウィンドウを閉じる def wm_close(): root.destroy() # 閉じるボタン作成 btn = Button(root, text=" X ", font=('', 16), relief=FLAT, command=wm_close) # 画面がリサイズされたとき def change_size(event): # ボタンの位置を右上に btn.place(x=root.winfo_width() - 60, y=14) # 画面のリサイズをバインドする root.bind('<Configure>', change_size) # メインウィンドウの最大化 #root.attributes("-zoom", "1") root.attributes("-fullscreen", "1") counter_time = 0 count_time_flag = 1 def count_down_time(): global counter_time global count_time_flag if count_time_flag == 1: counter_time = 5 count_time_flag = 0 # フラグを下げてカウントがリセットされないようにする counter_time -= 1 #print(counter_time) if counter_time < 0: return 0 t = "インターバル残り時間:{0}".format(counter_time) app.wp.configure(text=t) root.after(1000, count_down_time) count_down_time() # メインループ root.mainloop()
参考サイト
Raspberry piにモーニングコールをしてもらう
やったこと
今回はRaspberry piに、朝の起きる時刻になると設定した音声を喋ってもらう機能を実装しました。
環境
Raspberry pi 3B+
python 3.7.3
Open JTalk1.08
準備
発話の準備
jtalkを使って喋らせるので、こちらの記事を参考にしながらjtalkの環境構築を進めました。 pacoは使えなかったので普通にmake installしました。パッケージの管理はできなくなりますが問題ありません。
プログラム
#!/usr/bin/env python # -*- coding:utf-8 -*- import shlex import subprocess from datetime import datetime CMD_SAY = 'jsay' def Mornigcall(): text = '起きてください 会社に遅れます' text = CMD_SAY + ' ' + text proc = subprocess.Popen(shlex.split(text)) proc.communicate() return def SayDateTime(): d = datetime.now() text = '現在時刻は%s時%s分%s秒です' % (d.hour, d.minute, d.second) text = CMD_SAY + ' ' + text proc = subprocess.Popen(shlex.split(text)) proc.communicate() return def main(): for num in range(6): SayDateTime() Mornigcall() return if __name__ == "__main__": main()
ファイル名は「mornigcall.py」です。ひとまず6回繰り返すようにしました。
自動起動の設定
朝の起きる時刻になったら発話するプログラムを自動で起動します。
コマンドラインからcrontab -e
を実行して出てきたファイルの一番下に以下のように記述します。注意点としてフルパスで記述する必要があります。
定期自動実行に関してはcronの使い方(pythonスクリプト)を参考にしました。
これで毎朝7時にモーニングコールで起こしてもらえます。
参考
Raspberry piでものを上下させると増えるカウンターを作ってみた
やったこと
Raspberry pi 3B+に赤外線距離センサをつけて、ものを近づけて遠ざけるとカウントが増えるプログラムを作成しました。Raspberrypiで何か生活を便利にするものを作ろうと思っていますが、いきなり高度なものはモチベーションが続かないので簡単なものから作って積み上げていこうと思います。今回はその第1段です。
環境
python 3.7.3
Raspberry pi 3B+
VL53L0x(赤外線距離センサ)
準備
距離センサの選定
赤外線距離センサは、最小検出距離の短さと小ささからAmazonに売っているVL53L0xを選びました。
VL53L0xをPythonで使えるようにするまで
こちらのサイトのとおりに環境構築を進めていきました。
pythonでいきなり使えるようになるわけではなくて、センサの発売元であるSTmicro Electronicsが配布しているAPI(C言語で書かれている)をダウンロードしてコンパイルしないといけないようです。コンパイルが終わったらAPIをpythonで使えるようにするためのオープンソースプロジェクトをGithubからクローンします。
今回は自分でプログラムを作成するので、「Counter」というディレクトリを作成し、VL53L0X.piとbinを「Counter」ディレクトリにコピーしました。
カウントするプログラムを作成する
プログラムの設計としては、以下の図に示すような状態をとり、それぞれの条件判定によって状態を遷移していきます。「inital」はプログラムを起動したときの初期状態、「above」は基準よりものが上にある状態、「down」はものを近づけている(下げている)状態、「below」は基準より下に下がっている状態、「up」はものが上がっている状態になります。
普通に書こうとするとifとwhileの大量の入れ子が発生して見づらくなるので状態で管理します。
こうして状態で管理すると、次の状態に遷移するときの判定だけを見ていれば良いので、見やすく、機能の追加もしやすいです。
本来は距離データは移動平均などを取る必要がありますが、計測してみたらあまり振れ幅がなかったので、今回の用途ではしきい値を調整することでうまく判定できるようにしました。
書いたコードは以下です。
#!/usr/bin/env python # -*- coding: utf-8 -*- import time # time(sleepを使うためのモジュール)のインポート import VL53L0X # VL53L0X(spi通信を行うためのモジュール)のインポート counter = 0 state_dict = {"inital": 0, "above": 1, "down": 2, "below": 3, "up": 4} above_dist = 16 below_dist = 4 state = 0 def Counter(): global state global counter global above_dist global below_dist if state == state_dict["inital"]: print("inital state") if dist > above_dist and dist < above_dist+4: # この範囲に入ったらスタート state = state_dict["above"] elif state == state_dict["above"]: # print("above state") if dist < above_dist: state = state_dict["down"] elif state == state_dict["down"]: # print("down state") if dist < below_dist: state = state_dict["below"] elif state == state_dict["below"]: # print("below state") if dist > below_dist: state = state_dict["up"] elif state == state_dict["up"]: # print("up state") if dist > above_dist: state = state_dict["above"] counter += 1 print("%d 回" % counter) if __name__ == '__main__': """VL53L0Xのインスタンスを作成""" tof = VL53L0X.VL53L0X(address=0x29) # 距離の取得を開始する tof.start_ranging(VL53L0X.VL53L0X_BETTER_ACCURACY_MODE) while True: try: dist = tof.get_distance()/float(10) # VL53L0Xから距離[cm]を取得する Counter() except KeyboardInterrupt: break
完成品
プログラムを実行してものを近づけたり離したりするとカウントが上がります。
参考サイト
5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (44) 距離センサ5 I2C VL53L0X | 電子工作の環境向上