.. note::

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

    **参加する理由は？**

    - **エキスパートサポート**：コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決します。
    - **学び＆共有**：ヒントやチュートリアルを交換してスキルを向上させましょう。
    - **独占的なプレビュー**：新製品の発表や先行プレビューに早期アクセスしましょう。
    - **特別割引**：最新製品の独占割引をお楽しみください。
    - **祭りのプロモーションとギフト**：ギフトや祝日のプロモーションに参加しましょう。

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

.. _1.1.4_py_pi5:

1.1.4 7セグメントディスプレイ
=============================

概要
-----------------

7セグメントディスプレイを制御して、0から9およびAからFまでの数字を表示してみましょう。

必要な部品
------------------------------

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

.. image:: ../python_pi5/img/1.1.4_7_segment_list.png

一式を購入するのが便利です、こちらがリンクです： 

.. list-table::
    :widths: 20 20 20
    :header-rows: 1

    *   - 名前	
        - このキットのアイテム
        - リンク
    *   - Raphael Kit
        - 337
        - |link_Raphael_kit|

以下のリンクから別々に購入することもできます。

.. list-table::
    :widths: 30 20
    :header-rows: 1

    *   - コンポーネントの紹介
        - 購入リンク

    *   - :ref:`cpn_gpio_board`
        - |link_gpio_board_buy|
    *   - :ref:`cpn_breadboard`
        - |link_breadboard_buy|
    *   - :ref:`cpn_wires`
        - |link_wires_buy|
    *   - :ref:`cpn_resistor`
        - |link_resistor_buy|
    *   - :ref:`cpn_7_segment`
        - |link_7segment_buy|
    *   - :ref:`cpn_74hc595`
        - |link_74hc595_buy|


回路図
---------------------

74HC595のST_CPピンをRaspberry PiのGPIO18に、SH_CPをGPIO27に、DSをGPIO17に接続し、LEDセグメントディスプレイの8つのセグメントに並列出力ポートを接続します。

SH_CP（シフトレジスタのクロック入力）が立ち上がりエッジのときにDSピンへデータを入力し、ST_CP（メモリのクロック入力）が立ち上がりエッジのときにメモリレジスタにデータを入力します。その後、Raspberry PiのGPIOを介してSH_CPとST_CPの状態を制御して、シリアルデータ入力を並列データ出力に変換し、Raspberry PiのGPIOを節約してディスプレイを駆動できます。

============ ======== ===
T-Board Name physical BCM
GPIO17       Pin 11   17
GPIO18       Pin 12   18
GPIO27       Pin 13   27
============ ======== ===

.. image:: ../python_pi5/img/1.1.4_7_segment_schematic.png


実験手順
------------------------------

**ステップ1:** 回路を組み立てます。

.. image:: ../python_pi5/img/1.1.4_7-Segment_circuit.png

**ステップ2:** コードのフォルダに移動します。

.. raw:: html

   <run></run>

.. code-block::

    cd ~/raphael-kit/python-pi5

**ステップ3:** 実行します。

.. raw:: html

   <run></run>

.. code-block::

    sudo python3 1.1.4_7-Segment_zero.py

コードを実行した後、7セグメントディスプレイが0から9、AからFまで表示されるのを確認できます。

.. warning::

    エラー メッセージ ``RuntimeError: Cannot determine SOC peripheral base address`` が表示された場合は、 :ref:`faq_soc` を参照してください。

**コード**

.. note::
    以下のコードは **変更/リセット/コピー/実行/停止** することができます。ただし、それを行う前に「raphael-kit/python_5」というソースコードのパスに移動する必要があります。コードを変更した後、そのまま実行して効果を確認できます。問題がないことを確認したら、修正されたコードをコピーするためのCopyボタンを使用し、ターミナルで「nano」コマンドを使用してソースコードを開き、コードを貼り付けることができます。

.. raw:: html

    <run></run>

