注釈

こんにちは、SunFounder Raspberry Pi & Arduino & ESP32 Enthusiast Community on Facebookへようこそ!他の愛好家と一緒に、Raspberry Pi、Arduino、ESP32の世界により深く入り込みましょう。

参加する理由

  • 専門家サポート: 購入後の問題や技術的な課題を、コミュニティと私たちのチームの助けを借りて解決します。

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

  • 限定プレビュー: 新製品の発表や先行プレビューに早期アクセスできます。

  • 特別割引: 最新製品を特別割引でお楽しみいただけます。

  • 季節限定キャンペーンとプレゼント: プレゼント企画やホリデーキャンペーンに参加しましょう。

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

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

はじめに

このプロジェクトでは、4桁の7セグメントディスプレイを制御してカウンターを作成する方法を学びます。カウンターは1秒ごとに1ずつ増加し、それに合わせて表示も更新されます。このプロジェクトでは、GPIOピンと74HC595シフトレジスタを使用して複数桁の表示を効率的に制御する方法を紹介します。


必要なもの

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

COMPONENT

PURCHASE LINK

ブレッドボード

購入

ジャンパーワイヤー

購入

抵抗器

購入

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

-

74HC595

購入

Fusion HAT+

-

Raspberry Pi

-


回路図

以下の回路図は、74HC595シフトレジスタを4桁7セグメントディスプレイおよびRaspberry PiのGPIOピンに接続する方法を示しています。シフトレジスタを使用することで必要なGPIOピンの数を削減でき、効率的にディスプレイを制御することができます。

../_images/1.1.5_sch.png

配線図

以下の手順に従って回路を組み立ててください。

  1. ブレッドボード上に4桁7セグメントディスプレイと74HC595シフトレジスタを配置します。

  2. 74HC595の出力ピンをディスプレイの各セグメントに接続します。

  3. データ入力(SER、SDIとも呼ばれる)、シフトレジスタクロック(SRCLK)、ラッチレジスタクロック(RCLK)には、Fusion HAT+ のデジタルピンを使用します。

  4. ディスプレイの各セグメントに流れる電流を制限するため、抵抗を追加します。

../_images/1.1.5_bb.png

サンプルの実行

このチュートリアルで使用するすべてのサンプルコードは ai-lab-kit ディレクトリにあります。 以下の手順に従ってサンプルを実行してください。

cd ~/ai-lab-kit/python/
sudo python3 1.8_4-Digit.py

スクリプトを実行すると、4桁の7セグメントディスプレイに1秒ごとに1ずつ増加するカウンターが表示されます。現在のカウンター値はコンソールにも出力されます。プログラムは Ctrl + C を押して停止するまで継続して動作します。


コード

以下のPythonコードは、ディスプレイの初期化、カウンターの更新、およびディスプレイ更新ループの管理を行います。

#!/usr/bin/env python3
from fusion_hat.pin import Pin, Mode
import time
import threading

# Define GPIO pins for the 74HC595 shift register
SDI = Pin(17,mode=Mode.OUT)   # Serial Data Input
RCLK = Pin(4,mode=Mode.OUT)  # Register Clock
SRCLK = Pin(27,mode=Mode.OUT) # Shift Register Clock

# Define GPIO pins for digit selection on the 7-segment display
placePin = [Pin(pin,mode=Mode.OUT) for pin in (23, 24, 25, 12)]

# Define segment codes for numbers 0-9 for the 7-segment display
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

counter = 0  # Initialize counter for display
timer1 = 0   # Initialize timer for counter increment

def clearDisplay():
   """ Clear the 7-segment display. """
   for _ in range(8):
      SDI.high()
      SRCLK.high()
      SRCLK.low()
   RCLK.high()
   RCLK.low()

def hc595_shift(data):
   """ Shift a byte of data to the 74HC595 shift register. """
   for i in range(8):
      SDI.value(0x80 & (data << i))  # Set SDI high/low based on data bit
      SRCLK.high()  # Pulse the Shift Register Clock
      SRCLK.low()
   RCLK.high()  # Latch data on the output by pulsing Register Clock
   RCLK.low()

def pickDigit(digit):
   """ Select a digit for display on the 7-segment display. """
   for pin in placePin:
      pin.low()  # Turn off all digit selection pins
   placePin[digit].high()  # Turn on the selected digit

def timer():
   """ Timer function to increment the counter every second. """
   global counter, timer1
   timer1 = threading.Timer(1.0, timer)  # Reset timer for next increment
   timer1.start()
   counter += 1  # Increment counter
   print("%d" % counter)  # Print current counter value

def setup():
   """ Setup initial state and start the timer. """
   global timer1
   timer1 = threading.Timer(1.0, timer)  # Initialize and start the timer
   timer1.start()

