注釈

こんにちは、SunFounderのRaspberry Pi & Arduino & ESP32愛好家コミュニティへようこそ!Facebook上でRaspberry Pi、Arduino、ESP32についてもっと深く掘り下げ、他の愛好家と交流しましょう。

参加する理由は?

  • エキスパートサポート:コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決します。

  • 学び&共有:ヒントやチュートリアルを交換してスキルを向上させましょう。

  • 独占的なプレビュー:新製品の発表や先行プレビューに早期アクセスしましょう。

  • 特別割引:最新製品の独占割引をお楽しみください。

  • 祭りのプロモーションとギフト:ギフトや祝日のプロモーションに参加しましょう。

👉 私たちと一緒に探索し、創造する準備はできていますか?[ここ]をクリックして今すぐ参加しましょう!

4.1.3 音声時計

はじめに

このプロジェクトでは、スピーカーと4桁の7セグメントディスプレイを用いて音声時計を作成しましょう。4桁の7セグメントディスプレイで時間を表示し、スピーカーで毎時時間をアナウンスします。

必要な部品

このプロジェクトには以下のコンポーネントが必要です。

../_images/3.1.17components.png

一式をまとめて購入するのが便利です。リンクはこちら:

名前

このキットのアイテム

リンク

Raphael Kit

337

Raphael Kit

以下のリンクから個別に購入することも可能です。

コンポーネントの紹介

購入リンク

GPIO拡張ボード

購入

ブレッドボード

購入

ジャンパーワイヤー

購入

抵抗器

購入

オーディオモジュールとスピーカー

-

4桁7セグメントディスプレイ

-

74HC595

購入

回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

SPIMOSI

Pin 19

12

10

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

../_images/4.1.3_speechclock_schematic.png ../_images/3.1.17_schematic.png

実験手順

ステップ1: 回路を作成する。

../_images/3.1.17fritzing.png

このプロジェクトに取り組む前に、 3.1.4 テキストから音声へ(TTS) を完了している必要があります。

ステップ2: date コマンドでローカル時間を確認する。

date

ローカル時間が実際の時間と異なる場合、以下のコマンドを使用してタイムゾーンを設定します。

sudo dpkg-reconfigure tzdata

タイムゾーンを選択します。

../_images/tzdata.png

ステップ3: コードのフォルダに移動する。

cd ~/raphael-kit/python/

ステップ4: 実行する。

python3 4.1.3_SpeechClock.py

コードが実行されると、次の動作が行われます:

  • 音声で「時計システムを起動しました。ようこそ!」という歓迎メッセージが再生されます。

  • 4 桁のディスプレイには、現在時刻が HH:MM 形式で表示されます。

  • 毎正時(分が 0 のとき)に、システムがその時刻を 1 回アナウンスします。

  • Ctrl+C が押されるまでディスプレイは継続的に更新され、終了時には GPIO リソースが適切に解放されます。

コード

注釈

下記のコードは 修正/リセット/コピー/実行/停止 が可能です。ただし、その前にソースコードのパス、例えば raphael-kit/python に移動する必要があります。コードを修正した後、直接実行して効果を確認することができます。

import RPi.GPIO as GPIO
from tts import TTS
import time

# Initialize TTS
tts = TTS(engine="espeak")
tts.lang('en-US')

# GPIO pins
SDI = 24
RCLK = 23
SRCLK = 25

placePin = (10, 22, 27, 17)

# Seven-segment encoding
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(SDI, GPIO.OUT)
    GPIO.setup(RCLK, GPIO.OUT)
    GPIO.setup(SRCLK, GPIO.OUT)
    for pin in placePin:
        GPIO.setup(pin, GPIO.OUT)

def clearDisplay():
    for _ in range(8):
        GPIO.output(SDI, 1)
        GPIO.output(SRCLK, GPIO.HIGH)
        GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(RCLK, GPIO.HIGH)
    GPIO.output(RCLK, GPIO.LOW)

def hc595_shift(data):
    for i in range(8):
        GPIO.output(SDI, (0x80 & (data << i)))
        GPIO.output(SRCLK, GPIO.HIGH)
        GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(RCLK, GPIO.HIGH)
    GPIO.output(RCLK, GPIO.LOW)