.. code-block:: python

   #!/usr/bin/env python3
   from gpiozero import OutputDevice
   from time import sleep

   # GPIO pins connected to 74HC595 shift register
   SDI = OutputDevice(17)   # Serial Data Input
   RCLK = OutputDevice(18)  # Memory Clock Input (Register Clock)
   SRCLK = OutputDevice(27) # Shift Register Clock

   # Hexadecimal digit codes for a common cathode 7-segment display
   segCode = [
       0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,
       0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
   ]

   def hc595_shift(data):
       # Shift 8 bits of data into the 74HC595
       for bit in range(8):
           # Set SDI high or low based on data bit
           SDI.value = 0x80 & (data << bit)
           # Trigger shift register clock
           SRCLK.on()
           sleep(0.001)
           SRCLK.off()
       # Latch data to output by triggering memory clock
       RCLK.on()
       sleep(0.001)
       RCLK.off()

   def display_all_on():
       # Function to turn all segments on (for common cathode 7-segment display)
       all_on_code = 0x3f
       hc595_shift(all_on_code)
       print("Displaying all segments on")

   try:
       while True:
           # Display each hexadecimal digit on 7-segment display
           for code in segCode:
               hc595_shift(code)  # Shift the code into 74HC595
               # Print the displayed segment code
               print(f"Displaying segCode[{segCode.index(code)}]: 0x{code:02X}")
               sleep(0.5)  # Pause between displaying each digit

   except KeyboardInterrupt:
       # Gracefully handle script interruption (e.g., Ctrl+C)
       pass

**コードの説明**

#. このスニペットはプロジェクトに必要なクラスをインポートします。 ``gpiozero`` から ``OutputDevice`` は、GPIOピンに接続されたハードウェアコンポーネントを制御するために、 ``time`` から ``sleep`` は遅延を追加するために使用されます。

   .. code-block:: python

       #!/usr/bin/env python3
       from gpiozero import OutputDevice
       from time import sleep

#. SDI、RCLK、SRCLKは、74HC595のシリアルデータ入力、メモリクロック入力（レジスタクロック）、シフトレジスタクロックピンに対応しています。

   .. code-block:: python

       # GPIO pins connected to 74HC595 shift register
       SDI = OutputDevice(17)   # Serial Data Input
       RCLK = OutputDevice(18)  # Memory Clock Input (Register Clock)
       SRCLK = OutputDevice(27) # Shift Register Clock

#. ``segCode`` は、7セグメントディスプレイに表示する各デジットの16進数コードを含む配列です。

   .. code-block:: python

       # Hexadecimal digit codes for a common cathode 7-segment display
       segCode = [
           0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,
           0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
       ]

#. この関数は、データを74HC595に8ビットシフトします。それは各ビットを ``SDI`` に連続的に入力し、ビットをシフトするために ``SRCLK`` をトグルし、データを出力にラッチするために ``RCLK`` を使用します。

   .. code-block:: python

       def hc595_shift(data):
           # Shift 8 bits of data into the 74HC595
           for bit in range(8):
               # Set SDI high or low based on data bit
               SDI.value = 0x80 & (data << bit)
               # Trigger shift register clock
               SRCLK.on()
               sleep(0.001)
               SRCLK.off()
           # Latch data to output by triggering memory clock
           RCLK.on()
           sleep(0.001)
           RCLK.off()

#. この関数は、ディスプレイのすべてのセグメントをオンにします。これは、共通カソードの7セグメントディスプレイ用です。

   .. code-block:: python

       def display_all_on():
           # Function to turn all segments on (for common cathode 7-segment display)
           all_on_code = 0x3f
           hc595_shift(all_on_code)
           print("Displaying all segments on")

#. メインループでは、 ``segCode`` の各コードが順番にディスプレイに送られ、各コードの間に遅延があります。

   .. code-block:: python

       try:
           while True:
               # Display each hexadecimal digit on 7-segment display
               for code in segCode:
                   hc595_shift(code)  # Shift the code into 74HC595
                   # Print the displayed segment code
                   print(f"Displaying segCode[{segCode.index(code)}]: 0x{code:02X}")
                   sleep(0.5)  # Pause between displaying each digit

#. この部分のコードは、スクリプトの中断（Ctrl+Cなど）を優雅に処理します。

   .. code-block:: python

       except KeyboardInterrupt:
           # Gracefully handle script interruption (e.g., Ctrl+C)
           pass