def loop():
   """ Main loop to update the 7-segment display with counter value. """
   global counter
   while True:
      for i in range(4):  # Loop through each digit
            clearDisplay()  # Clear display before setting new digit
            pickDigit(i)    # Select digit for display

            # Choose the digit of counter to display
            digit = (counter // (10 ** (3-i))) % 10

            hc595_shift(number[digit])  # Shift digit value to 74HC595
            time.sleep(0.001)  # Short delay for display stability

def destroy():
   """ Cleanup GPIO resources and stop timer on exit. """
   global timer1
   timer1.cancel()  # Stop the timer
   for device in [SDI, RCLK, SRCLK] + placePin:
      device.close()  # Close GPIO devices

try:
   setup()  # Initialize the setup
   while True:
      loop()  # Start the main loop

except KeyboardInterrupt:
   # Handle script interruption (e.g., Ctrl+C)
   destroy()  # Cleanup resources on exit

このPythonスクリプトは、Raspberry Pi と 74HC595 シフトレジスタを使用して4桁の7セグメントディスプレイを制御します。実行すると次のように動作します。

  1. ディスプレイには1秒ごとに更新されるカウンターが表示されます。

  2. カウンターの値はデバッグ用としてコンソールにも出力されます。

ユーザーが Ctrl+C を押してスクリプトを停止するまで、プログラムは継続してカウンターを増加させながら動作します。


コードの解説

  1. GPIOピンの初期化

    シフトレジスタおよび桁選択用のGPIOピンを設定します。

    # Define GPIO pins for the 74HC595 shift register
    SDI = Pin(17,Pin.OUT)   # Serial Data Input
    RCLK = Pin(4,Pin.OUT)  # Register Clock
    SRCLK = Pin(27,Pin.OUT) # Shift Register Clock
    
    # Define GPIO pins for digit selection on the 7-segment display
    placePin = [Pin(pin,mode=Mode.OUT) for pin in (23, 24, 25, 12)]
    
  2. セグメントコード

    number 配列は、0〜9の各数字に対応するバイナリ表現を定義しています。

    number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
    
  3. ディスプレイ更新処理

    loop 関数は各桁を順番に選択し、対応するデータを送信してディスプレイを継続的に更新します。

    def loop():
       global counter
       while True:
          for i in range(4):
             clearDisplay()
             pickDigit(i)
             digit = (counter // (10 ** (3-i))) % 10
             hc595_shift(number[digit])
             time.sleep(0.001)
    
  4. カウンター更新

    timer 関数は1秒ごとにカウンターを増加させます。

    def timer():
       global counter, timer1
       timer1 = threading.Timer(1.0, timer)
       timer1.start()
       counter += 1
       print("%d" % counter)
    
  5. クリーンアップ

    destroy 関数はプログラム終了時にタイマーを停止し、GPIOリソースを解放します。

    def destroy():
       """ Cleanup GPIO resources and stop timer on exit. """
       global timer1
       timer1.cancel()  # Stop the timer
       for device in [SDI, RCLK, SRCLK] + placePin:
          device.close()  # Close GPIO devices
    

トラブルシューティング

  1. ディスプレイに何も表示されない

    • 原因: 配線ミス、またはGPIOピン設定の誤り。

    • 解決方法: 74HC595シフトレジスタへの接続を再確認し、GPIOピン(17、4、27)が定義されている変数( SDIRCLKSRCLK )と一致していることを確認してください。

  2. 数字が正しく更新されない

    • 原因: タイミングの問題、またはマルチプレクス処理の設定ミス。

    • 解決方法: loop() 関数内の time.sleep(0.001) が、ディスプレイを安定して更新するのに十分であることを確認してください。

  3. カウンターが予期せずリセットされる

    • 原因: timer1 のスレッドタイマーが正しく動作していない可能性があります。

    • 解決方法: setup() 関数がメインの loop() の前に実行され、タイマーが正しく開始されていることを確認してください。

  4. KeyboardInterrupt が機能しない

    • 原因: 割り込み時に destroy() 関数が正しく実行されていない可能性があります。

    • 解決方法: destroy() 内ですべてのGPIOデバイスが適切に閉じられていること、および except KeyboardInterrupt ブロック内で呼び出されていることを確認してください。


発展アイデア

  1. カウンター動作のカスタマイズ

    カウンターをカウントダウンに変更したり、特定の値でリセットするようにしたり、特定のパターンを表示するように変更できます。

  2. マルチモード表示

    以下のような表示モードを追加できます。

    • 固定メッセージ表示

    • カウンター表示と事前定義メッセージの交互表示

  3. カウンター速度の変更

    ユーザーがカウンターの増加速度を動的に変更できるようにします。

    speed = float(input("Enter counter speed in seconds: "))
    timer1 = threading.Timer(speed, timer)
    
  4. リアルタイムクロック

    カウンターの代わりにリアルタイムクロックを表示するように変更します。

    from datetime import datetime
    now = datetime.now()
    counter = now.hour * 100 + now.minute  # Display as HHMM
    

まとめ

このプロジェクトでは、74HC595シフトレジスタとGPIOプログラミングを使用して4桁7セグメントディスプレイを制御する方法を紹介しました。ここで学んだ技術は、より複雑な表示装置やインタラクティブシステムの開発にも応用することができます。