def pickDigit(digit):
    # Turn all digits off
    for pin in placePin:
        GPIO.output(pin, GPIO.LOW)
    # Turn selected digit ON
    GPIO.output(placePin[digit], GPIO.HIGH)

def loop():
    status = 0

    while True:
        now = time.localtime()
        hour = now.tm_hour
        minute = now.tm_min

        # Display minute (unit)
        clearDisplay()
        pickDigit(0)
        hc595_shift(number[minute % 10])

        # Display minute (tens)
        clearDisplay()
        pickDigit(1)
        hc595_shift(number[(minute // 10) % 10])

        # Display hour (unit)
        clearDisplay()
        pickDigit(2)
        hc595_shift(number[hour % 10])

        # Display hour (tens)
        clearDisplay()
        pickDigit(3)
        hc595_shift(number[(hour // 10) % 10])

        # Speak once every hour (at minute == 0)
        if minute == 0 and status == 0:
            tts.say(f'The time is now {hour} hours and {minute} minutes')
            time.sleep(3)   # Give time to finish speaking
            status = 1
        elif minute != 0:
            status = 0

        time.sleep(0.005)  # Prevent CPU overload

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    setup()

    # ★ Welcome message at startup
    tts.say("Clock system started. Welcome!")
    time.sleep(3)

    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コード説明

  1. espeak を使用して音声合成エンジンを初期化し、言語を英語に設定します。

    tts = TTS(engine="espeak")
    tts.lang('en-US')
    
  2. シフトレジスタ(74HC595)と 4 桁表示用の各桁選択ピンに使用する GPIO ピンを定義します。

    SDI = 24
    RCLK = 23
    SRCLK = 25
    placePin = (10, 22, 27, 17)
    
  3. 7 セグメントディスプレイで数字 0〜9 を表示するためのセグメントエンコード値を保存します。

    number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
    
  4. シフトレジスタに「1」のビットを 8 回送り、ディスプレイをクリアします。

    def clearDisplay():
        for _ in range(8):
            GPIO.output(SDI, 1)
            GPIO.output(SRCLK, GPIO.HIGH)
            GPIO.output(SRCLK, GPIO.LOW)
        GPIO.output(RCLK, GPIO.HIGH)
        GPIO.output(RCLK, GPIO.LOW)
    
  5. 現在表示する数字を更新するため、1 バイト分のセグメントデータを 74HC595 に送信します。

    def hc595_shift(data):
        for i in range(8):
            GPIO.output(SDI, (0x80 & (data << i)))
            GPIO.output(SRCLK, GPIO.HIGH)
            GPIO.output(SRCLK, GPIO.LOW)
        GPIO.output(RCLK, GPIO.HIGH)
        GPIO.output(RCLK, GPIO.LOW)
    
  6. 4 桁表示のうち、千の位・百の位・十の位・一の位のいずれかを選択して表示する桁を切り替えます(多重化処理)。

    def pickDigit(digit):
        for pin in placePin:
            GPIO.output(pin, GPIO.LOW)
        GPIO.output(placePin[digit], GPIO.HIGH)
    
  7. システムクロックから現在時刻を読み取ります。

    now = time.localtime()
    hour = now.tm_hour
    minute = now.tm_min
    
  8. HH:MM 形式で現在時刻を表示するため、7 セグメントディスプレイの各桁を更新します。

    hc595_shift(number[minute % 10])
    hc595_shift(number[(minute // 10) % 10])
    hc595_shift(number[hour % 10])
    hc595_shift(number[(hour // 10) % 10])
    
  9. 毎正時(minute が 0 のとき)に、現在時刻を音声で 1 回読み上げます。

    if minute == 0 and status == 0:
        tts.say(f'The time is now {hour} hours and {minute} minutes')
        status = 1
    elif minute != 0:
        status = 0
    
  10. プログラム起動時にウェルカムメッセージを再生します。

    tts.say("Clock system started. Welcome!")
    
  11. Ctrl+C が押されたとき、すべての GPIO ピンを解放し、後処理を行います。

    GPIO.cleanup()
    

現象の画像

../_images/4.1.3speech_clock.JPG