SunFounder Da Vinci Kit for Raspberry Pi

SunFounder Vinci Kitをお選びいただき、ありがとうございます。

注釈

このドキュメントは以下の言語で利用可能です。

ご希望の言語でドキュメントにアクセスするために、それぞれのリンクをクリックしてください。

Da Vinciキットについて

このDa Vinciキットは、Raspberry Pi 世代4モデルB、世代3モデA+、世代3モデルB+、世代3モデルB、世代2モデルB、世代1モデルB+、世代1モデA+、ゼロWおよびゼロに適用される。さまざまな興味深い現象を作成するのに役立つさまざまな部品とチップが含まれており、実験の指示に従って操作すると達成できる。このプロセスでは、プログラミングに関する基本的な知識を習得できる。また、より多くのアプリケーションを自分で探索することもできる。さあ、未知の世界を探そう!

もし、私たちが持っていない別のプロジェクトを学びたい場合は、お気軽にメールをお送りください。

電子メール:cs@sunfounder.com

部品一覧

パッケージを開封した後、部品の数量が製品の説明に一致しているかどうか、およびすべての部品が良好な状態にあるかどうかを確認してください。

_images/image4.jpeg _images/image6.png _images/image8.jpeg _images/image9.jpeg

前書き

DaVinciキットはプロジェクトのスケジュールを立てたインテリジェントな初心者に適した基本的なキットである。26の汎用の入力および出力部品とモジュール、およびプログラミング学習で友好的な支援を提供できる多くの基本的な電子装置(抵抗器、コンデンサなど)が含まれている。

このキットをマスターすることで、Raspberry Piの実装方法、Bash shell とGPIOについての知識など、Raspberry Piの基本的な知識を学ぶことができる。これらの知識を理解した上、プログラミングを開始できる。

ハードウェアに関する知識がない場合は、キットに関するこのドキュメントでは、26回の基本的なI/Oレッスンと4つの簡単な実例を含む30回のレッスンを参照と学習のために提供する。これらのコースの配置は難易度ではなく、実際の機能に基づいていることに注意してください。ニーズに応じて、対応するコースを見つけることができる。つまり、コース全体を読み終えていないく、言及した部品の使用方法を習得していない場合でも、このドキュメントは将来の実用的なプロジェクトを完了させるためのガイドとして重要な役割を果たす。

我々はあなたのプロジェクトを楽しみにしており、このドキュメントを読んでいる間にフォーラムであなたの成果や創造を共有できることを願っている。

準備

この章では、まずラズベリーパイの起動方法を学びます。内容には、オペレーティングシステム、ラズベリーパイネットワークをインストールする方法とターミナルの開き方が含まれます。

注釈

完全なチュートリアルは、ラズベリーパイの公式サイト: raspberry-pi-setting-up.

ラズベリーパイがセットアップされている場合は、この部分をスキップして次の章に進むことができます。

何が必要?

必要なものなど

Raspberry Pi

Raspberry Piは低価格のクレジットカード サイズのコンピューターで、コンピューターのモニターまたはテレビに接続し、標準のキーボードとマウスを使用します。 Raspberry Piはあらゆる年齢の人々がコンピュータを利用し、Scratch や Python などの言語でプログラミングする方法を学ぶことを可能にする、有能な小さなデバイスです。

_images/image10.jpeg

電源アダプター

電源コンセントに接続するためにRaspberry Piには(スマホなどと同じ)マイクロUSBポートがあります。 電源容量は少なくとも2.5A/h以上の製品が必要です。

マイクロSDカード

Raspberry PiではRaspberry Pi OSとユーザーのデータを保存するためのマイクロSDカードが必要です。 通常のパソコンのSSDに当たります。最低でも8GB以上の容量のマイクロSDカードが必要です。

その他

ディスプレイ

Raspberry Piのデスクトップを表示するにはHDMI端子付きのテレビ画面かパソコン用のディスプレイが必要になります。 画面側にスピーカーが内蔵されている場合は音もそこから再生する事ができます。

マウスとキーボード

Raspberry Pi本体の操作のためにはUSBキーボードとUSBマウスも必要です。なおUSBアダプタ付きの無線マウスとキーボードも利用可能です。

HDMIケーブル

Raspberry Piには最新のテレビやディスプレイ用のHDMI出力ポートがあります。モデルによって使えるケーブルが異なるので確認してください。 またモニターが古くDVIまたはVGAポートしかない場合は適切な変換器を使用する必要があります。

ケース

Raspberry Piは専用ケースに入れることができます。 これによりデバイスを保護できますが、利用するロボットキットなどにはケースが付属していたりしますので必要かどうか確認してください。

イヤフォン出力

Raspberry Piには3.5mmのイヤフォン。ジャックが装備されておりモニターにスピーカーが内蔵されていない場合にイヤフォンやPC用外付けスピーカーなどが利用可能です。 こちらもロボットハットなどにはスピーカーを内蔵しておりますのでキットの内容をご確認ください。

Raspberry pi OSのインストール

必要なもの

  • Raspberry Pi 本体

  • PC(Windows Mac Linux/UNIX)

  • マイクロSDカード 8GB以上のもの

ステップ1

Raspberry Pi専用にSDカード書き込みツールが用意されました。Mac、WindowsならびにUbuntu 18.04で動作しますので、ほとんどの方にとって最も簡単なRaspberry pi用のSDカードの作成方法です。

ダウンロードページにアクセスしてください: https://www.raspberrypi.org/software/

お使いのパソコン用のRaspberry Pi Imagerのリンクをクリックしダウンロードし、完了したらそれをクリックしてインストーラーを起動します。

_images/image11.png

ステップ2

インストーラーを起動するとOSがインストーラーの実行を禁止しようとする場合があります。 たとえば、Windows では次のメッセージが表示されます。

このポップアップが表示された場合は、[More info] をクリックしてから [Run anyway] をクリックし指示に従ってRaspberry Pi Imagerをインストールします。

_images/image12.png

ステップ3

SDカードをパソコンのSDカード スロットに挿入します。(SDカードスロットが無いパソコンの場合USBマイクロSDカードアダプターを使用してください) SDカードのフォーマットなどのメニュー画面が表示された場合、それらは無視して閉じてください。

ステップ4

警告

Raspberry Pi OS を Debian Bullseye にアップグレードすると、一部の機能が動作しなくなるため、Debian Buster バージョンを引き続き使用することをお勧めします。

Raspberry Pi Imagerで、 CHOOSE OS から Raspberry Pi OS(other) を選択してクリックします。

_images/3d33.png

新しく開いたページの最後までスクロールすると Raspberry Pi OS(Legacy)Raspberry Pi OS Lite(Legacy) が表示されます。これらの違いはデスクトップ(GUI環境:普段から馴染みのあるマウスで操作できる画面)の有る/無しの違いです。 Raspberry Pi OS(Legacy) をインストールすることをお勧めします。これによりRaspberry Piデスクトップにアクセスしてカメラで捉えている映像をリアルタイムで見ることができるようになります。

_images/3d34.png

ステップ5

使用するSDカードを選択します。

_images/image14.png

ステップ6

設定 ボタン(画面右下のギアマーク:OSを選択すると表示される)をクリックして 詳細オプション ページを開き、SSHを有効にしてWi-Fiを設定します。 最低これら2つの項目を設定する必要があり他の項目は選択に応じて異なりますがパスワードはここで設定しておくと楽です。 このカスタマイズ オプションを常に使用するように選択できます(次回利用時のデフォルトになる)。

_images/image15.png

下にスクロールしてWi-Fiの設定を完了し SAVE をクリックします。

注釈

wifi country には、2 文字の ISO/IEC alpha2 コード を設定する必要があります。

日本国内で使用しているならば「JP」と設定してください。

_images/image16.png

ステップ7

書き込む ボタンをクリックしてください。

_images/image17.png

ステップ8

現在SDカードにファイルが保存されている場合はそれらのファイルを削除してしまわないように、事前にファイルをバックアップすることをお勧めします。 バックアップするファイルがない場合は、[ はい ] をクリックします。

_images/image18.png

ステップ9

しばらく待つと、次のウィンドウが表示され、書き込みが完了したことを示します。 そのままSDカードを取り出してRaspberry Pi Imagerを終了させます。

_images/image19.png

Raspberry Piの設定

モニターに接続できる場合

PC用のモニター画面(あるいはHDMI入力のあるテレビ)があればRaspberry Piの操作は簡単です。

必要なもの

  • Raspberry Pi 3または4

  • 1 * 電源アダプター

  • 1 * マイクロSDカード

  • 1 * モニター用電源アダプター(必要ならば)

  • 1 * HDMIケーブル

  • 1 * モニター(もしくはTV)

  • 1 * マウス

  • 1 * キーボード

  1. Raspberry Pi OSをインストールしたSDカードを、Raspberry Piの底面にあるマイクロSDカード・スロットに挿入します。

  2. マウスとキーボードを接続します。

  3. モニターをRaspberry PiのHDMIポートに接続し、モニターの電源が壁のコンセントに差し込まれ電源が入っていることを確認します。

    注釈

    Raspberry Pi 4を使用する場合はモニターをHDMI0(電源ポートに最も近い方)に接続する必要があります。

  4. 電源アダプターを使用してRaspberry Piに電源を供給します。 少し待つとにRaspberry Pi OSデスクトップが表示されます。なおRaspberry piには電源スイッチがありませんので電源アダプターを接続するとそのまま起動します。

    _images/image20.png
モニターがない場合

モニターがない場合はRaspberry Piにリモートでログインできます。

SSHコマンドを適用してRaspberry PiのBash Shellを開くことができます。BashはLinuxの標準のデフォルト・シェルです。シェル自体はユーザーがUnix/Linuxを利用する際のコマンドラインインタプリタ(CLI)です。シェルを通して必要な作業のほとんどが行えます。

コマンド・ウィンドウを使用してRaspberry Piを利用するすることに満足できない場合はリモートデスクトップ機能を使用してGUIを利用してRaspberry Pi内のファイルを簡単に管理することもできます。

各システムの詳しいチュートリアルは下記をご覧ください。

Mac OS X ユーザ

しかしMacユーザーの場合は可能であれば一時的にでもモニター、キーボード、マウスをセットしてRspberry pi側のVNCの設定を行った方が楽です。 まずはその方法から説明いたします。

なお予め断っておきますが、この方法の場合MacとRaspberry piの間の通信は暗号化による保護がなされません。 実際の利用に際しては個人宅もしくは社内のネットワーク内での通信となるので保護がなくても問題にはならないでしょう。 しかし気になる方は別途記述するVNCアプリを導入してご利用ください。

Mac OS X ユーザーで一時的にモニター(あるいはTV)を利用できる方
  1. Raspberry Piにディスプレイ、マウス、キーボードを接続し、電源を入れる。図の番号に従ってメニューを選択します。

    _images/mac_vnc1.png
  2. 以下の画面が表示されるので Interfaces タブをクリックし、さらに VNCEnabled に設定してから画面右下の OK ボタンをクリックします。

    _images/mac_vnc2.png
  3. 画面右上に VNC のアイコンが表示されVNCサーバーが起動します。

    _images/mac_vnc3.png
  4. 表示された VNC アイコンをクリックしてVNC Serverウィンドウを表示し、さらに右上のメニューボタンをクリック、続いて Options をクリックします

    _images/mac_vnc4.png
  5. 以下の画面が表示されるのでオプションを変更します。

    _images/mac_vnc5.png

    Encryptionを Prefer offon に、Authenticationを VNC password に設定してください。 OK ボタンをクリックするとパスワードの入力画面が表示されるのでRaspberry piのパスワードと同じでも、別のパスワードでも構わないので入力して OK をクリックしてください。これでMacから接続できる準備が整いました。もうモニターなどは接続を外しても大丈夫です。

ここからはMac側での操作になります。

  1. ファインダーの移動メニューからサーバーへ接続を選択します。

    _images/mac_vnc10.png
  2. Raspberry pi のアドレスを入力します。以下のように Raspberri piの名前.local でアドレスを指定します。

    _images/mac_vnc11.png

    接続 ボタンをクリックします。

  3. パスワードを聞いてくるので入力してください。

    _images/mac_vnc12.png
  4. Raspberry pi のデスクトップが表示され、Mac上からそのまま操作ができるようになります。

    _images/mac_vnc13.png
Mac OS X ユーザーで一時的であってもモニター(あるいはTV)を利用できない方
  • SSHコマンドを適用してRaspberry PiのBash Shellを開くことができます。

  • BashはLinuxの標準のデフォルト・シェルです。

  • シェル自体はユーザーがUnix/Linuxを利用する際のコマンド(命令)です。

  • シェルを通して必要な作業のほとんどが行えます。

  • Raspberry pi 側の設定が終われば前述の Mac からファインダーを使ってRaspberry piのデスクトップにアクセスできます。

  1. Raspberry Pi への SSH 接続 ssh <username>@<hostname>.local と入力して リターンキー を押します。

    ssh pi@raspberrypi.local
    
    _images/mac_vnc14.png
  2. 最初にログインするときだけ以下のメッセージが表示されるので yes と入力してください。

    The authenticity of host 'raspberrypi.local (2400:2410:2101:5800:635b:f0b6:2662:8cba)' can't be established.
    ED25519 key fingerprint is SHA256:oo7x3ZSgAo032wD1tE8eW0fFM/kmewIvRwkBys6XRwg.
    This key is not known by any other names
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    
  3. Raspberry pi の パスワード を入力します。パスワードは入力しても表示されませんので入力を間違えないように注意してください。

    pi@raspberrypi.local's password:
    Linux raspberrypi 5.15.61-v8+ #1579 SMP PREEMPT Fri Aug 26 11:16:44 BST 2022 aarch64
    
    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.
    Last login: Thu Sep 22 12:18:22 2022
    pi@raspberrypi:~ $
    
  4. これでRaspberry piに正常にログインできましたので、MacからVNCでログイン出来るように設定します。まずはOSのアップデートを行います。以下のコマンドを入力します。

    sudo apt update
    sudo apt upgrade
    

    Do you want to continue? [Y/n] が表示されたら Y を入力します。

    アップデートが終わるまでしばし時間がかかりることがあります。(その時のアップデート量によります。)

  5. VNC を有効化して VNC サーバーを起動します。以下のコマンドを入力します。

    sudo raspi-config
    
  6. 以下の画面が表示されますので、キーボードの矢印キーで 3 Interface Options を選択してリターンキーを押します。

    _images/image2821.png
  7. 以下の画面が表示されますので、キーボードの矢印キーで P3 VNC を選択してリターンキーを押します。

    _images/image288.png
  8. 以下の画面が表示されますので、キーボードの矢印キーで <Yes> を選択してリターンキーを押します。

    _images/mac_vnc8.png
  9. 以下の画面が表示されますので、キーボードの矢印キーで <Ok> を選択してリターンキーを押します。

    _images/mac_vnc7.png
  10. 最後にキーボードの矢印キーで <Finish> を選択してリターンキーを押します。

    _images/mac_vnc6.png
  11. VNCサーバーが起動するようになったので、今度はMacからの接続様の設定を変更します。

    sudo nano /etc/vnc/config.d/common.custom
    

    以下のような画面になるので Authentication=VncAuth と入力し、 Ctl + o を押し、リターンキーを押し、さらに Ctl + x を押します。

    _images/mac_vnc15.png
  12. さらにMacからVNCでログインするときのパスワードを設定します。Raspberry pi のパスワードと同じで問題はないはずです。

    sudo vncpasswd -service
    password: (パスワードを入力)
    
  13. これで設定が出来ましたので設定を反映させるためにRaspberry piを再起動します。

    sudo sudo reboot
    
  14. ファインダーの移動メニューからサーバーへ接続を選択します。

    _images/mac_vnc10.png
  15. Raspberry pi のアドレスを入力します。以下のように Raspberri piの名前.local でアドレスを指定します。

    _images/mac_vnc11.png

    Connect ボタンをクリックします。

  16. パスワードを聞いてくるので入力してください。

    _images/mac_vnc12.png
  17. Raspberry pi のデスクトップが表示され、Mac上からそのまま操作ができるようになります。

    _images/mac_vnc13.png
Windows ユーザ

Windowsユーザーの場合は Windows PowerShell を利用できます。

  1. windows + R キーを押し入力ウィンドウに powershell と入力してPowerShellを起動してください。

    _images/sp221221_135900.png
  2. 後は Mac や Linux のターミナル操作と同じで開かれたPowerShellの画面で ssh <username>@<hostname>.local と入力します。

    ssh pi@raspberrypi.local
    
  3. 以下のメッセージが表示されます.

    The authenticity of host 'raspberrypi.local (192.168.6.116)' can't be established.
    ECDSA key fingerprint is SHA256:7ggckKZ2EEgS76a557cddfxFNDOBBuzcJsgaqA/igz4.
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    

    "yes" と入力してください。

  4. パスワードを入力してください。 (デフォルトの場合は raspberry です。)

    注釈

    When you input the password, the characters do not display on window accordingly, which is normal. What you need is to input the correct password.

  5. これでRaspberry piに正常にログインできましたので、OSのアップデートを行います。

    _images/sp221221_140628.png
リモート・デスクトップ

VNCでリモート・デスクトップを利用できます。

VNCサービスの有効化

VNCは標準でインストールされておりますが、デフォルトでは無効化されていますので、有効化する必要があります。

  1. 以下のコマンドを入力します:

    $ sudo raspi-config
    
    _images/image287.png
  2. 3Interfacing Options を下矢印で選択してリターン機を押します。

    _images/image2821.png
  3. P3 VNC を矢印キーで選択してリターンキーを押します。

    _images/image288.png
  4. Yes → OK -> Finish と順番に選択して設定を終了させます。

    _images/image289.png

VNCによるログイン

  1. 先ず VNC Viewer をダウンロードしてファイルを開き、指示に従いインストールします。インストールしたら起動します。

  2. メニューのファイルから New connection を選択します。

    _images/image290.png
  3. Raspberry piのIPアドレスを入力します。 Name には好きな名前を付けます。(Raspberry piの名前と同じが良いかもしれません) 「OK」をクリックします。

    _images/image291.png
  4. 作成した 接続先 をダブルクリックします。:

    _images/image292.png
  5. ログイン・ユーザー名 ( pi ) とSDカードを作成した際に指定したパスワード (デフォルトでは raspberry )を入力します。

    _images/image293.png
  6. Raspberry Piのデスクトップ画面が表示されるはずです。:

    _images/image294.png
Linux / UNIX ユーザー
  1. ターミナルを開いて ssh <username>@<hostname>.local と入力してください。

    ssh pi@raspberrypi.local
    
  2. 以下のメッセージが表示されます。

    The authenticity of host 'raspberrypi.local (192.168.6.116)' can't be established.
    ECDSA key fingerprint is SHA256:7ggckKZ2EEgS76a557cddfxFNDOBBuzcJsgaqA/igz4.
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    
  3. "yes" と入力してください。

    _images/mac-ssh-login.png
  4. パスワードを入力してください。 (デフォルトの場合は raspberry です。)

  5. これでRaspberry piに正常にログインできましたので、OSのアップデートを行います。

    _images/mac-ssh-terminal.png

ライブラリ

Raspberry Piを使用したプログラミングでは、wiringPiとRPi.GPIOという2つの重要なライブラリが使用されている。Raspberry PiのRaspbian OSイメージはデフォルトでそれらを実装するため、直接使用できる。

RPi.GPIO

Pythonユーザーの場合、RPi.GPIOが提供するAPIを使用してGPIOをプログラミングできる。

RPi.GPIOは、Raspberry Pi GPIOチャネルを制御するモジュールである。このパッケージはRaspberry PiでGPIOを制御するクラスを提供する。例とドキュメントについては、次のURLにアクセスしてください: http://sourceforge.net/p/raspberry-gpio-python/wiki/Home/

RPi.GPIOが実装されているかどうかをテストするには、Pythonを入力する:

python
_images/image27.png

Python CLIで、「import RPi.GPIO」と入力する。エラーが表示されない場合は、RPi.GPIOの実装が完了したと意味する。

import RPi.GPIO
_images/image28.png

Python CLIを終了する場合は、次を入力する:

exit()
_images/image29.png

WiringPiをインストールして確認する

wiringPi は Raspberry Pi 用の C 言語 GPIO ライブラリです。 GUN Lv3に準拠。 wiringPi の機能は、Arduino の配線システムに似ています。 これにより、Arduino に精通しているユーザーは、wiringPi をより簡単に使用できるようになります。

wiringPi には、Raspberry Pi のさまざまなインターフェイスを制御できるようにする多数の GPIO コマンドが含まれています。

次のコマンドを実行して wiringPi ライブラリをインストールしてください。

sudo apt-get update
git clone https://github.com/WiringPi/WiringPi
cd WiringPi
./build

次の手順で、wiringPi ライブラリが正常にインストールされたかどうかをテストできます。

gpio -v
_images/image30.png

次のコマンドで GPIO を確認します。

gpio readall
_images/image31.png

配線Piの詳細については、 WiringPi を参照してください。

GPIO拡張ボード

コマンドの学習を開始する前に、最初にRaspberry Piのピンについて詳しく知る必要がある。これは、その後の研究の鍵となる。

GPIO拡張ボードによってRaspberry Piのピンをブレッドボードに簡単に引き出して、頻繁に挿入または引き抜きによるGPIOの損傷を防止できる。これは、Raspberry PiモデルB +、世代2モデルBおよび世代3、4モデルBに適用する40ピンGPIO拡張ボードとGPIOケーブルである。

_images/image32.png

ピン番号

Raspberry Piのピンには、命名方法が三つあり、つまり、wiringPi、BCM、およびボードである。

これらの命名方法の中で、40ピンGPIO拡張ボードは命名方法BCMを使用している。ただし、I2CポートやSPIポートなどの一部の特別なピンでは、付属の名前を使用する。

次の表は、WiringPi、ボード、およびGPIO拡張ボード上の各ピンの固有の命名方法を示している。たとえば、GPIO17の場合、ボードの命名方法によると11で、wiringPiの命名方法によると0で、固有の命名方法によるとGPIO0である。

注釈

1)C言語では、使用されている命名方法はWiringPiである。

2)Python言語では、適用される命名方法はBoardとBCMであり、関数GPIO.setmode()を使用してそれらを設定します。

_images/gpio_board.png

コードをダウンロードする

コードをダウンロードする前に、サンプルコードはRaspberry Pi OS のみ でテストすることに注意してください。ダウンロードには二つの方法がある:

方法1:git cloneを使用する(推奨)

Raspberry Piにログインし、ディレクトリを /home/pi に変更する。

cd /home/pi/

注釈

現在のパスから目的のディレクトリに移動するcd。非公式には、パス /home/pi/ に移動する。

GitHubからリポジトリを複製する。

git clone https://github.com/sunfounder/davinci-kit-for-raspberry-pi.git

方法2:コードをダウンロードする。

githubからソースコードをダウンロードする: https://github.com/sunfounder/davinci-kit-for-raspberry-pi.

_images/image33.png

1 出力 (Pi 5用ではない)

1.1 ディスプレイ

1.1.1 点滅LED

前書き

このレッスンでは、プログラミングによってLEDを点滅させる方法を学習する。設定により、LEDは一連の興味深い現象を生成できる。今、行動しよう。

部品
_images/blinking_led_list.png

注釈

スムーズに進めるには、独自のRaspberry Pi、TFカード、およびRaspberry Piの電源を用意する必要がある。

原理

ブレッドボード

ブレッドボードは、電子装置のプロトタイピングの構築基盤である。それは回路設計を完了する前に、回路を迅速に作って、テストするために使用される。また、上記の部品をICや抵抗器、ジャンパー線などのように挿入できる多くの穴が搭載されている。ブレッドボードを使用すると、部品を簡単に差し込んだり、取り外したりすることができる。

この写真は、full +ブレッドボードの内部構造を示している。ブレッドボード上のこれらの穴は互いに独立しているように見えるが、実際には内部で金属ストリップを介して互いに接続されている。

_images/image41.png

LED

LEDは一種のダイオードである。LEDの長いピンが正極に接続され、短いピンが負極に接続されている場合にのみ、LEDが点灯する。

image42image43

LEDを電源に直接接続することはできないため、部品に損傷を与える可能性がある。160Ω以上の抵抗(5V動作電圧)は、LEDの回路に直列に接続する必要がある。

抵抗器

抵抗器は、分岐電流を制限できる電子素子である。固定抵抗器は抵抗値を変更できない抵抗器の一種であるが、ポテンショメータまたは可変抵抗器の抵抗値は調整できる。

このキットには固定抵抗器が適用される。回路では、接続された部品を保護することは重要である。次の図は、実際の物体、220Ω抵抗器、および抵抗器汎用の二つの回路記号を示している。Ωは抵抗値の単位で、より大きな単位はKΩ、MΩなどである。それらの関係は次のように示している:1M= 1000KΩ、1KΩ=1000Ω。通常、抵抗値はマークされている。したがって、回路にこれらの記号が表示される場合、抵抗があることを意味する。

_images/image44.png

image45image46

抵抗器を使用する場合、まず抵抗値を知る必要がある。以下の二つの方法がある:抵抗の帯域を観察すること、またはマルチメーターを使用して抵抗を測定すること。より便利で迅速なので、一番目の方法をお勧めする。値を測定するには、マルチメーターを使用してください。

カードに示されているように、各色は数字を表している。

_images/image47.jpeg
回路図

この実験では、まず220Ωの抵抗器を陽極(LEDの長いピン)に接続し、それから抵抗器を3.3 Vの電源に接続し、LEDの陰極(短いピン)をRaspberry PiのGPIO17に接続する。したがって、LEDをオンにするには、GPIO17を低(0V)レベルにする必要がある。プログラミングを通じてこの現象を取得できる

注釈

Pin11 はRaspberry Piの左から11番目のピンを指し、それに対応する wiringPiBCM のピン番号は以下の表の通りです。

C言語関連のコンテンツでは、wiringPiでGPIO0を0と同等にする。Python言語関連のコンテンツの中で、BCM 17は次の表のBCM列の17である。同時に、それらはRaspberry Piの11番目のピン-ピン11と同じである。

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

_images/image48.png
実験手順

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

_images/image49.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

  1. モニターを使用する場合は、次の手順を実行することをお勧めする。

/home/pi/ に入り、 davinci-kit-for-raspberry-pi フォルダーを見つけてください。

フォルダー内で C を見つけて右クリックし、** Open in Terminal** を選択する。

_images/image50.png

それから以下のようなウィンドウがポップアップされる。これで、コード 1.1.1_BlinkingLed.c のパスに入っていた。

_images/image51.png

次のレッスンでは、右クリックの代わりにコマンドを使用してコードファイルを入力する。ただし、お好みの方法を選択可能である。

  1. Raspberry Piにリモートでログインする場合、 cd を使用してディレクトリを変更する:

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.1.1/

注釈

この実験では、cdを使用してディレクトリをコードのパスに変更します。

どちらにしても、現在は C フォルダにいることになります。この2つの方法に基づくその後の手順は同じです。次に進みましょう。

ステップ3: コードをコンパイルする.

gcc 1.1.1_BlinkingLed.c -o BlinkingLed -lwiringPi

注釈

gcc は GNU Compiler Collection です。ここでは、C言語ファイル*1_BlinkingLed.c*をコンパイルし、実行ファイルを出力するような機能を持っています。

コマンドでは、 -o は出力を意味し( -o の直後の文字はコンパイル後のファイル名出力であり、 BlinkingLed という名前のEXEファイルがここで生成される)、 -lwiringPi はライブラリー のwiringPiをロードする( l はlibraryの省略形である)。

ステップ4: 前のステップで出力されたEXEファイルを実行する。

sudo ./BlinkingLed

注釈

GPIOを制御するには、コマンド sudo (superuser do)でプログラムを実行してください。コマンド ./ は現在のディレクトリを示している。コマンド全体は、現在のディレクトリで BlinkingLed を実行することである。

_images/image52.png

コードの実行後、LEDが点滅する。

注釈

実行しても動作しない場合、または「wiringPi.h: No such file or directory」というエラー プロンプトが表示される場合は、Cコードが機能していませんか? を参照してください。

コードファイル 1.1.1_BlinkingLed.c を編集する場合は、 Ctrl + C を押してコードの実行を停止する。次に、次のコマンドを入力してそれを開く:

nano 1.1.1_BlinkingLed.c

注釈

nanoはテキストエディターツールである。このコマンドは、このツールを通して、コードファイル 1.1.1_BlinkingLed.c を開くために使用される。

Ctrl + X を押して終了する。コードを修正した場合、変更を保存するかどうかを尋ねるプロンプトが表示される。 Y (保存)または N (保存しない)を入力する。 次に、 Enter キーを押して終了する。 ステップ3ステップ4 を繰り返して、修正後の効果を確認する。

_images/image53.png

コード

プログラムコードは次のように表示される:

#include <wiringPi.h>
#include <stdio.h>
#define LedPin      0
int main(void)
{
   // When initialize wiring failed, print message to screen
   if(wiringPiSetup() == -1){
      printf("setup wiringPi failed !");
      return 1;
   }
   pinMode(LedPin, OUTPUT);// Set LedPin as output to write value to it.
   while(1){
      // LED on
      digitalWrite(LedPin, LOW);
      printf("...LED on\n");
      delay(500);
      // LED off
      digitalWrite(LedPin, HIGH);
      printf("LED off...\n");
      delay(500);
   }
   return 0;
}

コードの説明

include <wiringPi.h>

ハードウェアドライブライブラリは、Raspberry PiのC言語用に設計されている。このライブラリを追加すると、ハードウェアの初期化、およびI/Oポート、PWMなどの出力に役立つ。

#include <stdio.h>

標準I/Oライブラリ。画面に表示されるデータの印刷に使用されるpintf機能は、このライブラリによって実現される。他にも多くのパフォーマンス機能がある。

#define LedPin 0

T_Extension BoardのGPIO17ピンは、wiringPiのGPIO0に対応している。GPIO0をLedPinに割り当て、LedPinは後のコードでGPIO0を表す。

if(wiringPiSetup() == -1){
    printf("setup wiringPi failed !");
    return 1;

これにより、wiringPiが初期化され、呼び出しのプログラムがwiringPiピン番号スキームを使用することになると想定される。

この関数を呼び出すには、ルート権限が必要である。配線の初期化に失敗すると、画面にメッセージが表示される。 関数「return」は現在の関数から飛び出すために使用される。main()関数で関数「return」を使用すると、プログラムが終了する。

pinMode(LedPin, OUTPUT);

LedPinを出力として設定し、値を書き込む。

digitalWrite(LedPin, LOW);

GPIO0を0V(低レベル)に設定SURU。LEDの陰極はGPIO0に接続されているため、GPIO0が低レベルに設定されるとLEDが点灯する。 それに反して、GPIO0を高レベルに設定すると(digitalWrite(LedPin、HIGH)):LEDが消灯する。

printf("...LED off\n");

printf関数は標準ライブラリ関数であり、その関数プロトタイプはヘッダーファイル「stdio.h」にあります。 呼び出しの一般的な形式は次のとおりです。 printf("フォーマット制御文字列"、出力テーブルの列)。 フォーマット制御文字列は、フォーマット文字列と非フォーマット文字列に分けられる出力フォーマットを指定するために使用されます。フォーマット文字列は「%」で始まり、 10進整数出力の場合は「%d」などのフォーマット文字が続きます。 フォーマットされていない文字列はプロトタイプとして印刷されます。 ここで使用されているのは、フォーマットされていない文字列であり、その後に改行文字である 「\n」 が続きます。これは、文字列を印刷した後の自動行折り返しを表します。

delay(500);

Delay (500) は、現在のHIGHまたはLOW状態を500ms維持する。

これは、プログラムを一定期間中断する機能である。また、プログラムの速度はハードウェアによって決まる。ここで、LEDをオンまたはオフにする。 遅延機能がない場合、プログラムはプログラム全体を非常に高速で実行し、継続的にループする。そのため、プログラムの作成とデバッグに役立つ遅延機能が必要である。

return 0;

通常、メイン関数の後ろに配置され、関数が正常に実行されると0を返すことを示す。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入り、それを実行する。

  1. モニターを使用する場合は、次の手順を実行することをお勧めする。

1.1.1_BlinkingLed.py を見つけて、ダブルクリックして開く。今、ファイルに入った。

ウィンドウで Run ->Run Module をクリックすると、次の内容が表示される。

実行を停止するには、右上の「X」ボタンをクリックして閉じるだけで、コードに戻る。コードを変更する場合は、Run Module (F5) をクリックする前に、まず保存しなければならない。 その後、結果を確認できる。

  1. Raspberry Piにリモートでログインする場合、次のコマンドを入力する:

cd /home/pi/davinci-kit-for-raspberry-pi/python

注釈

cd を使用して、この実験のコードのパスにディレクトリを変更できる。

ステップ3: コードを実行する。

sudo python3 1.1.1_BlinkingLed.py

注釈

ここでは sudo - superuser doとpythonは、Pythonでファイルを実行することを意味する。

コードの実行後、LEDが点滅する。

ステップ4: コードファイル 1.1.1_BlinkingLed.py を編集する場合は、 Ctrl + C を押してコードの実行を停止してください。それから次のコマンドを入力して1.1.1_BlinkingLed.pyを開く:

nano 1.1.1_BlinkingLed.py

注釈

nanoはテキストエディターツールである。このツールは、コマンドを使用してコードファイル1.1.1_BlinkingLed.pyを開く。

Ctrl + X を押して終了する。コードを修正した場合、変更を保存するかどうかを尋ねるプロンプトが表示される。 Y (保存)または N (保存しない)を入力する。

次に、 Enter を押して終了する。変更後の効果を確認するには、 nano 1.1.1_BlinkingLed.py をもう一度入力してください。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
LedPin = 17
def setup():
   # Set the GPIO modes to BCM Numbering
   GPIO.setmode(GPIO.BCM)
   # Set LedPin's mode to output,and initial level to High(3.3v)
   GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)
# Define a main function for main process
def main():
   while True:
      print ('...LED ON')
      # Turn on LED
      GPIO.output(LedPin, GPIO.LOW)
      time.sleep(0.5)
      print ('LED OFF...')
      # Turn off LED
      GPIO.output(LedPin, GPIO.HIGH)
      time.sleep(0.5)
# Define a destroy function for clean up everything after the script finished
def destroy():
   # Turn off LED
   GPIO.output(LedPin, GPIO.HIGH)
   # Release resource
   GPIO.cleanup()
# If run this script directly, do:
if __name__ == '__main__':
   setup()
   try:
      main()
   # When 'Ctrl+C' is pressed, the program destroy() will be  executed.
   except KeyboardInterrupt:
      destroy()

コードの説明

#!/usr/bin/env python3

システムがこれを検出すると、env設定でpythonの実装パスを検索し、対応するインタープリターを呼び出して操作を完了させる。 その目的は、ユーザーがPythonを/usr/binのデフォルトパスに実装することを防止することである。

import RPi.GPIO as GPIO

この方法で、RPi.GPIOライブラリをインポートし、変数GPIOを定義して、次のコードでRPI.GPIOを置き換える。

import time

次のプログラムの時間遅延機能を行うために、時間パッケージをインポートしなければならない。

LedPin = 17

LEDはT字型拡張ボードのGPIO17、つまりBCM 17に接続している。

def setup():
   GPIO.setmode(GPIO.BCM)
   GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)

LedPinのモードを出力に設定し、初期レベルを高(3.3v)に設定する。

RPi.GPIO内のRaspberry PiのIOピンに番号を付けるには、BOARDとBCM二つの番号付与方法がある。レッスンでは、使用しているのはBCM番号である。入力または出力として使用しているチャンネルをすべて設定する必要がある。

GPIO.output(LedPin, GPIO.LOW)

GPIO17(BCM17)を0V(低レベル)に設定する。LEDのカソードはGPIO17に接続されているため、LEDが点灯する。

time.sleep(0.5)

0.5秒の遅延。ここで、ステートメントはC言語の遅延機能に似ており、単位は秒である。

def destroy():
   GPIO.cleanup()

スクリプトの終了後にすべてを消去する破棄関数を定義する。

if __name__ == '__main__':
   setup()
   try:
      main()
   # When 'Ctrl+C' is pressed, the program destroy() will be  executed.
   except KeyboardInterrupt:
      destroy()

これは、コードの一般的な実行構造である。 プログラムの実行が開始されると、 setup() を実行してピンを初期化し、 main() 関数でコードを実行してピンを高レベルと低レベルに設定する。 「Ctrl + C」を押すと、プログラム destroy() が実行される。

現象画像
_images/image54.jpeg

1.1.2 RGB LED

前書き

このレッスンでは、これを使用してRGB LEDを制御し、さまざまな種類の色を点滅させる。

部品
_images/list_rgb_led.png
原理

PWM

パルス幅変調(PWM)は、デジタル手段でアナログ結果を取得するための技術である。 デジタル制御は、オンとオフを切り替える信号である方形波を作成するために使用される。 このオン/オフパターンは、信号がオンになる時間と信号がオフになる時間の部分を変更することにより、完全にオン(5ボルト)である時と完全にオフ(0ボルト)である時の間の電圧をシミュレートできる。 「オンタイム」の期間はパルス幅と呼ばれる。さまざまなアナログ値を取得するには、その幅を変更または変調できる。 このオン/オフパターンを何らかのデバイス、たとえばLEDで十分に速く繰り返すと、結果は次のようになる:信号はLEDの輝度を制御する0〜5vの安定した電圧である。

デューティサイクル

デューティサイクルは、信号が有効である1周期の割合である。期間とは、信号がオンとオフのサイクルを完了するのにかかる時間である。式として、デューティサイクルは次のように表示される:

_images/image56.png

ここで、 D はデューティサイクル、 T は信号がアクティブな時間、 P は信号の合計周期です。 したがって、60%のデューティサイクルは、信号が60%の時間オンであるが、40%の時間オフであることを意味します。 60%のデューティサイクルの「定刻」は、期間の長さに応じて、数分の1秒、1日、または1週間になることもあります。

_images/image57.jpeg

RGB LED

_images/rgb_led_sch.png

RGB LEDの3つの原色は、輝度によってさまざまな色に混ぜることができる。 LEDの輝度はPWMで調整可能である。Raspberry PiにはハードウェアPWM出力用のチャネルが1つしかないが、RGB LEDを制御するには3つのチャネルが必要である。 つまり、Raspberry PiのハードウェアPWMでRGB LEDを制御することは困難である。 幸いなことに、softPwmライブラリはプログラミングによってPWM(softPwm)をシミュレートする。 ヘッダーファイルsoftPwm.h(C言語ユーザー向け)をインクルードし、提供されるAPIを呼び出して、マルチチャネルPWM出力によってRGB LEDを簡単に制御するだけで、あらゆる種類の色を表示できる。

回路図

R、G、およびBのピンを電流制限抵抗器に接続した後、それぞれGPIO17、GPIO18、およびGPIO27に接続してください。LEDの最も長いピン(GND)は、Raspberry Piの接地に接続する。3つのピンに異なるPWM値が与えられると、RGB LEDは異なる色を表示する。

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

_images/rgb_led_schematic.png
実験手順

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

_images/image61.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.1.2/

ステップ3: コードをコンパイルする。

gcc 1.1.2_rgbLed.c -lwiringPi

注釈

命令「gcc」が実行されるときに「-o」が呼び出されない場合、EXEファイルは「a.out」と命名する。

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードを実行すると、RGBが赤、緑、青、黄色、ピンク、およびシアンを表示する。

コード

#include <wiringPi.h>
#include <softPwm.h>
#include <stdio.h>
#define uchar unsigned char
#define LedPinRed    0
#define LedPinGreen  1
#define LedPinBlue   2

void ledInit(void){
    softPwmCreate(LedPinRed,  0, 100);
    softPwmCreate(LedPinGreen,0, 100);
    softPwmCreate(LedPinBlue, 0, 100);
}

void ledColorSet(uchar r_val, uchar g_val, uchar b_val){
    softPwmWrite(LedPinRed,   r_val);
    softPwmWrite(LedPinGreen, g_val);
    softPwmWrite(LedPinBlue,  b_val);
}

int main(void){

    if(wiringPiSetup() == -1){ //when initialize wiring failed, printf messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }

    ledInit();
    while(1){
        printf("Red\n");
        ledColorSet(0xff,0x00,0x00);   //red
        delay(500);
        printf("Green\n");
        ledColorSet(0x00,0xff,0x00);   //green
        delay(500);
        printf("Blue\n");
        ledColorSet(0x00,0x00,0xff);   //blue
        delay(500);
        printf("Yellow\n");
        ledColorSet(0xff,0xff,0x00);   //yellow
        delay(500);
        printf("Purple\n");
        ledColorSet(0xff,0x00,0xff);   //purple
        delay(500);
        printf("Cyan\n");
        ledColorSet(0xc0,0xff,0x3e);   //cyan
        delay(500);
    }
    return 0;
}

コードの説明

#include <softPwm.h>

ソフトウェアのpwm機能を実現するために使用されるライブラリ。

void ledInit(void){
    softPwmCreate(LedPinRed,  0, 100);
    softPwmCreate(LedPinGreen,0, 100);
    softPwmCreate(LedPinBlue, 0, 100);
}

この機能は、ソフトウェアを使用してPWMピンを作成し、その周期を0x100us〜100x100usに設定することである。

関数 softPwmCreate(LedPinRed、0、100) のプロトタイプは次のとおりである:

int softPwmCreate(int pin,int initialValue,int pwmRange);
  • pin: ラズベリーパイの任意のGPIOピンは、PWMピンとして設定することができます。

  • initialValue: 初期パルス幅はinitialValueに100usを掛けたものである。

  • pwmRange: PWMの周期は、pwmRangeに100usを掛けたものである。

void ledColorSet(uchar r_val, uchar g_val, uchar b_val){
    softPwmWrite(LedPinRed,   r_val);
    softPwmWrite(LedPinGreen, g_val);
    softPwmWrite(LedPinBlue,  b_val);
}

この機能はLEDの色を設定する。RGBを使用すると、仮パラメータは赤の輝度の r_val 、緑の輝度の g_val 、青の輝度の b_val を表す。

関数 softPwmWrite(LedPinBlue, b_val) のプロトタイプは次のとおりである:

void softPwmWrite (int pin, int value) ;
  • pin: ラズベリーパイの任意のGPIOピンは、PWMピンとして設定することができます。

  • Value: PWMのパルス幅は、値の100usの倍数です。値は、以前に定義された pwmRange より小さく、pwmRange より大きい場合、値には固定値 pwmRange が与えられることに注意してください。

ledColorSet(0xff,0x00,0x00);

前に定義した関数を呼び出す。 LedPinRed に0xffを、 LedPinGreenLedPinBlue に0x00を書き込む。 このコードを実行すると、赤色のLEDのみが点灯する。他の色のLEDを点灯させる場合は、パラメーターを変更するだけである。

Python言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: 実行する。

sudo python3 1.1.2_rgbLed.py

コードを実行すると、RGBが赤、緑、青、黄色、ピンク、およびシアンを表示する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

# Set up a color table in Hexadecimal
COLOR = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF]
# Set pins' channels with dictionary
pins = {'Red':17, 'Green':18, 'Blue':27}


def setup():
    global p_R, p_G, p_B
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    # Set all LedPin's mode to output and initial level to High(3.3v)
    for i in pins:
        GPIO.setup(pins[i], GPIO.OUT, initial=GPIO.HIGH)

    # Set all led as pwm channel and frequece to 2KHz
    p_R = GPIO.PWM(pins['Red'], 2000)
    p_G = GPIO.PWM(pins['Green'], 2000)
    p_B = GPIO.PWM(pins['Blue'], 2000)

    # Set all begin with value 0
    p_R.start(0)
    p_G.start(0)
    p_B.start(0)

# Define a MAP function for mapping values.  Like from 0~255 to 0~100
def MAP(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

# Define a function to set up colors
# input color should be Hexadecimal with
# red value, blue value, green value.
def setColor(color):
# configures the three LEDs' luminance with the inputted color value .
    # Devide colors from 'color' veriable
    R_val = (color & 0xFF0000) >> 16
    G_val = (color & 0x00FF00) >> 8
    B_val = (color & 0x0000FF) >> 0
# these three lines are used for analyzing the col variables
# assign the first two values of the hexadecimal to R, the middle two assigned to G
# assign the last two values to B, please refer to the shift operation of the hexadecimal for details.

    # Map color value from 0~255 to 0~100
    R_val = MAP(R_val, 0, 255, 0, 100)
    G_val = MAP(G_val, 0, 255, 0, 100)
    B_val = MAP(B_val, 0, 255, 0, 100)

    # Change the colors
    p_R.ChangeDutyCycle(R_val)
    # Assign the mapped duty cycle value to the corresponding PWM channel to change the luminance.
    p_G.ChangeDutyCycle(G_val)
    p_B.ChangeDutyCycle(B_val)

    print ("color_msg: R_val = %s,  G_val = %s,     B_val = %s"%(R_val, G_val, B_val))

def main():
    while True:
        for color in COLOR:# Assign every item in the COLOR list to the color respectively and change the color of the RGB LED via the setColor() function.
            setColor(color)# change the color of the RGB LED
            time.sleep(0.5)# set delay for 0.5s after each color changing. Modify this parameter will changed the LED's color changing rate.

def destroy():
    # Stop all pwm channel
    p_R.stop()
    p_G.stop()
    p_B.stop()
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()

コードの説明

p_R = GPIO.PWM(pins['Red'], 2000)
p_G = GPIO.PWM(pins['Green'], 2000)
p_B = GPIO.PWM(pins['Blue'], 2000)

p_R.start(0)
p_G.start(0)
p_B.start(0)

GPIO.PWM() 関数を呼び出して、赤、緑、青をPWMピンとして定義し、 PWMピンの周波数を2000Hzに設定してから、 Start() 関数を使用して初期デューティサイクルをゼロに設定する。

def MAP(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

値をマッピングするためのMAP関数を定義する。 たとえば、x = 50、in_min = 0、in_max = 255、out_min = 0、out_max = 100。 マップ関数のマッピング後、(50-0)*(100-0)/(255-0)+ 0 = 19.6を戻す。つまり、0-255の50は0-100の19.6に相当する。

def setColor(color):
    R_val = (color & 0xFF0000) >> 16
    G_val = (color & 0x00FF00) >> 8
    B_val = (color & 0x0000FF) >> 0

入力されたカラー値で三つのLEDの輝度を構成し、16進数の最初の二つの値をR_valに割り当て、 中央の二つをG_valに割り当て、最後の二つの値をB_valに割り当てる。 たとえば、color = 0xFF00FF、R_val =(0xFF00FF&0xFF0000)>> 16 = 0xFF、G_val = 0x00、B_val = 0xFFの場合。

R_val = MAP(R_val, 0, 255, 0, 100)
G_val = MAP(G_val, 0, 255, 0, 100)
B_val = MAP(B_val, 0, 255, 0, 100)

マップ機能を使用して、0〜255のR、G、B値をPWMデューティサイクル範囲0〜100にマップする。

p_R.ChangeDutyCycle(R_val)
p_G.ChangeDutyCycle(G_val)
p_B.ChangeDutyCycle(B_val)

マッピングされたデューティサイクルを対応するPWMチャネルに割り当てて、輝度を変更する。

for color in COLOR:
    setColor(color)
    time.sleep(0.5)

COLORリストのすべてのアイテムをそれぞれ色に割り当て、 setColor() 関数を介してRGB LEDの色を変更する。

現象画像
_images/image62.jpeg

1.1.3 LED棒グラフ

前書き

このプロジェクトでは、LED棒グラフのライトを順番に点灯させる。

部品
_images/list_led_bar.png
原理

LED棒グラフ

LED棒グラフは、電子回路またはマイクロコントローラーとの接続に使用されるLED配列である。10個の個別のLEDを10本の出力ピンに接続するように、LED棒グラフを回路に簡単に接続できる。 通常、LED棒グラフは、バッテリーレベルインジケーター、オーディオ機器、および産業用制御パネルとして使用できる。LED棒グラフには他にも多くの用途がある。

_images/led_bar_sche.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

SDA1

Pin 3

8

2

SCL1

Pin 5

9

3

SPICE0

Pin 24

10

8

_images/schematic_led_bar.png
実験手順

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

_images/image66.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd ~/davinci-kit-for-raspberry-pi/c/1.1.3/

ステップ3: コードをコンパイルする。

gcc 1.1.3_LedBarGraph.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行後、LEDバーのLEDが定期的にオン/オフになる。

コード

#include <wiringPi.h>
#include <stdio.h>

int pins[10] = {0,1,2,3,4,5,6,8,9,10};
void oddLedBarGraph(void){
    for(int i=0;i<5;i++){
        int j=i*2;
        digitalWrite(pins[j],HIGH);
        delay(300);
        digitalWrite(pins[j],LOW);
    }
}
void evenLedBarGraph(void){
    for(int i=0;i<5;i++){
        int j=i*2+1;
        digitalWrite(pins[j],HIGH);
        delay(300);
        digitalWrite(pins[j],LOW);
    }
}
void allLedBarGraph(void){
    for(int i=0;i<10;i++){
        digitalWrite(pins[i],HIGH);
        delay(300);
        digitalWrite(pins[i],LOW);
    }
}
int main(void)
{
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    for(int i=0;i<10;i++){       //make led pins' mode is output
        pinMode(pins[i], OUTPUT);
        digitalWrite(pins[i],LOW);
    }
    while(1){
        oddLedBarGraph();
        delay(300);
        evenLedBarGraph();
        delay(300);
        allLedBarGraph();
        delay(300);
    }
    return 0;
}

コードの説明

int pins[10] = {0,1,2,3,4,5,6,8,9,10};

配列を作成し、LED棒グラフ(0、1、2、3、4、5、6、8、9、10)に対応するピン番号に割り当て、配列はLEDを制御するために使用される。

void oddLedBarGraph(void){
    for(int i=0;i<5;i++){
        int j=i*2;
        digitalWrite(pins[j],HIGH);
        delay(300);
        digitalWrite(pins[j],LOW);
    }
}

LED棒グラフの奇数桁のLEDを順番に点灯させる。

void evenLedBarGraph(void){
    for(int i=0;i<5;i++){
        int j=i*2+1;
        digitalWrite(pins[j],HIGH);
        delay(300);
        digitalWrite(pins[j],LOW);
    }
}

LED棒グラフの偶数桁のLEDを順番に点灯させる。

void allLedBarGraph(void){
    for(int i=0;i<10;i++){
        digitalWrite(pins[i],HIGH);
        delay(300);
        digitalWrite(pins[i],LOW);
    }
}

LED棒グラフのLEDを1つずつ点灯させる。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 1.1.3_LedBarGraph.py

コードの実行後、LEDバーのLEDが定期的にオン/オフになる。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

ledPins = [11, 12, 13, 15, 16, 18, 22, 3, 5, 24]

def oddLedBarGraph():
    for i in range(5):
        j = i*2
        GPIO.output(ledPins[j],GPIO.HIGH)
        time.sleep(0.3)
        GPIO.output(ledPins[j],GPIO.LOW)

def evenLedBarGraph():
    for i in range(5):
        j = i*2+1
        GPIO.output(ledPins[j],GPIO.HIGH)
        time.sleep(0.3)
        GPIO.output(ledPins[j],GPIO.LOW)

def allLedBarGraph():
    for i in ledPins:
        GPIO.output(i,GPIO.HIGH)
        time.sleep(0.3)
        GPIO.output(i,GPIO.LOW)

def setup():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)        # Numbers GPIOs by physical location
    for i in ledPins:
        GPIO.setup(i, GPIO.OUT)   # Set all ledPins' mode is output
        GPIO.output(i, GPIO.LOW) # Set all ledPins to high(+3.3V) to off led

def loop():
    while True:
        oddLedBarGraph()
        time.sleep(0.3)
        evenLedBarGraph()
        time.sleep(0.3)
        allLedBarGraph()
        time.sleep(0.3)

def destroy():
    for pin in ledPins:
        GPIO.output(pin, GPIO.LOW)    # turn off all leds
    GPIO.cleanup()                     # Release resource

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the program destroy() will be  executed.
        destroy()

コードの説明

ledPins = [11, 12, 13, 15, 16, 18, 22, 3, 5, 24] 配列を作成し、LED棒グラフ(11、12、13、15、16、18、22、3、5、24)に対応するピン番号に割り当て、配列はLEDを制御するために使用される。

def oddLedBarGraph():
    for i in range(5):
        j = i*2
        GPIO.output(ledPins[j],GPIO.HIGH)
        time.sleep(0.3)
        GPIO.output(ledPins[j],GPIO.LOW)

LED棒グラフの奇数桁のLEDを順番に点灯させる。

def evenLedBarGraph():
    for i in range(5):
        j = i*2+1
        GPIO.output(ledPins[j],GPIO.HIGH)
        time.sleep(0.3)
        GPIO.output(ledPins[j],GPIO.LOW)

LED棒グラフの偶数桁のLEDを順番に点灯させる。

def allLedBarGraph():
    for i in ledPins:
        GPIO.output(i,GPIO.HIGH)
        time.sleep(0.3)
        GPIO.output(i,GPIO.LOW)

LED棒グラフのLEDを1つずつ点灯させる。

現象画像
_images/image67.jpeg

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

前書き

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

部品
_images/list_7_segment.png
原理

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

7セグメントディスプレイは、LEDを7個パッケージした8字型の部品である。各LEDはセグメントと呼ばれる-通電されると、1つのセグメントが表示される数字の一部を形成する。

ピン接続には、カソードコモン(CC)とアノードコモン(CA)の2種類がある。名前が示すように、CAディスプレイには7セグメントのアノードがすべて接続されている場合、CCディスプレイには7つのLEDのカソードがすべて接続されている。このキットでは、前者を使用する。

_images/image70.jpeg

ディスプレイの各LEDには、長方形のプラスチックパッケージから接続ピンの1つが引き出された位置セグメントがある。 これらのLEDピンには、個々のLEDを表す「a」から「g」までのラベルが付いている。他のLEDピンは一緒に接続され、共通のピンを形成する。 そのため、LEDセグメントの適切なピンを特定の順序で順方向にバイアスすることにより、一部のセグメントが明るくなり、他のセグメントが暗くなり、ディスプレイに対応する文字が表示される。

表示コード

7セグメントディスプレイ(カソードコモン)がどのように番号を表示するかを知るために、次の表を作成した。 数字は、7セグメントディスプレイに表示される数字0〜Fである。(DP)GFEDCBAは、0または1に設定された対応するLEDを指す。 たとえば、00111111は、DPとGが0に設定され、他が1に設定されることを意味する。 したがって、7セグメントディスプレイには0が表示され、HEXコードは16進数に対応する。

_images/common_cathode.png

74HC595

74HC595は、8ビットのシフトレジスタと、3段階の並列出力を備えたストレージレジスタで構成されている。MCUのIOポートを節約できるように、シリアル入力を並列出力に変換する。

MR(ピン10)が高レベルで、OE(ピン13)が低レベルの場合、データはSHcpの立ち上がりエッジで入力され、SHcpの立ち上がりエッジを介してメモリレジスタに入力される。 2つのクロックが接続されている場合、シフトレジスタは常にメモリレジスタより1パルス早くなる。 メモリレジスタには、シリアルシフト入力ピン(Ds)、シリアル出力ピン(Q)、非同期リセットボタン(低レベル)がある。 メモリレジスタは並列8ビットで3つの状態のバスを出力します。 OEが有効(低レベル)の場合、メモリレジスタのデータがバスに出力される。

_images/74hc595_sche.png

74HC595のピンとその機能

  • Q0-Q7 : 8ビットパラレルデータ出力端子。8個のLEDまたは8個の7セグメントディスプレイを直接制御することができます。

  • Q7' : 複数の74HC595を直列に接続するために,別の74HC595のDSに接続される直列出力端子。

  • MR : リセットピン-低レベルで作動;

  • SHcp : シフトレジスタの時系列入力。 立ち上がりエッジでは、シフトレジスタのデータが1ビット連続して移動します。つまり、Q1のデータがQ2に移動します。 立ち下がりエッジにある間、シフトレジスタのデータは変更されません。

  • STcp : ストレージレジスタの時系列入力。 立ち上がりエッジで、シフトレジスタのデータがメモリレジスタに移動します。

  • CE : 出力イネーブルピン、低レベルで作動する。

  • DS : 直列データ入力ピン

  • VCC : 正の電源電圧

  • GND : 接地

回路図

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

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

_images/schematic_7_segment.png
実験手順

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

_images/image73.png
C言語ユーザー向け

ステップ2:コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.1.4/

ステップ3:コンパイルする。

gcc 1.1.4_7-Segment.c -lwiringPi

ステップ4:EXEファイルを実行する。

sudo ./a.out

コードの実行後、7セグメントディスプレイに0〜9、AFが表示される。

コード

#include <wiringPi.h>
#include <stdio.h>
#define   SDI   0   //serial data input
#define   RCLK  1   //memory clock input(STCP)
#define   SRCLK 2   //shift register clock input(SHCP)
unsigned char SegCode[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void init(void){
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);
    digitalWrite(SDI, 0);
    digitalWrite(RCLK, 0);
    digitalWrite(SRCLK, 0);
}

void hc595_shift(unsigned char dat){
    int i;
    for(i=0;i<8;i++){
        digitalWrite(SDI, 0x80 & (dat << i));
        digitalWrite(SRCLK, 1);
        delay(1);
        digitalWrite(SRCLK, 0);
    }
        digitalWrite(RCLK, 1);
        delay(1);
        digitalWrite(RCLK, 0);
}

int main(void){
    int i;
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    init();
    while(1){
        for(i=0;i<16;i++){
            printf("Print %1X on Segment\n", i); // %X means hex output
            hc595_shift(SegCode[i]);
            delay(500);
        }
    }
    return 0;
}

コードの説明

unsigned char SegCode[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; 16進数(カソードコモン)の0からFまでのセグメントコード配列。

void init(void){
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);
    digitalWrite(SDI, 0);
    digitalWrite(RCLK, 0);
    digitalWrite(SRCLK, 0);
}

Set ds , st_cp , sh_cp の3つのピンをOUTPUTに設定し、初期状態を0に設定する。 void hc595_shift(unsigned char dat){} 8ビット値を74HC595のシフトレジスタに割り当てる。

digitalWrite(SDI, 0x80 & (dat << i));

ビットごとにdatデータをSDI(DS)に割り当てる。 ここでは、dat = 0x3f(0011 1111を仮定し、i = 2の場合、0x3fは左(<<)2ビットにシフトする。 1111 1100(0x3f << 2)&1000 0000(0x80)= 1000 0000、真である。

digitalWrite(SRCLK, 1);

SRCLKの初期値は元々に0に設定されていたが、ここでは1に設定されている。 これは、立ち上がりエッジパルスを生成し、DSの日付をシフトレジスタにシフトする。

digitalWrite(RCLK, 1);

RCLKの初期値は元々に0に設定されていたが、ここでは1に設定されている。これは、立ち上がりエッジパルスを生成し、データーをシフトレジスタからストレージレジスターにシフトする。

while(1){
        for(i=0;i<16;i++){
            printf("Print %1X on Segment\n", i); // %X means hex output
            hc595_shift(SegCode[i]);
            delay(500);
        }
    }

このforループでは、iを16進数で出力するために、"%1X" を使用しています。iを適用して SegCode[] 配列の対応するセグメントコードを求め、 hc595_shift() で74HC595のシフトレジスターにSegCodeを渡します。

Python言語ユーザー向け

ステップ2:コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3:実行する。

sudo python3 1.1.4_7-Segment.py

コードの実行後、7セグメントディスプレイに0〜9、AFが表示される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

# Set up pins
SDI   = 17
RCLK  = 18
SRCLK = 27

# Define a segment code from 0 to F in Hexadecimal
# Common cathode
segCode = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71]

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(SDI, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(RCLK, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(SRCLK, GPIO.OUT, initial=GPIO.LOW)

# Shift the data to 74HC595
def hc595_shift(dat):
    for bit in range(0, 8):
        GPIO.output(SDI, 0x80 & (dat << bit))
        GPIO.output(SRCLK, GPIO.HIGH)
        time.sleep(0.001)
        GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(RCLK, GPIO.HIGH)
    time.sleep(0.001)
    GPIO.output(RCLK, GPIO.LOW)

def main():
    while True:
        # Shift the code one by one from segCode list
        for code in segCode:
            hc595_shift(code)
            print ("segCode[%s]: 0x%02X"%(segCode.index(code), code)) # %02X means double digit HEX to print
            time.sleep(0.5)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    setup()
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの説明

segCode = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71]

16進数(カソードコモン)の0からFまでのセグメントコード配列。

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(SDI, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(RCLK, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(SRCLK, GPIO.OUT, initial=GPIO.LOW)

Set ds, st_cp , sh_cp の3つのピンを出力に設定し、初期状態を低レベルとして設定する。

GPIO.output(SDI, 0x80 & (dat << bit))

ビットごとにdatデータをSDI(DS)に割り当てる。ここでは、dat = 0x3f(0011 1111、bit = 2を仮定し、0x3fは右(<<)2ビットに切り替える。1111 1100(0x3f << 2)&1000 0000(0x80)=1000 0000、は真である。

GPIO.output(SRCLK, GPIO.HIGH)

SRCLKの初期値は元々LOWに設定されていたが、ここでは立ち上がりエッジを生成し、DSデータをシフトレジスタに切り替えるためにHIGHに設定されている。

GPIO.output(RCLK, GPIO.HIGH)

SRCLKの初期値は元々LOWに設定されていたが、ここでは立ち上がりエッジを生成し、DSデータをシフトレジスタに切り替えるためにHIGHに設定されている。

注釈

番号0〜15の16進形式は:(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F)。

現象画像
_images/image74.jpeg

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

前書き

次に、4桁7セグメントディスプレイを制御してみてください。

部品
_images/list_4_digit.png
原理

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

4桁の7セグメントディスプレイは、連携して動作する4つの7セグメントディスプレイで構成されている。

_images/4-digit-sche.png

4デジタル7セグメントディスプレイは独立して動作する。人間の視覚的持続性の原理を使用して、ループ内の各7セグメントの文字をすばやく表示し、連続した文字列を形成する。

つまり、ディスプレイに「1234」が表示されている場合、最初の7セグメントに「1」が表示され、「234」は表示されないということである。しばらくすると、2番目の7セグメントに「2」が表示され、7セグメントの1番目、3番目、4番目に表示されなくなり、4つのデジタルディスプレイショーが順番に表示される。このプロセスは非常に短く(通常5ms)、光学的残光効果と視覚的残留の原理により、同時に4つの文字を見ることができる。

_images/image78.png

表示コード

7セグメントディスプレイ(アノードコモン)がどのように番号を表示するかを知るために、次の表をご参照ください。数字は7セグメントディスプレイに表示される0〜Fの数字である。(DP)GFEDCBAは、0または1に設定された対応のLEDを指す。たとえば、11000000はDPおよびGが1に設定され、他のLEDが0に設定されることを意味する。 したがって、7セグメントディスプレイには0が表示され、HEXコードは16進数に対応する。

_images/common_anode.png
回路図

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/schmatic_4_digit.png
実験手順

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

_images/image80.png
C言語ユーザー向け

ステップ2:コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.1.5/

ステップ3:コードをコンパイルする。

gcc 1.1.5_4-Digit.c -lwiringPi

ステップ4:EXEファイルを実行する。

sudo ./a.out

コードの実行後、プログラムは1秒間に1つずつ増やすカウントを行い、4桁の7セグメントディスプレイにそのカウントが表示される。

コード

#include <wiringPi.h>
#include <stdio.h>
#include <wiringShift.h>
#include <signal.h>
#include <unistd.h>

#define SDI 5
#define RCLK 4
#define SRCLK 1

const int placePin[] = {12, 3, 2, 0};
unsigned char number[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

int counter = 0;

void pickDigit(int digit)
{
    for (int i = 0; i < 4; i++)
    {
        digitalWrite(placePin[i], 0);
    }
    digitalWrite(placePin[digit], 1);
}

void hc595_shift(int8_t data)
{
    int i;
    for (i = 0; i < 8; i++)
    {
        digitalWrite(SDI, 0x80 & (data << i));
        digitalWrite(SRCLK, 1);
        delayMicroseconds(1);
        digitalWrite(SRCLK, 0);
    }
    digitalWrite(RCLK, 1);
    delayMicroseconds(1);
    digitalWrite(RCLK, 0);
}

void clearDisplay()
{
    int i;
    for (i = 0; i < 8; i++)
    {
        digitalWrite(SDI, 1);
        digitalWrite(SRCLK, 1);
        delayMicroseconds(1);
        digitalWrite(SRCLK, 0);
    }
    digitalWrite(RCLK, 1);
    delayMicroseconds(1);
    digitalWrite(RCLK, 0);
}

void loop()
{
    while(1){
    clearDisplay();
    pickDigit(0);
    hc595_shift(number[counter % 10]);

    clearDisplay();
    pickDigit(1);
    hc595_shift(number[counter % 100 / 10]);

    clearDisplay();
    pickDigit(2);
    hc595_shift(number[counter % 1000 / 100]);

    clearDisplay();
    pickDigit(3);
    hc595_shift(number[counter % 10000 / 1000]);
    }
}

void timer(int timer1)
{
    if (timer1 == SIGALRM)
    {
        counter++;
        alarm(1);
        printf("%d\n", counter);
    }
}

void main(void)
{
    if (wiringPiSetup() == -1)
    {
        printf("setup wiringPi failed !");
        return;
    }
    pinMode(SDI, OUTPUT);
    pinMode(RCLK, OUTPUT);
    pinMode(SRCLK, OUTPUT);

    for (int i = 0; i < 4; i++)
    {
        pinMode(placePin[i], OUTPUT);
        digitalWrite(placePin[i], HIGH);
    }
    signal(SIGALRM, timer);
    alarm(1);
    loop();
}

コードの説明

const int placePin[] = {12, 3, 2, 0};

これらの4つのピンは、4桁の7セグメントディスプレイのアノードコモンピンを制御する。

unsigned char number[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

16進数(アノードコモン)の0〜9のセグメントコード配列。

void pickDigit(int digit)
{
    for (int i = 0; i < 4; i++)
    {
        digitalWrite(placePin[i], 0);
    }
    digitalWrite(placePin[digit], 1);
}

値の場所を選択する。毎回有効な場所は1つだけである。有効な場所はhighに書き込まれる。

void loop()
{
    while(1){
    clearDisplay();
    pickDigit(0);
    hc595_shift(number[counter % 10]);

    clearDisplay();
    pickDigit(1);
    hc595_shift(number[counter % 100 / 10]);

    clearDisplay();
    pickDigit(2);
    hc595_shift(number[counter % 1000 / 100]);

    clearDisplay();
    pickDigit(3);
    hc595_shift(number[counter % 10000 / 1000]);
    }
}

この機能を使用して、4桁の7セグメントディスプレイに表示される番号を設定する。

  • clearDisplay():11111111に書き込み、7セグメントディスプレイ上のこれら8つのLEDをオフにして、表示されたコンテンツを消去する。

  • pickDigit(0):4番目の7セグメントディスプレイを選択する。

  • hc595_shift(number[counter%10]):カウンターの1桁の数字が4番目のセグメントに表示される。

signal(SIGALRM, timer);

これはシステム組み込みの関数であり、コードのプロトタイプは次のとおりである:

sig_t signal(int signum,sig_t handler);

signal() を実行した後、プロセスは対応する signum(ここでSIGALRM)を受信すると、すぐに既存のタスクを一時停止し、設定関数(ここでtimer(sig))を処理する。

alarm(1);

これもシステム組み込み関数である。コードのプロトタイプは:

unsigned int alarm (unsigned int seconds);

指定した秒数後にSIGALRMシグナルを生成する。

void timer(int timer1)
{
    if (timer1 == SIGALRM)
    {
        counter++;
        alarm(1);
        printf("%d\n", counter);
    }
}

上記の関数を使用して、タイマー関数を実装する。 alarm() がSIGALRMシグナルを生成した後、タイマー関数が呼び出される。カウンターに1を追加すると、1秒後に関数 alarm(1) が繰り返し呼び出される。

Python言語ユーザー向け

ステップ2:コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3:EXEファイルを実行する。

sudo python3 1.1.5_4-Digit.py

コードの実行後、プログラムは1秒ずつ増加するカウントをして、4桁のディスプレイにカウントが表示される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import threading

SDI = 24
RCLK = 23
SRCLK = 18

placePin = (10, 22, 27, 17)
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

counter = 0
timer1 = 0

def clearDisplay():
    for i 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):
    for i in placePin:
        GPIO.output(i,GPIO.LOW)
    GPIO.output(placePin[digit], GPIO.HIGH)


def timer():
    global counter
    global timer1
    timer1 = threading.Timer(1.0, timer)
    timer1.start()
    counter += 1
    print("%d" % counter)


def loop():
    global counter
    while True:
        clearDisplay()
        pickDigit(0)
        hc595_shift(number[counter % 10])

        clearDisplay()
        pickDigit(1)
        hc595_shift(number[counter % 100//10])

        clearDisplay()
        pickDigit(2)
        hc595_shift(number[counter % 1000//100])

        clearDisplay()
        pickDigit(3)
        hc595_shift(number[counter % 10000//1000])


def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(SDI, GPIO.OUT)
    GPIO.setup(RCLK, GPIO.OUT)
    GPIO.setup(SRCLK, GPIO.OUT)
    for i in placePin:
        GPIO.setup(i, GPIO.OUT)
    global timer1
    timer1 = threading.Timer(1.0, timer)
    timer1.start()

def destroy():   # When "Ctrl+C" is pressed, the function is executed.
    global timer1
    GPIO.cleanup()
    timer1.cancel()  # cancel the timer

if __name__ == '__main__':  # Program starting from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コードの説明

placePin = (10, 22, 27, 17)

これらの4つのピンは、4桁の7セグメントディスプレイのアノードコモンピンを制御する。

number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

16進数の0〜9のセグメントコード配列(アノードコモン)。

def clearDisplay():
    for i 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)

SDIに「1」を8回書き込むと、7セグメントディスプレイの8つのLEDが消灯し、表示されたコンテンツが消去される。

def pickDigit(digit):
    for i in placePin:
        GPIO.output(i,GPIO.LOW)
    GPIO.output(placePin[digit], GPIO.HIGH)

値の場所を選択する。毎回有効な場所は1つだけである。有効な場所はhighに書き込まれる。

def loop():
    global counter
    while True:
        clearDisplay()
        pickDigit(0)
        hc595_shift(number[counter % 10])

        clearDisplay()
        pickDigit(1)
        hc595_shift(number[counter % 100//10])

        clearDisplay()
        pickDigit(2)
        hc595_shift(number[counter % 1000//100])

        clearDisplay()
        pickDigit(3)
        hc595_shift(number[counter % 10000//1000])

この機能は、4桁の7セグメントディスプレイに表示される番号を設定するために使用される。

まず、4番目のセグメントディスプレイを開始し、1桁の数字を書き込む。次に、3番目のセグメントディスプレイを開始し、10桁の数字を入力する。その後、2番目と1番目のセグメントディスプレイをそれぞれ開始し、それぞれ数百桁と数千桁を書き込む。リフレッシュ速度が非常に速いため、完全な4桁のディスプレイが表示される。

timer1 = threading.Timer(1.0, timer)
timer1.start()

モジュール、スレッドはPythonの一般的なスレッドモジュールであり、タイマーはそのサブクラスである。コードのプロトタイプは次のとおりです:

class threading.Timer(interval, function, args=[], kwargs={})

間隔の後、関数が実行される。ここでは、間隔は1.0、関数は timer() である。 start() は、タイマーがこの時点で開始することを意味する。

def timer():
    global counter
    global timer1
    timer1 = threading.Timer(1.0, timer)
    timer1.start()
    counter += 1
    print("%d" % counter)

Timerが1.0秒に達すると、Timer関数が呼び出される。カウンターに1を追加すると、タイマーが再び使用されて、1秒ごとに繰り返し実行される。

現象画像
_images/image81.jpeg

1.1.6 LEDドットマトリックス

前書き

名前が示すように、LEDドットマトリックスはLEDで構成されるマトリックスである。LEDの点灯と調光は、さまざまな文字とパターンを形成する。

部品
_images/list_dot.png
原理

LEDドットマトリックス

一般に、LEDドットマトリックスは、cathode (CC)とcommon anode (CA)の2つのタイプに分類できる。見た目は似ているが、内部的には違いがある。テストを行うとすぐに分かる。このキットではCAが使用される。側面に788BSというラベルが付いている。

下の図を参照してください。ピンは背面の両端に配置されている。ラベル側を参考にしてください。この端のピンはピン1〜8で、もう一方のピンはピン9〜16である。

外部ビュー:

_images/image84.png

図の下に内部構造を示している。CA LEDドットマトリックスが見える。ROWはLEDのアノードを表し、COLはカソードを表す。CCの場合は逆である。共通点が1つある:両方のタイプで、ピン13、3、4、10、6、11、15、および16はすべてCOLである。ピン9、14、8、12、1、7、2、および5がすべてROWである。左上隅の最初のLEDをオンにする場合、CA LEDドットマトリックスに対して、ピン9をHigh、ピン13をLowに設定し、CC 1に対して、ピン13をHighに、ピン9をLowに設定する。CAの最初の列全体を点灯させる場合は、ピン13をLowに、行9、14、8、12、1、7、2、および5をHighに設定するCCの場合、ピン13をHighに、行9、14、8、12、1、7、2、および5をLowに設定する。理解を深めるために、次の図を検討してください。

内部ビュー:

_images/image85.png

上記の行と列に対応するピン番号:

COL

1

2

3

4

5

6

7

8

Pin No.

13

3

4

10

6

11

15

16

ROW

1

2

3

4

5

6

7

8

Pin No.

9

14

8

12

1

7

2

5

さらに、2つの74HC595チップがここで使用されている。1つはLEDドットマトリックスの行を制御し、もう1つは列を制御する。

回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

_images/schematic_dot.png
実験手順

ステップ1: 回路を作る。配線が複雑なので、段階的に作りましょう。まず、T-Cobbler、LEDドットマトリックス、および2つの74HC595チップをブレッドボードに挿入する。 T-Cobblerの3.3Vと接地をボードの両側の穴に接続し、2つの74HC595チップのピン16と10をVCCに、ピン13とピン8を接地に接続する。

注釈

上のFritzing画像では、ラベルのある側が下にある。

_images/image87.png

ステップ2: 2つの74HC595のピン11を一緒に接続し、GPIO27に接続する。 次に、2つのチップのピン12を一緒に接続し、GPIO18に接続する。 それから左側の74HC595のピン14をGPIO17に、ピン9を2番目の74HC595のピン14に接続する。

_images/image88.png

ステップ3: 右側の74HC595は、LEDドットマトリックスの列を制御する。 マッピングについては、以下の表を参照してください。 したがって、74HC595のQ0〜Q7ピンは、それぞれピン13、3、4、10、6、11、15、および16にマップされる。

74HC595

Q0

Q1

Q2

Q3

Q4

Q5

Q6

Q7

LED Dot Matrix

13

3

4

10

6

11

15

16

_images/image89.png

ステップ4: 次に、LEDドットマトリックスの行を接続する。左側の74HC595はLEDドットマトリックスの行を制御する。 マッピングについては、以下の表を参照してください。左側の74HC595のQ0〜Q7は、それぞれピン9、14、8、12、1、7、2、および5にマッピングされていることは分かった。

74HC595

Q0

Q1

Q2

Q3

Q4

Q5

Q6

Q7

LED Dot Matrix

9

14

8

12

1

7

2

5

_images/image90.png
C言語ユーザー向け

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

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.1.6/

ステップ6: コンパイルする。

gcc 1.1.6_LedMatrix.c -lwiringPi

ステップ7: 実行する。

sudo ./a.out

コードの実行後、LEDドットマトリックスが行ごとに、列ごとに点灯したり消灯したりする。

コード

#include <wiringPi.h>
#include <stdio.h>

#define   SDI   0   //serial data input
#define   RCLK  1   //memory clock input(STCP)
#define   SRCLK 2   //shift register clock input(SHCP)

unsigned char code_H[20] = {0x01,0xff,0x80,0xff,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned char code_L[20] = {0x00,0x7f,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

void init(void){
   pinMode(SDI, OUTPUT);
   pinMode(RCLK, OUTPUT);
   pinMode(SRCLK, OUTPUT);

   digitalWrite(SDI, 0);
   digitalWrite(RCLK, 0);
   digitalWrite(SRCLK, 0);
}

void hc595_in(unsigned char dat){
   int i;
   for(i=0;i<8;i++){
      digitalWrite(SDI, 0x80 & (dat << i));
      digitalWrite(SRCLK, 1);
      delay(1);
      digitalWrite(SRCLK, 0);
   }
}

void hc595_out(){
   digitalWrite(RCLK, 1);
   delay(1);
   digitalWrite(RCLK, 0);
}

int main(void){
   int i;
   if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
      printf("setup wiringPi failed !");
      return 1;
   }
   init();
   while(1){
      for(i=0;i<sizeof(code_H);i++){
            hc595_in(code_L[i]);
            hc595_in(code_H[i]);
            hc595_out();
            delay(100);
      }

      for(i=sizeof(code_H);i>=0;i--){
            hc595_in(code_L[i]);
            hc595_in(code_H[i]);
            hc595_out();
            delay(100);
      }
   }

   return 0;
}

Code Explanation

unsigned char code_H[20] = {0x01,0xff,0x80,0xff,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned char code_L[20] = {0x00,0x7f,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

配列code_HはLEDドットマトリックス行の要素を表し、配列code_Lは列の要素を表す。 文字が表示されると、行の要素と列の要素が取得され、それぞれ2つのHC595チップに割り当てられる。 したがって、パターンはLEDドットマトリックスに表示される。例として、code_Hの最初の数字0x01とcode_Lの最初の数字0x00を取り上げる。

二進法に変換された0x01は00000001になり、二進法に変換された0x00は0000 0000になる。

このキットでは、アノードコモンLEDドットマトリックスディスプレイが適用されるため、 8列目の8つのLEDのみが点灯する。コードHが0xffで、code_Lが0x7fであるという条件が同時に満たされると、最初の列のこれら8つのLEDが点灯する。

_images/anode_table.png
void hc595_in(unsigned char dat){
   int i;
   for(i=0;i<8;i++){
      digitalWrite(SDI, 0x80 & (dat << i));
      digitalWrite(SRCLK, 1);
      delay(1);
      digitalWrite(SRCLK, 0);

HC 595ビットのピンSDIにビット単位でDATの値を書き込みます。SRCLKの初期値は0に設定され、ここで1がセットされ、立ち上がりエッジパルスを生成し、次にPHSDI(DS)の日付をシフトレジスタにシフトさせる。

void hc595_out(){
   digitalWrite(RCLK, 1);
   delay(1);
   digitalWrite(RCLK, 0);

RCLKの初期値は元々に0に設定されていたが、ここでは1に設定されている。これは、立ち上がりエッジパルスを生成し、データーをシフトレジスタからストレージレジスターにシフトする。

while(1){
   for(i=0;i<sizeof(code_H);i++){
      hc595_in(code_L[i]);
      hc595_in(code_H[i]);
      hc595_out();
      delay(100);
   }
}

このループでは、2つの配列code_Lおよびcode_Hのこれらの20個の要素が2つの74HC595チップに1つずつアップロードされる。次に、関数hc595_out()を呼び出して、データをシフトレジスタからストレージレジスタにシフトする。

Python言語ユーザー向け

ステップ5: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ6: 実行する。

sudo python3 1.1.6_LedMatrix.py

コードの実行後、LEDドットマトリックスが行ごとに、列ごとに点灯したり消灯したりする。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

SDI   = 17
RCLK  = 18
SRCLK = 27

# we use BX matrix, ROW for anode, and COL for cathode
# ROW  ++++
code_H = [0x01,0xff,0x80,0xff,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff]
# COL  ----
code_L = [0x00,0x7f,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f]

def setup():
   GPIO.setmode(GPIO.BCM)    # Number GPIOs by its BCM location
   GPIO.setup(SDI, GPIO.OUT)
   GPIO.setup(RCLK, GPIO.OUT)
   GPIO.setup(SRCLK, GPIO.OUT)
   GPIO.output(SDI, GPIO.LOW)
   GPIO.output(RCLK, GPIO.LOW)
   GPIO.output(SRCLK, GPIO.LOW)

# Shift the data to 74HC595
def hc595_shift(dat):
   for bit in range(0, 8):
      GPIO.output(SDI, 0x80 & (dat << bit))
      GPIO.output(SRCLK, GPIO.HIGH)
      time.sleep(0.001)
      GPIO.output(SRCLK, GPIO.LOW)
   GPIO.output(RCLK, GPIO.HIGH)
   time.sleep(0.001)
   GPIO.output(RCLK, GPIO.LOW)

def main():
   while True:
      for i in range(0, len(code_H)):
            hc595_shift(code_L[i])
            hc595_shift(code_H[i])
            time.sleep(0.1)

      for i in range(len(code_H)-1, -1, -1):
            hc595_shift(code_L[i])
            hc595_shift(code_H[i])
            time.sleep(0.1)

def destroy():
   GPIO.cleanup()

if __name__ == '__main__':
   setup()
   try:
      main()
   except KeyboardInterrupt:
      destroy()

コードの説明

code_H = [0x01,0xff,0x80,0xff,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff]
code_L = [0x00,0x7f,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f]

配列code_Hはmatix行の要素を表し、配列code_Lは列の要素を表す。文字が表示されると、行の要素と列の要素が取得され、それぞれ2つのHC595チップに割り当てられる。したがって、パターンはLEDドットマトリックスに表示される。例として、code_Hの最初の数字0x01とcode_Lの最初の数字0x00を取り上げる。

二進法に変換された0x01は00000001になり、二進法に変換された0x00は0000 0000になる。

このキットでは、アノードコモンLEDドットマトリックスが適用されるため、8行目の8つのLEDのみが点灯する。コードHが0xffで、code_Lが0x7fであるという条件が同時に満たされると、最初の列のこれら8つのLEDが点灯する。

_images/anode_table.png
for i in range(0, len(code_H)):
   hc595_shift(code_L[i])
   hc595_shift(code_H[i])

このループでは、2つの配列code_Lおよびcode_Hのこれらの20個の要素が2つのHC595チップに1つずつアップロードされる。

注釈

LEDドットマトリックスに文字を表示する場合は、Pythonコードを参照してください: https://github.com/sunfounder/SunFounder_Dot_Matrix.

現象画像
_images/image91.jpeg

1.1.7 I2C LCD1602

前書き

LCD1602は文字型液晶ディスプレイで、32(16 * 2)文字を同時に表示できる。

部品
_images/list_i2c_lcd.png
原理

I2C LCD1602

ご存知のように、LCDやその他のディスプレイはマンマシンの相互作用を大幅に強化するが、共通の弱点を共有している。 それらがコントローラーに接続されると、外部ポートがあまりないコントローラーの複数のIOが占用される。 また、コントローラーの他の機能も制限される。したがって、この問題を解決するために、I2Cバスを備えたLCD1602が開発された。

_images/i2c_lcd.png

I2C通信

I2C(アイ・スクエアド・シー)バスは、一つマスターデバイス(または複数のマスターデバイス)と単一または複数のスレーブデバイス間の通信用の非常に強力なバスである。

I2Cメインコントローラーを使用して、IOエクスパンダー、各種センサー、EEPROM、ADC/DACなどを制御できる。 これらはすべて、ホストの2つのピン、シリアルデータ(SDA1)ラインとシリアルクロックライン(SCL1)によってのみ制御される。

回路図

T-Board Name

physical

SDA1

Pin 3

SCL1

Pin 5

_images/schematic_i2c_lcd.png
実験手順

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

_images/image96.png

ステップ2: I2Cをセットアップします( I2C構成 。I2Cを設定している場合は、このステップをスキップしてください。)

C言語ユーザー向け

ステップ3: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.1.7/

ステップ4: コンパイルする。

gcc 1.1.7_Lcd1602.c -lwiringPi

ステップ5: 実行する。

sudo ./a.out

コードの実行後、LCDに「Greetings」、「SunFounderから」が表示される。

注釈

コードと配線に問題がないのに LCD に内容が表示されない場合は、背面のポテンショメータをひねってみてください。

コード

#include <stdio.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <string.h>

int LCDAddr = 0x27;
int BLEN = 1;
int fd;

void write_word(int data){
    int temp = data;
    if ( BLEN == 1 )
        temp |= 0x08;
    else
        temp &= 0xF7;
    wiringPiI2CWrite(fd, temp);
}

void send_command(int comm){
    int buf;
    // Send bit7-4 firstly
    buf = comm & 0xF0;
    buf |= 0x04;                    // RS = 0, RW = 0, EN = 1
    write_word(buf);
    delay(2);
    buf &= 0xFB;                    // Make EN = 0
    write_word(buf);

    // Send bit3-0 secondly
    buf = (comm & 0x0F) << 4;
    buf |= 0x04;                    // RS = 0, RW = 0, EN = 1
    write_word(buf);
    delay(2);
    buf &= 0xFB;                    // Make EN = 0
    write_word(buf);
}

void send_data(int data){
    int buf;
    // Send bit7-4 firstly
    buf = data & 0xF0;
    buf |= 0x05;                    // RS = 1, RW = 0, EN = 1
    write_word(buf);
    delay(2);
    buf &= 0xFB;                    // Make EN = 0
    write_word(buf);

    // Send bit3-0 secondly
    buf = (data & 0x0F) << 4;
    buf |= 0x05;                    // RS = 1, RW = 0, EN = 1
    write_word(buf);
    delay(2);
    buf &= 0xFB;                    // Make EN = 0
    write_word(buf);
}

void init(){
    send_command(0x33);     // Must initialize to 8-line mode at first
    delay(5);
    send_command(0x32);     // Then initialize to 4-line mode
    delay(5);
    send_command(0x28);     // 2 Lines & 5*7 dots
    delay(5);
    send_command(0x0C);     // Enable display without cursor
    delay(5);
    send_command(0x01);     // Clear Screen
    wiringPiI2CWrite(fd, 0x08);
}

void clear(){
    send_command(0x01);     //clear Screen
}

void write(int x, int y, char data[]){
    int addr, i;
    int tmp;
    if (x < 0)  x = 0;
    if (x > 15) x = 15;
    if (y < 0)  y = 0;
    if (y > 1)  y = 1;

    // Move cursor
    addr = 0x80 + 0x40 * y + x;
    send_command(addr);

    tmp = strlen(data);
    for (i = 0; i < tmp; i++){
        send_data(data[i]);
    }
}


void main(){
    fd = wiringPiI2CSetup(LCDAddr);
    init();
    write(0, 0, "Greetings!");
    write(1, 1, "From SunFounder");
}

コードの説明

void write_word(int data){……}
void send_command(int comm){……}
void send_data(int data){……}
void init(){……}
void clear(){……}
void write(int x, int y, char data[]){……}

これらの関数は、I2C LCD1602オープンソースコードを制御するために使用される。 これにより、I2C LCD1602を簡単に使用できる。 これらの関数の中で、 init() は初期化に使用され、 clear() は画面の消去に使用され、 write() は表示内容の書き込みに使用され、 他の関数は上記の関数をサポートする。

fd = wiringPiI2CSetup(LCDAddr);

この関数は指定されたデバイスシンボルでI2Cシステムを初期化する。関数のプロトタイプ:

int wiringPiI2CSetup(int devId);

パラメーターdevIdはI2Cデバイスのアドレスであり、i2cdetectコマンド(付録を参照)で見つけることができ、I2C LCD1602のdevIdは通常0x27である。

void write(int x, int y, char data[]){}

この関数では、 data[] はLCDにプリントされる文字であり、パラメーターxとyはプリントの位置を決定する(行y + 1、列x + 1はプリントされる文字の開始位置である)。

Python言語ユーザー向け

ステップ3: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ4: 実行。

sudo python3 1.1.7_Lcd1602.py

コードの実行後、LCDに「Greetings」、「SunFounderから」が表示される。

注釈

  • FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1' というエラーが発生した場合は、 I2C構成 を参照して I2C を有効にする必要があります。

  • ModuleNotFoundError: No module named 'smbus2' エラーが発生した場合は、 sudo pip3 install smbus2 を実行してください。

  • OSError: [Errno 121] Remote I/O というエラーが発生した場合は、モジュールの配線が間違っているか、モジュールが破損しています。

  • コードと配線に問題がないのに LCD に内容が表示されない場合は、背面のポテンショメータをひねってみてください。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import LCD1602
import time

def setup():
    LCD1602.init(0x27, 1)   # init(slave address, background light)
    LCD1602.write(0, 0, 'Greetings!!')
    LCD1602.write(1, 1, 'from SunFounder')
    time.sleep(2)

def destroy():
    LCD1602.clear()

if __name__ == "__main__":
    try:
        setup()
    except KeyboardInterrupt:
        destroy()

コードの説明

import LCD1602

このファイルはI2C LCD1602を制御するためのオープンソースファイルである。I2C LCD1602を簡単に使用できる。

LCD1602.init(0x27, 1)

この関数は指定されたデバイスシンボルでI2Cシステムを初期化する。最初のパラメーターはI2Cデバイスのアドレスで、i2cdetectコマンドで検出できる(詳細については付録を参照してください)。I2C LCD1602のアドレスは通常0x27である。

LCD1602.write(0, 0, 'Greetings!!')

コードの実行後、LCDに「Greetings」、「SunFounderから」が表示される。

現象画像
_images/image97.jpeg

1.2 音声

1.2.1 アクティブブザー

前書き

このレッスンでは、PNPトランジスタでアクティブブザーを鳴らす方法を学習する。

部品
_images/list_1.2.1.png
原理

ブザー

統合された構造を持つ電子ブザーの一種として、DC電源によって電圧供給されるブザーは、コンピューター、プリンター、コピー機、警報器、電子玩具、自動車用電子装置、電話、タイマー、その他の電子製品または音声装置で広く使用されている。ブザーは、アクティブとパッシブに分類できる(次の図を参照)。ピンが上を向くようにブザーを回し、緑色の回路基板を備えたブザーはパッシブブザーで、黒いテープで囲まれたブザーはアクティブである。

アクティブブザーとパッシブブザーの違い:

_images/image101.png

アクティブブザーとパッシブブザーの違いは次の通りである:アクティブブザーには振動源が内蔵されているため、通電すると音が鳴る。ただし、パッシブブザーにはそのような振動源がないため、DC信号が使用されてもビープ音は鳴らない。代わりに、周波数が2K〜5Kの方形波を使用して駆動する必要がある。アクティブブザーは、多くの場合、複数の発振回路が内蔵されているため、パッシブブザーよりも高価である。

以下はブザーの電気記号である。両極の2つのピンが搭載されている。表面の+は陽極を表し、もう1つは陰極を表す。

_images/image102.png

ブザーのピンをチェックすることができ、長い方が陽極で、短い方が陰極である。接続時にそれらを混同しないでください。混同すると、ブザーが鳴らない。

回路図

この実験では、アクティブブザー、PNPトランジスタ、および1k抵抗器をトランジスタのベースとGPIOの間に使用して、トランジスタを保護する。Raspberry Pi出力のGPIO17にプログラミングによって低レベル(0V)が供給されると、電流飽和のためトランジスタが導通し、ブザーが音を出す。しかし、Raspberry PiのIOに高レベルが供給されると、トランジスターが切断され、ブザーは音を出さない。

_images/image332.png
実験手順

ステップ1: 回路を作る。(ブザーの両極に注意してください:+ラベルが付いている方が正極で、もう一方が負極である。)

_images/image104.png
C言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.2.1/

ステップ3: コードをコンパイルする。

gcc 1.2.1_ActiveBuzzer.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードが実行されると、ブザーが鳴く。

コード

#include <wiringPi.h>
#include <stdio.h>

#define BeepPin 0
int main(void){
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(BeepPin, OUTPUT);   //set GPIO0 output
    while(1){
        //beep on
        printf("Buzzer on\n");
        digitalWrite(BeepPin, LOW);
        delay(100);
        printf("Buzzer off\n");
        //beep off
        digitalWrite(BeepPin, HIGH);
        delay(100);
    }
    return 0;
}

コードの説明

digitalWrite(BeepPin, LOW);

この実験ではアクティブブザーを使用しているため、直流に接続すると自動的に音が鳴く。このスケッチは、I/Oポートを低レベル(0V)に設定して、トランジスタを管理し、ブザーを鳴らすためのものである。

digitalWrite(BeepPin, HIGH);

I/Oポートを高レベル(3.3V)に設定するため、トランジスターは通電されず、ブザーは鳴らない。

Python言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: 実行する。

sudo python3 1.2.1_ActiveBuzzer.py

コードが実行されると、ブザーが鳴く。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

# Set #17 as buzzer pin
BeepPin = 17

def setup():
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    # Set LedPin's mode to output,
    # and initial level to High(3.3v)
    GPIO.setup(BeepPin, GPIO.OUT, initial=GPIO.HIGH)

def main():
    while True:
        # Buzzer on (Beep)
        print ('Buzzer On')
        GPIO.output(BeepPin, GPIO.LOW)
        time.sleep(0.1)
        # Buzzer off
        print ('Buzzer Off')
        GPIO.output(BeepPin, GPIO.HIGH)
        time.sleep(0.1)

def destroy():
    # Turn off buzzer
    GPIO.output(BeepPin, GPIO.HIGH)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()

コードの説明

GPIO.output(BeepPin, GPIO.LOW)

ビープ音を鳴らすには、ブザーピンを低レベルに設定してください。

time.sleep(0.1)

0.1秒待つ。このパラメーターを変更して、スイッチング周波数を変更する。

注釈

これは音の周波数ではない。アクティブブザーは音の周波数を変更できない。

GPIO.output(BeepPin, GPIO.HIGH)

ブザーを閉じる。

現象画像
_images/image105.jpeg

1.2.2 パッシブブザー

前書き

このレッスンでは、パッシブブザーで音楽を再生する方法を学習する。

部品
_images/list_1.2.2.png
回路図

この実験では、トランジスタを保護するために、トランジスタのベースとGPIOの間にパッシブブザー、PNPトランジスタ、および1k抵抗器を使用する。

GPIO17に異なる周波数が与えられると、パッシブブザーは異なる音を出す。このようにして、ブザーは音楽を再生する。

_images/image333.png
実験手順

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

_images/image106.png
C言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.2.2/

ステップ3: コードをコンパイルする。

gcc 1.2.2_PassiveBuzzer.c -lwiringPi

ステップ4: 実行。

sudo ./a.out

コードが実行されると、ブザーが音楽を再生する。

コード

#include <wiringPi.h>
#include <softTone.h>
#include <stdio.h>

#define BuzPin    0

#define  CL1  131
#define  CL2  147
#define  CL3  165
#define  CL4  175
#define  CL5  196
#define  CL6  221
#define  CL7  248

#define  CM1  262
#define  CM2  294
#define  CM3  330
#define  CM4  350
#define  CM5  393
#define  CM6  441
#define  CM7  495

#define  CH1  525
#define  CH2  589
#define  CH3  661
#define  CH4  700
#define  CH5  786
#define  CH6  882
#define  CH7  990

int song_1[] = {CM3,CM5,CM6,CM3,CM2,CM3,CM5,CM6,CH1,CM6,CM5,CM1,CM3,CM2,
                CM2,CM3,CM5,CM2,CM3,CM3,CL6,CL6,CL6,CM1,CM2,CM3,CM2,CL7,
                CL6,CM1,CL5};

int beat_1[] = {1,1,3,1,1,3,1,1,1,1,1,1,1,1,3,1,1,3,1,1,1,1,1,1,1,2,1,1,
                1,1,1,1,1,1,3};


int song_2[] = {CM1,CM1,CM1,CL5,CM3,CM3,CM3,CM1,CM1,CM3,CM5,CM5,CM4,CM3,CM2,
                CM2,CM3,CM4,CM4,CM3,CM2,CM3,CM1,CM1,CM3,CM2,CL5,CL7,CM2,CM1
                };

int beat_2[] = {1,1,1,3,1,1,1,3,1,1,1,1,1,1,3,1,1,1,2,1,1,1,3,1,1,1,3,3,2,3};

int main(void)
{
    int i, j;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    if(softToneCreate(BuzPin) == -1){
        printf("setup softTone failed !");
        return 1;
    }

    while(1){
        printf("music is being played...\n");
        delay(100);
        for(i=0;i<sizeof(song_1)/4;i++){
            softToneWrite(BuzPin, song_1[i]);
            delay(beat_1[i] * 500);
        }

        for(i=0;i<sizeof(song_2)/4;i++){
            softToneWrite(BuzPin, song_2[i]);
            delay(beat_2[i] * 500);
        }
    }

    return 0;
}

コードの説明

#define  CL1  131
#define  CL2  147
#define  CL3  165
#define  CL4  175
#define  CL5  196
#define  CL6  221
#define  CL7  248

#define  CM1  262
#define  CM2  294

各音の周波数は以下のように示している。CL-低音、CM-中音、CH-高音、1~7は音C、D、E、F、G、A、Bに対応する。

int song_1[] = {CM3,CM5,CM6,CM3,CM2,CM3,CM5,CM6,CH1,CM6,CM5,CM1,CM3,CM2,
                CM2,CM3,CM5,CM2,CM3,CM3,CL6,CL6,CL6,CM1,CM2,CM3,CM2,CL7,
                CL6,CM1,CL5};
int beat_1[] = {1,1,3,1,1,3,1,1,1,1,1,1,1,1,3,1,1,3,1,1,1,1,1,1,1,2,1,1,
                1,1,1,1,1,1,3};

配列 song_1[] は曲の楽譜を保存する。 beat_1[] は曲の各音符の拍を表す(1拍ごとに0.5秒)。

if(softToneCreate(BuzPin) == -1){
        printf("setup softTone failed !");
        return 1;

これにより、ソフトウェア制御のトーンピンが作成される。 任意のGPIOピンを使用でき、ピンの番号は使用した wiringPiSetup() 関数の番号になる。成功した場合の戻り値は0である。 それ以外の場合は、グローバル変数errnoをチェックして、何が問題なのかを確認する必要がある。

for(i=0;i<sizeof(song_1)/4;i++){
    softToneWrite(BuzPin, song_1[i]);
    delay(beat_1[i] * 500);
}

song_1 を再生するために for statement を使用する。

判断条件 i<sizeof(song_1)/4 では、 配列 song_1[] は整数のデータ型の配列であり、各要素は 4 ビートを取るため、4 で除算します。

song_1の要素の数(音符の数)は、 sizeof(song_4) を4で割ることによって得られる。

各音符を拍* 500msで再生できるようにするには、関数 delay(beat_1[i]*500) が呼び出される。

softToneWrite(BuzPin、song_1[i]) のプロトタイプ:

void softToneWrite (int pin, int freq);

これにより、指定されたピンのトーン周波数値が更新される。周波数を0に設定するまで、トーンの再生は停止しない。

Python言語ユーザー向け

ステップ2:ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3:実行する。

sudo python3 1.2.2_PassiveBuzzer.py

コードが実行されると、ブザーが音楽を再生する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

Buzzer = 11

CL = [0, 131, 147, 165, 175, 196, 211, 248]         # Frequency of Bass tone in C major

CM = [0, 262, 294, 330, 350, 393, 441, 495]         # Frequency of Midrange tone in C major

CH = [0, 525, 589, 661, 700, 786, 882, 990]         # Frequency of Treble tone in C major

song_1 = [  CM[3], CM[5], CM[6], CM[3], CM[2], CM[3], CM[5], CM[6], # Notes of song1
            CH[1], CM[6], CM[5], CM[1], CM[3], CM[2], CM[2], CM[3],
            CM[5], CM[2], CM[3], CM[3], CL[6], CL[6], CL[6], CM[1],
            CM[2], CM[3], CM[2], CL[7], CL[6], CM[1], CL[5] ]

beat_1 = [  1, 1, 3, 1, 1, 3, 1, 1,                         # Beats of song 1, 1 means 1/8 beat
            1, 1, 1, 1, 1, 1, 3, 1,
            1, 3, 1, 1, 1, 1, 1, 1,
            1, 2, 1, 1, 1, 1, 1, 1,
            1, 1, 3 ]

song_2 = [  CM[1], CM[1], CM[1], CL[5], CM[3], CM[3], CM[3], CM[1], # Notes of song2
            CM[1], CM[3], CM[5], CM[5], CM[4], CM[3], CM[2], CM[2],
            CM[3], CM[4], CM[4], CM[3], CM[2], CM[3], CM[1], CM[1],
            CM[3], CM[2], CL[5], CL[7], CM[2], CM[1]        ]

beat_2 = [  1, 1, 2, 2, 1, 1, 2, 2,                         # Beats of song 2, 1 means 1/8 beat
            1, 1, 2, 2, 1, 1, 3, 1,
            1, 2, 2, 1, 1, 2, 2, 1,
            1, 2, 2, 1, 1, 3 ]

def setup():

    GPIO.setmode(GPIO.BOARD)                # Numbers GPIOs by physical location
    GPIO.setup(Buzzer, GPIO.OUT)    # Set pins' mode is output
    global Buzz                                             # Assign a global variable to replace GPIO.PWM
    Buzz = GPIO.PWM(Buzzer, 440)    # 440 is initial frequency.
    Buzz.start(50)                                  # Start Buzzer pin with 50% duty cycle

def loop():
    while True:
        print ('\n    Playing song 1...')
        for i in range(1, len(song_1)):             # Play song 1
            Buzz.ChangeFrequency(song_1[i]) # Change the frequency along the song note
            time.sleep(beat_1[i] * 0.5)             # delay a note for beat * 0.5s
        time.sleep(1)                                               # Wait a second for next song.

        print ('\n\n    Playing song 2...')
        for i in range(1, len(song_2)):     # Play song 1
            Buzz.ChangeFrequency(song_2[i]) # Change the frequency along the song note
            time.sleep(beat_2[i] * 0.5)     # delay a note for beat * 0.5s

def destory():
    Buzz.stop()                 # Stop the buzzer
    GPIO.output(Buzzer, 1)      # Set Buzzer pin to High
    GPIO.cleanup()                          # Release resource

if __name__ == '__main__':          # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:       # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destory()

コードの説明

CL = [0, 131, 147, 165, 175, 196, 211, 248]     # Frequency of Bass tone in C major
CM = [0, 262, 294, 330, 350, 393, 441, 495]     # Frequency of Midrange tone in C major
CH = [0, 525, 589, 661, 700, 786, 882, 990]     # Frequency of Treble tone in C major

これらは各音符の周波数である。番号1〜7が音色のCDEFGABに対応するように、最初の0は CL[0] をスキップする。

song_1 = [  CM[3], CM[5], CM[6], CM[3], CM[2], CM[3], CM[5], CM[6],
            CH[1], CM[6], CM[5], CM[1], CM[3], CM[2], CM[2], CM[3],
            CM[5], CM[2], CM[3], CM[3], CL[6], CL[6], CL[6], CM[1],
            CM[2], CM[3], CM[2], CL[7], CL[6], CM[1], CL[5] ]

これらの配列は歌の音符である。

beat_1 = [  1, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1,
            1, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,
            1, 1, 3 ]

すべての音符の拍(各番号)は、⅛拍で、つまり0.5秒を表す。

Buzz = GPIO.PWM(Buzzer, 440)
Buzz.start(50)

ピンブザーをPWMピンとして定義し、その周波数を440に設定し、 Buzz.start(50) を使用してPWMを実行する。 さらに、デューティサイクルを50%に設定する。

for i in range(1, len(song_1)):
            Buzz.ChangeFrequency(song_1[i])
            time.sleep(beat_1[i] * 0.5)

for 文を実行すると、ブザーは配列 song_1[] の音符を beat_1[] 配列の拍で再生する。

これで、パッシブブザーが音楽を再生していることが聞こえる。

現象画像
_images/image107.jpeg

1.3 ドライバー

1.3.1 モーター

前書き

このレッスンでは、L293Dを使用してDCモーターを駆動し、時計回りと反時計回りに回転させる方法を学習する。 安全上の理由で、DCモーターは大電流を必要とするため、ここでは電源モジュールを使用してモーターに電力を供給する。

部品
_images/list_1.3.1.png
原理

L293D

L293Dは、高電圧と高電流のチップで統合された4チャネルモータードライバーである。 標準のDTL、TTLロジックレベルに接続し、誘導負荷(リレーコイル、DC、ステッピングモーターなど)およびパワースイッチングトランジスタなどを駆動するように設計される。 DCモーターは、DC電気エネルギーを機械エネルギーに変換するデバイスである。それらは、優れた速度調整性能の利点により、電気駆動装置で広く使用されている。

ピンの図については、以下の図を参照してください。L293Dには、電源用の2つのピン(Vcc1とVcc2)がある。Vcc2はモーターに電力を供給し、Vcc1はチップに電力を供給するために使用される。 ここでは小型のDCモーターが使用されているため、両方のピンを+ 5Vに接続してください。

_images/image111.png

以下はL293Dの内部構造である。ピンENはイネーブルピンであり、高レベルでのみ機能する。Aは入力を表し、Yは出力を表す。それらの間の関係は右下に見ることができる。 ピンENがHighレベルのとき、AがHighの場合、YはHighレベルを出力する。AがLowの場合、YはLowレベルを出力する。ピンENがLowレベルの場合、L293Dは機能しない。

_images/image334.png

DCモーター

_images/image114.jpeg

これは5V DCモーターである。銅板の2つの端子に1つの高レベルと1つの低レベルを与えると回転する。便宜上、ピンを溶接することができる。

_images/image335.png

電源モジュール

この実験では、特に起動時と停止時にモーターを駆動するために大きな電流が必要である。 これは、Raspberry Piの通常の動作を大幅に妨害する可能性がある。そのため、このモジュールによってモーターに個別に電力を供給し、安全かつ着実に動作させる。

ブレッドボードに差し込むだけで電力を供給できる。3.3Vと5Vの電圧を提供し、付属のジャンパーキャップを介してどちらでも接続できる。

_images/image115.png
回路図

電源モジュールをブレッドボードに差し込み、ジャンパーキャップを5Vのピンに挿入すると、5Vの電圧が出力される。L293Dのピン1をGPIO22に接続し、それを高レベルに設定する。 ピン2をGPIO27に、ピン7をGPIO17に接続し、一方のピンをhighに、もう一方のピンをhighに設定する。したがって、モーターの回転方向を変更できる。

_images/image336.png
実験手順

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

_images/image117.png

注釈

電源モジュールはキットの9Vバッテリーバックルで9Vバッテリーを適用できる。電源モジュールのジャンパキャップをブレッドボードの5Vバスストリップに挿入する。

_images/image118.jpeg
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.3.1/

ステップ3: コンパイルする。

gcc 1.3.1_Motor.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードが実行されると、モーターは最初に5秒間時計回りに回転し、それから5秒間停止し、その後5秒間反時計回りに回転してから5秒間停止する。この一連の動作は繰り返し実行される。

コード

#include <wiringPi.h>
#include <stdio.h>

#define MotorPin1       0
#define MotorPin2       2
#define MotorEnable     3

int main(void){
    int i;
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(MotorPin1, OUTPUT);
    pinMode(MotorPin2, OUTPUT);
    pinMode(MotorEnable, OUTPUT);
    while(1){
        printf("Clockwise\n");
        delay(100);
        digitalWrite(MotorEnable, HIGH);
        digitalWrite(MotorPin1, HIGH);
        digitalWrite(MotorPin2, LOW);
        for(i=0;i<3;i++){
            delay(1000);
        }

        printf("Stop\n");
        delay(100);
        digitalWrite(MotorEnable, LOW);
        for(i=0;i<3;i++){
            delay(1000);
        }

        printf("Anti-clockwise\n");
        delay(100);
        digitalWrite(MotorEnable, HIGH);
        digitalWrite(MotorPin1, LOW);
        digitalWrite(MotorPin2, HIGH);
        for(i=0;i<3;i++){
            delay(1000);
        }

        printf("Stop\n");
        delay(100);
        digitalWrite(MotorEnable, LOW);
        for(i=0;i<3;i++){
            delay(1000);
        }
    }
    return 0;
}

コードの説明

digitalWrite(MotorEnable, HIGH);

L239Dを有効にする。

digitalWrite(MotorPin1, HIGH);
digitalWrite(MotorPin2, LOW);

2A(ピン7)に高レベルを設定する。1,2EN(ピン1)は高レベルなので、2Yは高レベルを出力する。

1Aに低レベルを設定すると、1Yが低レベルを出力し、モーターが回転する。

for(i=0;i<3;i++){
delay(1000);
}

このループは3 * 1000ms遅延する。

digitalWrite(MotorEnable, LOW)

1,2EN(ピン1)が低レベルの場合、L293Dは機能しない。モーターが回転を停止する。

digitalWrite(MotorPin1, LOW)
digitalWrite(MotorPin2, HIGH)

モーターの電流を逆にすると、モーターが逆回転する。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: 実行する。

sudo python3 1.3.1_Motor.py

コードが実行されると、モーターは最初に5秒間時計回りに回転し、それから5秒間停止し、その後5秒間反時計回りに回転してから5秒間停止する。この一連の動作は繰り返し実行される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

dhtPin = 17

GPIO.setmode(GPIO.BCM)

MAX_UNCHANGE_COUNT = 100

STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5

def readDht11():
    GPIO.setup(dhtPin, GPIO.OUT)
    GPIO.output(dhtPin, GPIO.HIGH)
    time.sleep(0.05)
    GPIO.output(dhtPin, GPIO.LOW)
    time.sleep(0.02)
    GPIO.setup(dhtPin, GPIO.IN, GPIO.PUD_UP)

    unchanged_count = 0
    last = -1
    data = []
    while True:
        current = GPIO.input(dhtPin)
        data.append(current)
        if last != current:
            unchanged_count = 0
            last = current
        else:
            unchanged_count += 1
            if unchanged_count > MAX_UNCHANGE_COUNT:
                break

    state = STATE_INIT_PULL_DOWN

    lengths = []
    current_length = 0

    for current in data:
        current_length += 1

        if state == STATE_INIT_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_INIT_PULL_UP
            else:
                continue
        if state == STATE_INIT_PULL_UP:
            if current == GPIO.HIGH:
                state = STATE_DATA_FIRST_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_FIRST_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_DATA_PULL_UP
            else:
                continue
        if state == STATE_DATA_PULL_UP:
            if current == GPIO.HIGH:
                current_length = 0
                state = STATE_DATA_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_PULL_DOWN:
            if current == GPIO.LOW:
                lengths.append(current_length)
                state = STATE_DATA_PULL_UP
            else:
                continue
    if len(lengths) != 40:
        #print ("Data not good, skip")
        return False

    shortest_pull_up = min(lengths)
    longest_pull_up = max(lengths)
    halfway = (longest_pull_up + shortest_pull_up) / 2
    bits = []
    the_bytes = []
    byte = 0

    for length in lengths:
        bit = 0
        if length > halfway:
            bit = 1
        bits.append(bit)
    #print ("bits: %s, length: %d" % (bits, len(bits)))
    for i in range(0, len(bits)):
        byte = byte << 1
        if (bits[i]):
            byte = byte | 1
        else:
            byte = byte | 0
        if ((i + 1) % 8 == 0):
            the_bytes.append(byte)
            byte = 0
    #print (the_bytes)
    checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
    if the_bytes[4] != checksum:
        #print ("Data not good, skip")
        return False

    return the_bytes[0], the_bytes[2]

def main():

    while True:
        result = readDht11()
        if result:
            humidity, temperature = result
            print ("humidity: %s %%,  Temperature: %s C`" % (humidity, temperature))
        time.sleep(1)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの説明

def motor(direction):
    # Clockwise
    if direction == 1:
        # Set direction
        GPIO.output(MotorPin1, GPIO.HIGH)
        GPIO.output(MotorPin2, GPIO.LOW)
        # Enable the motor
        GPIO.output(MotorEnable, GPIO.HIGH)
        print ("Clockwise")
...

変数が direction である関数 motor() を作成する。 direction = 1 の条件が満たされると、モーターは時計回りに回転する。 direction = -1 の場合、モーターは反時計回りに回転する。 そして、 direction = 0 の条件下では、回転を停止する。

def main():
    # Define a dictionary to make the script more readable
    # CW as clockwise, CCW as counterclockwise, STOP as stop
    directions = {'CW': 1, 'CCW': -1, 'STOP': 0}
    while True:
        # Clockwise
        motor(directions['CW'])
        time.sleep(5)
        # Stop
        motor(directions['STOP'])
        time.sleep(5)
        # Anticlockwise
        motor(directions['CCW'])
        time.sleep(5)
        # Stop
        motor(directions['STOP'])
        time.sleep(5)

main() 関数で、CWが1、CCWの値が-1、0がStopを指す配列 directions[] を作成する。

コードが実行されると、モーターは最初に5秒間時計回りに回転し、それから5秒間停止し、その後5秒間反時計回りに回転してから5秒間停止する。この一連の動作は繰り返し実行される。

これで、モーターブレードが回転していることが分かる。

現象画像
_images/image119.jpeg

1.3.2 サーボ

前書き

このレッスンでは、サーボを回転させる方法を学ぶ。

部品
_images/list_1.3.2.png
原理

サーボ

サーボは一般に、ケース、シャフト、ギアシステム、ポテンショメーター、DCモーター、および内蔵式ボードで構成されている。

_images/image121.png

これは次のように動作する:マイクロコントローラーはPWM信号をサーボに送信し、サーボの内蔵式ボードは信号ピンを介して信号を受信し、内部のモーターを制御して回転させる。その結果、モーターはギアシステムを駆動し、減速後にシャフトを駆動する。サーボのシャフトとポテンショメーターは接続されている。シャフトが回転する時、ポテンショメーターが駆動されるため、ポテンショメーターは電圧信号を内蔵式ボードに出力する。 その後、ボードは現在の位置に基づいて回転の方向と速度を決めるため、定義された位置で正確に停止してそのまま保持する。

_images/image122.png

角度は制御ワイヤに適用されるパルスの持続時間によって決まる。これはパルス幅変調と呼ばれる。 サーボは20ミリ秒ごとに1パルスを期待している。パルスの長さにより、モーターの回転距離が決まる。 たとえば、1.5msパルスは、モーターを90度の位置(ニュートラル位置)に回転させる。

1.5 ms未満のパルスがサーボに送信されると、サーボはある位置まで回転し、出力軸をニュートラル位置から反時計回りにある程度保持する。 パルスが1.5ミリ秒を上回る場合、逆のことが起こる。 有効な位置にサーボを回転させるように命令するパルスの最小幅と最大幅は、各サーボの機能である。 通常、パルスの最小幅は約0.5 msで、最大幅は2.5 msである。

_images/image123.jpeg
回路図
_images/image337.png
実験手順

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

_images/image125.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.3.2

ステップ3: コードをコンパイルする。

gcc 1.3.2_Servo.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

プログラムが実行されると、サーボは0度から180度まで回転し、それから180度から0度まで循環的に回転する。

コード

#include <wiringPi.h>
#include <softPwm.h>
#include <stdio.h>

#define ServoPin    1       //define the servo to GPIO1
long Map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
    return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
}
void setAngle(int pin, int angle){    //Create a funtion to control the angle of the servo.
    if(angle < 0)
        angle = 0;
    if(angle > 180)
        angle = 180;
    softPwmWrite(pin,Map(angle, 0, 180, 5, 25));
}

int main(void)
{
    int i;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    softPwmCreate(ServoPin, 0, 200);       //initialize PMW pin of servo
    while(1){
        for(i=0;i<181;i++){     // Let servo rotate from 0 to 180.                  setAngle(ServoPin,i);
            delay(2);
        }
        delay(1000);
        for(i=181;i>-1;i--){        // Let servo rotate from 180 to 0.              setAngle(ServoPin,i);
            delay(2);
        }
        delay(1000);
    }
    return 0;
}

コードの説明

long Map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
    return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
}

次のコードで値をマップする Map() 関数を作成する。

void setAngle(int pin, int angle){    //Create a funtion to control the angle of the servo.
    if(angle < 0)
        angle = 0;
    if(angle > 180)
        angle = 180;
    softPwmWrite(pin,Map(angle, 0, 180, 5, 25));
}

角度をサーボに書き込むために、関数 setAngle() を作成する。

softPwmWrite(pin,Map(angle,0,180,5,25));

この関数はPWMのデューティサイクルを変更できる。

サーボを0〜180°に回転させるために、周期が20msのときにパルス幅を0.5ms〜2.5msの範囲内で変更してください。 関数 softPwmCreate() では、周期が200x100us = 20msに設定されているため、0〜180を5x100us〜25x100usにマッピングする必要がある。

この関数のプロトタイプを以下に示す。

int softPwmCreate(int pin,int initialValue,int pwmRange);

pin: Raspberry PiのGPIOピンはPWMピンとして設定できる。

initialValue: 初期パルス幅は、initialValueに100usを掛けたものである。

pwmRange: PWMの周期は、pwmRangeに100usを掛けたものである。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 1.3.2_Servo.py

プログラムが実行されると、サーボは0度から180度まで回転し、それから180度から0度まで循環的に回転する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

SERVO_MIN_PULSE = 500
SERVO_MAX_PULSE = 2500

ServoPin = 18

def map(value, inMin, inMax, outMin, outMax):
    return (outMax - outMin) * (value - inMin) / (inMax - inMin) + outMin

def setup():
    global p
    GPIO.setmode(GPIO.BCM)       # Numbers GPIOs by BCM
    GPIO.setup(ServoPin, GPIO.OUT)   # Set ServoPin's mode is output
    GPIO.output(ServoPin, GPIO.LOW)  # Set ServoPin to low
    p = GPIO.PWM(ServoPin, 50)     # set Frequecy to 50Hz
    p.start(0)                     # Duty Cycle = 0

def setAngle(angle):      # make the servo rotate to specific angle (0-180 degrees)
    angle = max(0, min(180, angle))
    pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
    pwm = map(pulse_width, 0, 20000, 0, 100)
    p.ChangeDutyCycle(pwm)#map the angle to duty cycle and output it

def loop():
    while True:
        for i in range(0, 181, 5):   #make servo rotate from 0 to 180 deg
            setAngle(i)     # Write to servo
            time.sleep(0.002)
        time.sleep(1)
        for i in range(180, -1, -5): #make servo rotate from 180 to 0 deg
            setAngle(i)
            time.sleep(0.001)
        time.sleep(1)

def destroy():
    p.stop()
    GPIO.cleanup()

if __name__ == '__main__':     #Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()

コードの説明

p = GPIO.PWM(ServoPin, 50)     # set Frequecy to 50Hz
p.start(0)                     # Duty Cycle = 0

servoPin をPWMピンに設定し、次に周波数を50hzに、周期を20msに設定する。

p.start(0) : PWM関数を実行し、初期値を0に設定する。

def setAngle(angle):      # make the servo rotate to specific angle (0-180 degrees)
    angle = max(0, min(180, angle))
    pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
    pwm = map(pulse_width, 0, 20000, 0, 100)
    p.ChangeDutyCycle(pwm)#map the angle to duty cycle and output it

関数 setAngle() を作成して、0〜180の範囲の角度をサーボに書き込む。

angle = max(0, min(180, angle))

このコードは角度を0〜180°の範囲に制限するために使用される。

min() 関数は入力値の最小値を返す。角度が180以下の場合、180を返す。そうではない場合、角度を返す。

max() メソッドは、反復可能または最大の2つ以上のパラメーターで最大要素を返す。角度が0以上の場合は0を返し、そうでない場合は角度を返す。

pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
pwm = map(pulse_width, 0, 20000, 0, 100)
p.ChangeDutyCycle(pwm)

0〜180°の範囲をサーボにレンダリングすると、サーボのパルス幅は0.5ms(500us)〜2.5ms(2500us)に設定される。

PWMの周期は20ms(20000us)であるため、PWMのデューティサイクルは(500/20000)%-(2500/20000)%であり、0〜180の範囲は2.5〜12.5にマッピングされる。

現象画像
_images/image126.jpeg

1.3.3 ステッピングモーター

前書き

独自の設計により、ステッピングモーターはフィードバックメカニズムなしで高度な精度で制御できる。一連の磁石が取り付けられたステッパーのシャフトは、特定のシーケンスで正と負に帯電する一連の電磁コイルによって制御され、小さな「ステップ」で前後に正確に移動する。

部品
_images/list_1.3.3.png
原理

ステッピングモーター

ステッパーには、ユニポーラーとバイポーラーの2つのタイプがあり、使用しているタイプを知ることが非常に重要である。 この実験では、ユニポーラステッパーを使用する。

ステッピングモーターは単相DC電源を使用する4相モーターである。 適切な時系列でモーターのすべての相巻線に通電する限り、一歩一歩に回転させることができる。 4相リアクティブステッピングモーターの概略図:

_images/image129.png

図では、モーターの中央にローター-歯車状の永久磁石がある。ローターの周りの0〜5は歯である。 さらに外側には、8つの磁極があり、それぞれ反対側の2つの磁極がコイル巻線で接続されている。 そのため、AからDまでの4つのペアを形成し、相と呼ばれる。スイッチSA、SB、SC、SDに接続するリード線が4本ある。 したがって、回路では4つの相が並列になっており、1つの相の2つの磁極は直列になっている。

4相ステッピングモーターの動作原理は次の通りである:

スイッチSBの電源がオンになると、スイッチSA、SC、およびSDの電源がオフになり、B相の磁極がローターの歯0と3と整列する。 同時に、歯1と4は、C相とD相の極を持つ互い違いに配列した歯を生成する。 歯2と5は、D相とA相の極を持つ互い違いに配列した歯を生成する。 スイッチSCの電源がオン、スイッチSB、SA、およびSDの電源がオフの場合、ローターはC相巻線の磁場と歯1と4の間の磁場の下で回転する。 次に、歯1と4がC相巻線の磁極と整列する。 一方、歯0と3はA相とB相の極を持つ互い違いに配列した歯を生成し、歯2と5はA相とD相の極を持つ互い違いに配列した歯を生成する。 同様の状況が続いていく。 A、B、C、D相に順番に通電すると、ローターはA、B、C、Dの順に回転する。

_images/image130.png

4相ステッピングモーターには、3つの動作モードがある:シングル4ステップ、ダブル4ステップ、および8ステップ。 シングル4ステップとダブル4ステップのステップ角は同じであるが、シングル4ステップの駆動トルクは小さくなる。 8ステップのステップ角は、シングル4ステップおよびダブル4ステップの半分である。 したがって、8ステップの動作モードは、高い駆動トルクを維持し、制御精度を向上させることができる。

使用するステッピングモーターのステータには32個の磁極があるため、円には32ステップが必要である。 ステッピングモーターの出力軸は減速装置セットに接続され、減速比は1/64である。 ですから、最終出力シャフトは32 * 64 = 2048ステップを必要とする円を回転させる。

ULN2003

モーターを円に適用するには、ドライバーボードを使用する必要があります。 ステッパーモータードライバ-ULN2003は7チャネルインバータサークルです。 つまり、入力ピンが高レベルの場合、ULN2003の出力ピンは低レベルであり、その逆も同様です。 IN1 に高レベルを供給し、IN2、IN3、IN4 に低レベルを供給すると、出力端 OUT1 は低レベルであり、他のすべての出力端は高レベルになります。 チップの内部構造を以下に示します。

_images/image338.png

ULN2003チップと4つのLEDで構成されるステッピングモータードライバーを以下に示す。 ボードでは、IN1、IN2、IN3、IN4が入力として機能し、4つのLED、A、B、C、Dは入力ピンの指示器である。 さらに、OUT1、OUT2、OUT3、およびOUT4はそれぞれ、ステッピングモータードライバーのSA、SB、SC、およびSDに接続されている。 IN1の値が高レベルに設定されると、Aが点灯し、スイッチSAの電源がオンになり、ステッピングモーターが1ステップで回転する。 同様のケースが何度も繰り返される。したがって、ステッピングモーターに特定の時系列を与えるだけで、ステップごとに回転する。 ステッピングモーターに特定の時系列を提供するために、ここでULN2003を使用する。

_images/image132.png
回路図
_images/image339.png
実験手順

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

_images/image134.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.3.3/

ステップ3: コードをコンパイルする。

gcc 1.3.3_StepperMotor.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードが実行されると、入力「a」または「c」に応じてステッピングモーターが時計回りまたは反時計回りに回転する。

コード

#include <stdio.h>
#include <wiringPi.h>

const int motorPin[] = {1, 4, 5, 6};
int rolePerMinute = 15;
int stepsPerRevolution = 2048;
int stepSpeed = 0;

void rotary(char direction){
    if(direction == 'c'){
        for(int j=0;j<4;j++){
            for(int i=0;i<4;i++)
                {digitalWrite(motorPin[i],0x99>>j & (0x08>>i));}
            delayMicroseconds(stepSpeed);
        }
    }
    else if(direction =='a'){
        for(int j=0;j<4;j++){
            for(int i=0;i<4;i++)
                {digitalWrite(motorPin[i],0x99<<j & (0x80>>i));}
            delayMicroseconds(stepSpeed);
        }
    }
}

void loop()
{
    char direction = '0';
    while (1)
    {
        printf("select motor direction a=anticlockwise, c=clockwise: ");
        delay(100);
        direction=getchar();
        if (direction == 'c')
        {
            printf("motor running clockwise\n");
            delay(100);
            break;
        }
        else if (direction == 'a')
        {
            printf("motor running anti-clockwise\n");
            delay(100);
            break;
        }
        else
        {
            printf("input error, please try again!\n");
            delay(100);
        }
    }
    while(1)
    {
        rotary(direction);
    }
}

void main(void)
{
    if (wiringPiSetup() == -1)
    {
        printf("setup wiringPi failed !");
        return;
    }
    for (int i = 0; i < 4; i++)
    {
        pinMode(motorPin[i], OUTPUT);
    }
    stepSpeed = (60000000 / rolePerMinute) / stepsPerRevolution;
    loop();
}

コードの説明

int rolePerMinute = 15;
int stepsPerRevolution = 2048;
int stepSpeed = 0;

rolePerMinute: 1分あたりの回転数。このキットで使用されるステッピングモーターのRPMは0〜17である。

stepPerRevolution: 1ターンのステップ数、およびこのキットで使用されるステッピングモーターには、1回転あたり2048ステップが必要である。

stepSpeed: 各ステップに使用される時間、 main() では、それらに値を割り当てる。 (60000000/rolePerMinute)/stepsPerRevolution (60,000,000 us = 1分)

void loop()
{
    char direction = '0';
    while (1)
    {
        printf("select motor direction a=anticlockwise, c=clockwise: ");
        direction=getchar();
        if (direction == 'c')
        {
            printf("motor running clockwise\n");
            break;
        }
        else if (direction == 'a')
        {
            printf("motor running anti-clockwise\n");
            break;
        }
        else
        {
            printf("input error, please try again!\n");
        }
    }
    while(1)
    {
        rotary(direction);
    }
}

loop() 関数は、2つの部分(2つの while(1) の間にある)に大まかに分けられている:

最初の部分の目的は、key valueを取得することである。「a」または「c」が取得されたら、ループを終了して入力を停止してください。

2番目の部分は rotary(direction) を呼び出して、ステッピングモーターを動作させる。

void rotary(char direction){
    if(direction == 'c'){
        for(int j=0;j<4;j++){
            for(int i=0;i<4;i++)
                {digitalWrite(motorPin[i],0x99>>j & (0x08>>i));}
            delayMicroseconds(stepSpeed);
        }
    }
    else if(direction =='a'){
        for(int j=0;j<4;j++){
            for(int i=0;i<4;i++)
                {digitalWrite(motorPin[i],0x99<<j & (0x80>>i));}
            delayMicroseconds(stepSpeed);
        }
    }
}

ステッピングモーターを 時計回りに回転させる ために、motorPinのレベルス状態要求は以下の通りである:

_images/image340.png

したがって、2層のfor文を使用してMotorPinの潜在的な書き込みを実装する。

Step1では、j=0、i=0〜4。

motorPin[0] は高レベル (10011001 & 00001000 = 1) で書き込まれる

motorPin[1] は低レベル (10011001 & 00000100 = 0) で書き込まれる

motorPin[2] は低レベル (10011001 & 00000010 = 0) で書き込まれる

motorPin[3] は高レベル (10011001 & 00000001 = 1) で書き込まれる

Step2では、j=1、i= 0〜4。

motorPin[0] は高レベル (01001100 & 00001000 = 1) で書き込まれる

motorPin[1] は低レベル (01001100 & 00000100 = 1) などで書き込

まれる。

また、ステッピングモーターを 反時計回り に回転させるために、motorPinのレベルステータスを次の表に示す。

_images/image341.png

Step1では、j=0、i=0〜4。

motorPin[0] は高レベル (10011001 & 10000000 = 1)で書き込まれる

motorPin[1] は低レベル (10011001 & 01000000 = 0)で書き込まれる

ステップ2では、j=1、i=0〜4。

motorPin[0] は高レベル (00110010 & 10000000 = 0)で書き込まれる

motorPin[1] は低レベル (00110010 & 01000000 = 0)で書き込まれる

まれる。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 1.3.3_StepperMotor.py

コードが実行されると、入力「a」または「c」に応じて、ステッピングモーターが時計回りまたは反時計回りに回転する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
from time import sleep

motorPin = (18,23,24,25)
rolePerMinute =15
stepsPerRevolution = 2048
stepSpeed = (60/rolePerMinute)/stepsPerRevolution

def setup():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    for i in motorPin:
        GPIO.setup(i, GPIO.OUT)

def rotary(direction):
    if(direction == 'c'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99>>j & (0x08>>i))
            sleep(stepSpeed)

    elif(direction == 'a'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99<<j & (0x80>>i))
            sleep(stepSpeed)

def loop():
    while True:
        direction = input('select motor direction a=anticlockwise, c=clockwise: ')
        if(direction == 'c'):
            print('motor running clockwise\n')
            break
        elif(direction == 'a'):
            print('motor running anti-clockwise\n')
            break
        else:
            print('input error, please try again!')
    while True:
        rotary(direction)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コードの説明

rolePerMinute =15
stepsPerRevolution = 2048
stepSpeed = (60/rolePerMinute)/stepsPerRevolution

rolePerMinute: 1分あたりの回転数。このキットで使用されるステッピングモーターのRPMは0〜17である。

stepPerRevolution: 1ターンのステップ数、およびこのキットで使用されるステッピングモーターには、1回転あたり2048ステップが必要である。

stepSpeed: 各ステップに使用される時間。それらに値を割り当てる: (60/rolePerMinute)/stepsPerRevolution (60s = 1分)。

def loop():
    while True:
        direction = input('select motor direction a=anticlockwise, c=clockwise: ')
        if(direction == 'c'):
            print('motor running clockwise\n')
            break
        elif(direction == 'a'):
            print('motor running anti-clockwise\n')
            break
        else:
            print('input error, please try again!')
    while True:
        rotary(direction)

loop() 関数は、大きく分けて2つの部分に分かれている(2つの while(1) にある):

最初の部分の目的は、key valueを取得することである。「a」または「c」が取得されたら、ループを終了して入力を停止してください。

2番目の部分は rotary(direction) を呼び出して、ステッピングモーターを動作させる。

def rotary(direction):
    if(direction == 'c'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99>>j & (0x08>>i))
            sleep(stepSpeed)

    elif(direction == 'a'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99<<j & (0x80>>i))
            sleep(stepSpeed)

ステッピングモーターを時計回りに回転させるために、motorPinのレベルステータスを次の表に示す:

_images/image342.png

したがって、2層のfor文を使用してMotorPinの潜在的な書き込みを実装する。

Step1では、j=0、i=0〜4。

motorPin[0] は高レベル (10011001 & 00001000 = 1) で書き込まれる

motorPin[1] は低レベル (10011001 & 00000100 = 0) で書き込まれる

motorPin[2] は低レベル (10011001 & 00000010 = 0) で書き込まれる

motorPin[3] は高レベル (10011001 & 00000001 = 1) で書き込まれる

Step2では、j=1、i= 0〜4。

motorPin[0] は高レベル (01001100 & 00001000 = 1) で書き込まれる

motorPin[1] は低レベル (01001100 & 00000100 = 1) などで書き込

まれる。

また、ステッピングモーターを 反時計回り に回転させるために、motorPinのレベルステータスを次の表に示す。

_images/image343.png

Step1では、j=0、i=0〜4。

motorPin[0] は高レベル (10011001 & 10000000 = 1)で書き込まれる

motorPin[1] は低レベル (10011001 & 01000000 = 0)で書き込まれる

ステップ2では、j=1、i=0〜4。

motorPin[0] は高レベル (00110010 & 10000000 = 0)で書き込まれる

motorPin[1] は低レベル (00110010 & 01000000 = 0)で書き込まれる

まれる。

現象画像
_images/image135.jpeg

1.3.4 リレー

前書き

このレッスンでは、リレーの使用方法を学習する。 これは、自動制御システムで一般的に使用される部品の1つである。 電圧、電流、温度、圧力などが所定の値に到達、超過、または低下すると、リレーは回路を接続または中断して、機器を制御したり保護したりする。

部品
_images/list_1.3.4.png
原理

ダイオード

ダイオードは一方向に電流が流れる電子機器の2端子部品である。 電流の流れる方向に低い抵抗を提供し、反対方向に高い抵抗を提供する。 ダイオードは主に、通常は分極している回路の起電力による部品の損傷を防ぐために使用される。

_images/image344.png

ダイオードの2つの端子は極性があり、陽極と呼ばれる正の端と陰極と呼ばれる負の端がある。 陰極は通常、銀でできているか、またあカラーバンドを持っている。 電流の方向を制御することは、ダイオードの重要な機能の1つである。 ダイオードの電流は陽極から陰極に流れる。ダイオードの動作は、逆止弁の動作に似ている。 ダイオードの最も重要な特性の1つは、非線形電流電圧である。 より高い電圧が陽極に接続されている場合、電流は陽極から陰極に流れ、プロセスは順方向バイアスと呼ばれる。 ただし、より高い電圧が陰極に接続されている場合、ダイオードは電気を通さず、プロセスは逆方向バイアスと呼ばれる。

リレー

ご存知のように、リレーは、入力信号に応じて2つ以上のポイントまたはデバイス間の接続を提供するために使用されるデバイスである。 つまり、デバイスはACとDCの両方で動作する可能性があるため、リレーはコントローラーとデバイスの間を分離する。 しかしながら、DC上で動作するマイクロコントローラーから信号を受信するため、ギャップを埋めるためのリレーが必要である。 小さな電気信号で大量の電流または電圧を制御する必要がある場合には、リレーは非常に有用である。

すべてのリレーには5つのパーツがある:

電磁石 - ワイヤーのコイルで巻かれた鉄心で構成されている。通電させると、磁気になります。したがって、電磁石と呼ばれる。

電機子 - 可動磁気ストリップは電機子と呼ばれる。それらに電流が流れると、コイルが通電されて磁場が生成され、常開(N/O)または常閉(N/C)ポイントを作成したり切断したりするために使用される。また、電機子は直流(DC)と交流(AC)で移動できる。

スプリング - 電磁石のコイルに電流が流れない場合、スプリングは電機子を引き離し、回路を完成できない。

電気 接点 のセット-2つの接点がある:

  • 通常開-リレーがアクティブなときに接続され、非アクティブなときに切断されます。

  • 常閉-リレーが作動している時に接続しなく、リ

成形フレーム - 保護のため、リレーはプラスチックで覆われている。

リレーの動作

リレーの動作原理は非常に簡単である。リレーに電力が供給されると、制御コイルに電流が流れ始める。その結果、電磁石が通電を開始する。次に、電機子がコイルに引き付けられ、可動接点が一緒に引き下げられ、常開接点に接続される。したがって、負荷がかけられた回路が通電される。次に、可動接点がスプリングの力で常閉接点に引き上げられるため、回路を遮断することも同様のケースになる。このようにして、リレーのオンとオフの切り替えにより、負荷回路の状態を制御できる。

_images/image142.jpeg
回路図
_images/image345.png
実験手順

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

_images/image144.png
C言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/c/1.3.4

ステップ3: コードをコンパイルする。

gcc 1.3.4_Relay.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行後、LEDが点灯する。さらに、通常は閉じている接点を切断し、通常は開いている接点を閉じることによって発生するカチカチという声が聞こえる。

コード

#include <wiringPi.h>
#include <stdio.h>
#define RelayPin 0

int main(void){
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    pinMode(RelayPin, OUTPUT);   //set GPIO17(GPIO0) output
    while(1){
        // Tick
        printf("Relay Open......\n");
        delay(100);
        digitalWrite(RelayPin, LOW);
        delay(1000);
        // Tock
        printf("......Relay Close\n");
        delay(100);
        digitalWrite(RelayPin, HIGH);
        delay(1000);
    }

    return 0;
}

コードの説明

digitalWrite(RelayPin, LOW);

I/Oポートを低レベル(0V)に設定すると、トランジスタに通電されず、コイルに電力が供給されない。 電磁力がないため、リレーが開き、LEDは点灯しない。

digitalWrite(RelayPin, HIGH);

I/Oポートを高レベル(5V)に設定して、トランジスタに通電する。 リレーのコイルに電力を供給し、電磁力が発生すると、リレーが閉じてLEDが点灯する。

Pythonユーザーの場合

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: 実行する。

sudo python3 1.3.4_Relay.py

コードの実行中、LEDが点灯する。 さらに、通常は閉じている接点を切断し、通常は開いている接点を閉じることによって発生するカチカチという声が聞こえる。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

# Set GPIO17 as control pin
relayPin = 17

# Define a setup function for some setup
def setup():
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    # Set relayPin's mode to output,
    # and initial level to High(3.3v)
    GPIO.setup(relayPin, GPIO.OUT, initial=GPIO.HIGH)

# Define a main function for main process
def main():
    while True:
        print ('Relay open...')
        # Tick
        GPIO.output(relayPin, GPIO.LOW)
        time.sleep(1)
        print ('...Relay close')
        # Tock
        GPIO.output(relayPin, GPIO.HIGH)
        time.sleep(1)

# Define a destroy function for clean up everything after
# the script finished
def destroy():
    # Turn off LED
    GPIO.output(relayPin, GPIO.HIGH)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()

コードの説明

GPIO.output(relayPin, GPIO.LOW)

トランジスタのピンを低レベルに設定して、リレーを開く。LEDは点灯しない。

time.sleep(1)

1秒待つ。

GPIO.output(relayPin, GPIO.HIGH)

トランジスタのピンを低レベルに設定してリレーを作動させ、LEDが点灯する。

現象画像
_images/image145.jpeg

2 入力 (Pi 5用ではない)

2.1 コントローラー

2.1.1 ボタン

前書き

このレッスンでは、LEDをボタンでオンまたはオフにする方法を学習する。

部品
_images/list_2.1.1_Button.png
原理

ボタン

ボタンは電子デバイスを制御するために使用される一般的な部品である。通常、回路を接続または遮断するためのスイッチとして使用される。ボタンにはさまざまなサイズと形状があるが、ここで使用するものは、次の図に示すように6mmのミニボタンである。

左側の2つのピンが接続されており、右側の方は左側と同じである。以下を参照してください:

_images/image148.png

以下に示す記号は、通常、回路内のボタンを表すために使用される。

_images/image301.png

ボタンを押すと、4つのピンが接続され、回路が閉じる。

回路図

Raspberry Piの入力として常開ボタンを使用し、接続は下の概略図に示されている。 ボタンを押すと、GPIO18は低レベル(0V)に変わる。 プログラミングによってGPIO18の状態を検出できる。 つまり、GPIO18が低レベルになった場合、ボタンが押されたことを意味する。 ボタンが押されたときに対応するコードを実行すると、LEDが点灯する。

_images/image302.png _images/image303.png
実験手順

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

_images/image152.png
C言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.1.1/

注釈

cd を使用して、この実験のコードのパスにディレクトリを変更する。

ステップ3: コードをコンパイルする。

gcc 2.1.1_Button.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行後、ボタンを押すと、LEDが点灯する。それ以外の場合は消灯する。

コード

#include <wiringPi.h>
#include <stdio.h>

#define LedPin      0
#define ButtonPin   1

int main(void){
    // When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(LedPin, OUTPUT);
    pinMode(ButtonPin, INPUT);
    digitalWrite(LedPin, HIGH);

    while(1){
        // Indicate that button has pressed down
        if(digitalRead(ButtonPin) == 0){
            // Led on
            digitalWrite(LedPin, LOW);
        //  printf("...LED on\n");
        }
        else{
            // Led off
            digitalWrite(LedPin, HIGH);
        //  printf("LED off...\n");
        }
    }
    return 0;
}

コードの説明

#define LedPin      0

T_ExtensionボードのGPIO17ピンは、wiringPiのGPIO0と同じである。

#define ButtonPin   1

ButtonPinはGPIO1に接続されている。

pinMode(LedPin, OUTPUT);

LedPinを出力として設定し、値を割り当てる。

pinMode(ButtonPin, INPUT);

ButtonPinを入力として設定し、ButtonPinの値を読み取る。

while(1){
        // Indicate that button has pressed down
        if(digitalRead(ButtonPin) == 0){
            // Led on
            digitalWrite(LedPin, LOW);
        //  printf("...LED on\n");
        }
        else{
            // Led off
            digitalWrite(LedPin, HIGH);
        //  printf("LED off...\n");
        }
    }

if(digitalRead(ButtonPin))== 0: ボタンが押されたかどうかを確認してください。 ボタンを押してLEDを点灯させると、 digitalWrite(LedPin、LOW) を実行してください。

Python言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: コードを実行する。

sudo python3 2.1.1_Button.py

それから、ボタンを押すと、LEDが点灯する。もう一度ボタンを押すと、LEDが消灯する。同時に、LEDの状態が画面にプリントされる。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

LedPin = 17 # Set GPIO17 as LED pin
BtnPin = 18 # Set GPIO18 as button pin


Led_status = True # Set Led status to True(OFF)

# Define a setup function for some setup
def setup():
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)  # Set LedPin's mode to output, and initial level to high (3.3v)
    GPIO.setup(BtnPin, GPIO.IN) # Set BtnPin's mode to input.

# Define a callback function for button callback
def swLed(ev=None):
    global Led_status
    # Switch led status(on-->off; off-->on)
    Led_status = not Led_status
    GPIO.output(LedPin, Led_status)
    if Led_status:
        print ('LED OFF...')
    else:
        print ('...LED ON')

# Define a main function for main process
def main():
    # Set up a falling detect on BtnPin,
    # and callback function to swLed
    GPIO.add_event_detect(BtnPin, GPIO.FALLING, callback=swLed)
    while True:
        # Don't do anything.
        time.sleep(1)

# Define a destroy function for clean up everything after
# the script finished
def destroy():
    # Turn off LED
    GPIO.output(LedPin, GPIO.HIGH)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()

コードの説明

LedPin = 17

GPIO17をLEDピンとして設定する。

BtnPin = 18

GPIO18をボタンピンとして設定する。

GPIO.add_event_detect(BtnPin, GPIO.FALLING, callback=swLed)

BtnPinで立ち下がり検出を設定してから、BtnPinの値が高レベルから低レベルに変わると、 ボタンが押されたことを意味する。次のステップは、関数swledを呼び出す。

def swLed(ev=None):
global Led_status
# Switch led status(on-->off; off-->on)
Led_status = not Led_status
GPIO.output(LedPin, Led_status)

ボタンコールバックとしてコールバック関数を定義する。 ボタンが初めて押され、 not Led_status 条件がfalseの場合、 GPIO.output() 関数を呼び出してLEDを点灯させる。 ボタンをもう一度押すと、LEDの状態が false から true に変換され、LEDが消灯する。

現象画像
_images/image153.jpeg

2.1.2 スライドスイッチ

前書き

このレッスンでは、スライドスイッチの使用方法を学習する。 通常、スライドスイッチは電源スイッチとしてPCBにはんだ付けされるが、 ここではブレッドボードに挿入する必要があるため、締め付けられない場合がある。 そして、その機能を示すためにブレッドボードで使用する。

部品
_images/list_2.1.2_slide_switch.png
原理

スライドスイッチ

_images/image156.jpeg

スライドスイッチは名前が示すように、スイッチバーをスライドさせて回路を接続または遮断し、 さらに回路を切り替えるものである。汎用タイプは、SPDT、SPTT、DPDT、DPTTなどである。 スライドスイッチは低電圧回路で一般的に使用されている。融通性と安定性の特徴を備えており、 電気機器や電気玩具に広く適用されている。

仕組み:中央のピンを固定ピンとして設定する。 スライドを左に引くと、左の2つのピンが接続され、右に引くと、 右側の2つのピンが接続される。したがって、 回路を接続または遮断するスイッチとして機能する。以下の図を参照してください:

_images/image304.png

スライドスイッチの回路記号を以下に示す。図のピン2は中央のピンを指す。

_images/image159.png

コンデンサ

コンデンサーは、小さな充電式バッテリーのように、エネルギーを電荷の形で蓄えたり、プレート間に電位差(静的電圧)を生成する能力を持つ部品である。

静電容量の標準単位

Microfarad (μF) 1μF = 1/1,000,000 = 0.000001 = \(10^{- 6}\) F

Nanofarad (nF) 1nF = 1/1,000,000,000 = 0.000000001 = \(10^{- 9}\)F

Picofarad (pF) 1pF = 1/1,000,000,000,000 = 0.000000000001 = \(10^{- 12}\)F

注釈

ここでは、 104コンデンサ (10 x \(10^{4}\)PF) を使用する。 抵抗器のリングのように、コンデンサの数字は、ボードに組み立てられた後に値を読み取ることに役立つ。 最初の2桁は値を表し、数字の最後の桁は乗数を指す(pF単位)。

回路図

スライドスイッチの中央のピンをGPIO17に接続し、2つのLEDをそれぞれGPIO22とGPIO27に接続する。 次に、スライドを引くと、2つのLEDが交互に点灯する。

_images/image305.png _images/image306.png
実験手順

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

_images/image161.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.1.2

ステップ3: コンパイルする。

gcc 2.1.2_Slider.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行中に、スイッチを左側に接続すると、黄色のLEDが点灯する。右側に接続すると、赤いライトが点灯する。

コード

#include <wiringPi.h>
#include <stdio.h>
#define slidePin        0
#define led1            3
#define led2            2

int main(void)
{
    // When initialize wiring failed, print message to screen
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }
    pinMode(slidePin, INPUT);
    pinMode(led1, OUTPUT);
    pinMode(led2, OUTPUT);
    while(1){
        // slide switch high, led1 on
        if(digitalRead(slidePin) == 1){
            digitalWrite(led1, LOW);
            digitalWrite(led2, HIGH);
            printf("LED1 on\n");
            delay(100);
        }
        // slide switch low, led2 on
        if(digitalRead(slidePin) == 0){
            digitalWrite(led2, LOW);
            digitalWrite(led1, HIGH);
            printf(".....LED2 on\n");
            delay(100);
        }
    }
    return 0;
}

コードの説明

if(digitalRead(slidePin) == 1){
            digitalWrite(led1, LOW);
            digitalWrite(led2, HIGH);
            printf("LED1 on\n");
    }

スライドを右に引くと、中央のピンと右のピンが接続される。 Raspberry Piは中央のピンで高レベルを読み取るため、LED1は点灯し、LED2は消灯する。

if(digitalRead(slidePin) == 0){
            digitalWrite(led2, LOW);
            digitalWrite(led1, HIGH);
            printf(".....LED2 on\n");
        }

スライドを左に引くと、中央のピンと左のピンが接続されます。Raspberry Piが低レベルを読み取るため、LED2が点灯し、LED1が消灯する。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: 実行する。

sudo python3 2.1.2_Slider.py

コードの実行中に、スイッチを左側に接続すると、黄色のLEDが点灯する。右側に接続すると、赤いライトが点灯する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

# Set #17 as slide switch pin, #22 as led1 pin, #27 as led2 pin
slidePin = 17
led1Pin = 22
led2Pin = 27

# Define a setup function for some setup
def setup():
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    # Set slidePin input
    # Set ledPin output,
    # and initial level to High(3.3v)
    GPIO.setup(slidePin, GPIO.IN)
    GPIO.setup(led1Pin, GPIO.OUT, initial=GPIO.HIGH)
    GPIO.setup(led2Pin, GPIO.OUT, initial=GPIO.HIGH)

# Define a main function for main process
def main():
    while True:
        # slide switch high, led1 on
        if GPIO.input(slidePin) == 1:
            print ('LED1 ON')
            GPIO.output(led1Pin, GPIO.LOW)
            GPIO.output(led2Pin, GPIO.HIGH)

        # slide switch low, led2 on
        if GPIO.input(slidePin) == 0:
            print ('    LED2 ON')
            GPIO.output(led2Pin, GPIO.LOW)
            GPIO.output(led1Pin, GPIO.HIGH)

        time.sleep(0.5)
# Define a destroy function for clean up everything after
# the script finished
def destroy():
    # Turn off LED
    GPIO.output(led1Pin, GPIO.HIGH)
    GPIO.output(led2Pin, GPIO.HIGH)
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()

コードの説明

if GPIO.input(slidePin) == 1:
    GPIO.output(led1Pin, GPIO.LOW)
    GPIO.output(led2Pin, GPIO.HIGH)

スライドを右に引くと、中央のピンと右のピンが接続される。 Raspberry Piは中央のピンで高レベルを読み取るため、LED1は点灯し、LED2は消灯する。

if GPIO.input(slidePin) == 0:
    GPIO.output(led2Pin, GPIO.LOW)
    GPIO.output(led1Pin, GPIO.HIGH)

スライドを左に引くと、中央のピンと左のピンが接続されます。 Raspberry Piが低レベルを読み取るため、LED2が点灯し、LED1が消灯する。

現象画像
_images/image162.jpeg

2.1.3 チルトスイッチ

前書き

これは、内部に金属製のボールがあるボールチルトスイッチである。小さな角度の傾きを検出するために使用される。

部品
_images/list_2.1.3_tilt_switch.png
原理

チルト

原理は非常に簡単である。スイッチが特定の角度に傾けられると、内側のボールが転がり落ち、外側のピンに接続された2つの接点に触れて、回路をトリガーする。 そうしないと、ボールが接点から遠ざかり、回路が遮断される。

_images/image167.png
回路図
_images/image307.png _images/image308.png
実験手順

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

_images/image169.png
C言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.1.3/

ステップ3: コンパイルする。

gcc 2.1.3_Tilt.c -lwiringPi

ステップ4: 実行する。

sudo ./a.out

水平に置くと、緑色のLEDが点灯する。傾けると、「Tilt!」画面にプリントされ、赤いLEDが点灯する。再び水平に置くと、緑色のLEDが再び点灯する。

コード

#include <wiringPi.h>
#include <stdio.h>

#define TiltPin     0
#define Gpin        2
#define Rpin        3

void LED(char* color)
{
    pinMode(Gpin, OUTPUT);
    pinMode(Rpin, OUTPUT);
    if (color == "RED")
    {
        digitalWrite(Rpin, HIGH);
        digitalWrite(Gpin, LOW);
    }
    else if (color == "GREEN")
    {
        digitalWrite(Rpin, LOW);
        digitalWrite(Gpin, HIGH);
    }
    else
        printf("LED Error");
}

int main(void)
{
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(TiltPin, INPUT);
    LED("GREEN");

    while(1){
        if(0 == digitalRead(TiltPin)){
            delay(10);
            if(0 == digitalRead(TiltPin)){
                LED("RED");
                printf("Tilt!\n");
                delay(100);
            }
        }
        else if(1 == digitalRead(TiltPin)){
            delay(10);
            if(1 == digitalRead(TiltPin)){
                LED("GREEN");
            }
        }
    }
    return 0;
}

コードの説明

void LED(char* color)
{
    pinMode(Gpin, OUTPUT);
    pinMode(Rpin, OUTPUT);
    if (color == "RED")
    {
        digitalWrite(Rpin, HIGH);
        digitalWrite(Gpin, LOW);
    }
    else if (color == "GREEN")
    {
        digitalWrite(Rpin, LOW);
        digitalWrite(Gpin, HIGH);
    }
    else
        printf("LED Error");
}

関数 LED() を定義して、2つのLEDをオン・オフにする。 パラメータの色が赤の場合、赤のLEDが点灯する。 同様に、パラメータの色が緑の場合、緑のLEDが点灯する。

while(1){
        if(0 == digitalRead(TiltPin)){
            delay(10);
            if(0 == digitalRead(TiltPin)){
                LED("RED");
                printf("Tilt!\n");
            }
        }
        else if(1 == digitalRead(TiltPin)){
            delay(10);
            if(1 == digitalRead(TiltPin)){
                LED("GREEN");
            }
        }
    }

傾斜スイッチの読み取り値が0の場合、傾斜スイッチが傾斜していることを意味し、 関数LEDにパラメーター「RED」を書き込んで赤色LEDを点灯させる。 そうしない場合、緑色のLEDが点灯する。

Python言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 2.1.3_Tilt.py

水平に置くと、緑色のLEDが点灯する。 傾けると、「Tilt!」画面にプリントされ、赤いLEDが点灯する。 再び水平に置くと、緑色のLEDが再び点灯する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

dhtPin = 17

GPIO.setmode(GPIO.BCM)

MAX_UNCHANGE_COUNT = 100

STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5

def readDht11():
    GPIO.setup(dhtPin, GPIO.OUT)
    GPIO.output(dhtPin, GPIO.HIGH)
    time.sleep(0.05)
    GPIO.output(dhtPin, GPIO.LOW)
    time.sleep(0.02)
    GPIO.setup(dhtPin, GPIO.IN, GPIO.PUD_UP)

    unchanged_count = 0
    last = -1
    data = []
    while True:
        current = GPIO.input(dhtPin)
        data.append(current)
        if last != current:
            unchanged_count = 0
            last = current
        else:
            unchanged_count += 1
            if unchanged_count > MAX_UNCHANGE_COUNT:
                break

    state = STATE_INIT_PULL_DOWN

    lengths = []
    current_length = 0

    for current in data:
        current_length += 1

        if state == STATE_INIT_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_INIT_PULL_UP
            else:
                continue
        if state == STATE_INIT_PULL_UP:
            if current == GPIO.HIGH:
                state = STATE_DATA_FIRST_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_FIRST_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_DATA_PULL_UP
            else:
                continue
        if state == STATE_DATA_PULL_UP:
            if current == GPIO.HIGH:
                current_length = 0
                state = STATE_DATA_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_PULL_DOWN:
            if current == GPIO.LOW:
                lengths.append(current_length)
                state = STATE_DATA_PULL_UP
            else:
                continue
    if len(lengths) != 40:
        #print ("Data not good, skip")
        return False

    shortest_pull_up = min(lengths)
    longest_pull_up = max(lengths)
    halfway = (longest_pull_up + shortest_pull_up) / 2
    bits = []
    the_bytes = []
    byte = 0

    for length in lengths:
        bit = 0
        if length > halfway:
            bit = 1
        bits.append(bit)
    #print ("bits: %s, length: %d" % (bits, len(bits)))
    for i in range(0, len(bits)):
        byte = byte << 1
        if (bits[i]):
            byte = byte | 1
        else:
            byte = byte | 0
        if ((i + 1) % 8 == 0):
            the_bytes.append(byte)
            byte = 0
    #print (the_bytes)
    checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
    if the_bytes[4] != checksum:
        #print ("Data not good, skip")
        return False

    return the_bytes[0], the_bytes[2]

def main():

    while True:
        result = readDht11()
        if result:
            humidity, temperature = result
            print ("humidity: %s %%,  Temperature: %s C`" % (humidity, temperature))
        time.sleep(1)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの説明

GPIO.add_event_detect(TiltPin, GPIO.BOTH, callback=detect, bouncetime=200)

TiltPinで検出を設定し、検出する関数をコールバックする。

def Led(x):
    if x == 0:
        GPIO.output(Rpin, 1)
        GPIO.output(Gpin, 0)
    if x == 1:
        GPIO.output(Rpin, 0)
        GPIO.output(Gpin, 1)

関数 Led() を定義して、2つのLEDをオンまたはオフにする。 x=0の場合、赤いLEDが点灯する。そうしないと、緑色のLEDが点灯する。

def Print(x):
    if x == 0:
        print ('    *************')
        print ('    *   Tilt!   *')
        print ('    *************')

関数 Print() を作成して、画面上の上記の文字をプリントする。

def detect(chn):
    Led(GPIO.input(TiltPin))
    Print(GPIO.input(TiltPin))

傾斜コールバックのコールバック関数を定義する。傾斜スイッチの読み取り値を取得してから、 関数 Led() が傾斜スイッチの読み取り値に依存する2つのLEDを点灯・消灯させる。

現象画像
_images/image170.jpeg

2.1.4 ポテンショメータ

前書き

ADC機能を使用してアナログ信号をデジタル信号に変換でき、この実験では、 ADC0834を使用してADCに関する関数を取得する。 ここでは、ポテンショメータを使用してこのプロセスを実装する。 ポテンショメーターはADC機能によって変換される物理量-電圧を変更する。

部品
_images/list_2.1.4_potentiometer.png
原理

ADC0834

ADC0834 は、入力構成可能なマルチチャンネル マルチプレクサとシリアル入出力を備えた 8 ビットの逐次比較型 A/D コンバータです。 シリアル入出力は、標準的なシフトレジスターやマイクロプロセッサーとのインターフェースとして構成されています。

_images/image309.png

操作の順序

変換はCSをlowに設定することで開始され、 論理回路がすべて有効になる。 変換プロセスを完了するには、CSをlowに保持する必要がある。 次に、プロセッサからクロック入力を受信する。 クロック入力のLowからHighへの遷移ごとに、 DI上のデータがマルチプレクサーアドレスシフトレジスタに入力される。 入力の最初のロジックhighはスタートビットである。スタートビットの後に、 3〜4ビットの割り当てワードが続く。クロック入力のLowからHighへの遷移ごとに、 スタートビットと割り当てワードがシフトレジスターにシフトする。 スタートビットがマルチプレクサレジスタの開始位置にシフトされると、 入力チャネルが選択され、変換が開始される。SAR Statu出力(SARS)は、 変換が進行中であることを示すために高レベルになり、 マルチプレクサーシフトレジスタへのDIは変換中は無効になる。

1クロック周期の間隔が自動的に挿入されて、 選択されたマルチプレックスチャネルの安定化を実現する。 データ出力DOは高インピーダンス状態から出て、 マルチプレクサの整定時間のこの1クロック期間に先行するLowを提供する。 SARコンパレータは、抵抗ラダーからの連続出力を入力アナログ信号と比較する。 コンパレータ出力は、アナログ入力が抵抗ラダー出力より大きいか小さいかを示す。 変換が進むと、変換データがDO出力ピンから同時に出力され、最上位ビット(MSB)が最初になる。

8クロック周期後、変換が完了し、SARS出力がLOWになる。 最後に、MSBファーストデータストリームの後に最下位ビットファーストデータを出力する。

_images/image175.png

ADC0834 MUXアドレス制御論理表

_images/image176.png

ポテンショメータ

ポテンショメーターも3つの端子を持つ抵抗部品であり、その抵抗値は定期的な変動に応じて調整できる。 ポテンショメータは通常、抵抗器と可動ブラシで構成されている。 ブラシが抵抗に沿って移動しているとき、変位に応じて特定の抵抗または電圧出力が生成される。

_images/image310.png

回路内のポテンショメータの機能は次のとおりである:

  1. 分圧器として機能する

ポテンショメータは連続的に調整可能な抵抗器である。 ポテンショメータのシャフトまたはスライドハンドルを調整すると、 可動接点が抵抗器上でスライドする。この時点で、ポテンショメータに印加される電圧と、 可動アームが回転した角度または移動距離に応じて、電圧を出力できる。

回路図
_images/image311.png _images/image312.png
実験手順

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

_images/image180.png

注釈

写真に示されている対応する位置を参照して、チップを配置してください。配置するときにチップの溝は左側にあることに注意してください。

C言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.1.4/

ステップ3: コードをコンパイルする。

gcc 2.1.4_Potentiometer.c -lwiringPi

ステップ4: 実行する。

sudo ./a.out

コードの実行後、ポテンショメーターのノブを回すと、それに応じてLEDの輝度が変化する。

コード

#include <wiringPi.h>
#include <stdio.h>
#include <softPwm.h>

typedef unsigned char uchar;
typedef unsigned int uint;

#define     ADC_CS    0
#define     ADC_CLK   1
#define     ADC_DIO   2
#define     LedPin    3

uchar get_ADC_Result(uint channel)
{
    uchar i;
    uchar dat1=0, dat2=0;
    int sel = channel > 1 & 1;
    int odd = channel & 1;

    pinMode(ADC_DIO, OUTPUT);
    digitalWrite(ADC_CS, 0);
    // Start bit
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
//Single End mode
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    // ODD
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Select
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);

    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);

    for(i=0;i<8;i++)
    {
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

        pinMode(ADC_DIO, INPUT);
        dat1=dat1<<1 | digitalRead(ADC_DIO);
    }

    for(i=0;i<8;i++)
    {
        dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
    }

    digitalWrite(ADC_CS,1);
    pinMode(ADC_DIO, OUTPUT);
    return(dat1==dat2) ? dat1 : 0;
}

int main(void)
{
    uchar analogVal;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    softPwmCreate(LedPin,  0, 100);
    pinMode(ADC_CS,  OUTPUT);
    pinMode(ADC_CLK, OUTPUT);

    while(1){
        analogVal = get_ADC_Result(0);
        printf("Current analogVal : %d\n", analogVal);
        delay(100);
        softPwmWrite(LedPin, analogVal);
        delay(100);
    }
    return 0;
}

コードの説明

#define     ADC_CS    0
#define     ADC_CLK   1
#define     ADC_DIO   2
#define     LedPin    3

ADC0834のCS、CLK、DIOを定義し、それぞれGPIO0、GPIO1、GPIO2に接続する。それから、GPIO3にLEDを取り付ける。

uchar get_ADC_Result(uint channel)
{
    uchar i;
    uchar dat1=0, dat2=0;
    int sel = channel > 1 & 1;
    int odd = channel & 1;

    pinMode(ADC_DIO, OUTPUT);
    digitalWrite(ADC_CS, 0);
    // Start bit
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
//Single End mode
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    // ODD
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Select
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);

    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    for(i=0;i<8;i++)
    {
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

        pinMode(ADC_DIO, INPUT);
        dat1=dat1<<1 | digitalRead(ADC_DIO);
    }

    for(i=0;i<8;i++)
    {
        dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
    }

    digitalWrite(ADC_CS,1);
    pinMode(ADC_DIO, OUTPUT);
    return(dat1==dat2) ? dat1 : 0;
}

ADC0834 には、アナログからデジタルへの変換を行う機能がある。特定の ワークフローは次のとおりです:

digitalWrite(ADC_CS, 0);

CSを低レベルに設定し、AD変換の有効化を開始する。

// Start bit
digitalWrite(ADC_CLK,0);
digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
digitalWrite(ADC_CLK,1);    delayMicroseconds(2);

クロック入力の lowからhighへの遷移が最初に発生したとき、 スタートビットとしてDIOを 1に設定する。次の三つのステップには 、割り当て単語が3つある 。

//Single End mode
digitalWrite(ADC_CLK,0);
igitalWrite(ADC_DIO,1);    delayMicroseconds(2);
gitalWrite(ADC_CLK,1);    delayMicroseconds(2);

クロック入力のlowからhighへの遷移が二回発生したらすぐに、DIOを1に設定し、SGLモードを選択する。

// ODD
digitalWrite(ADC_CLK,0);
digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
digitalWrite(ADC_CLK,1);    delayMicroseconds(2);

三回目に発生すると、DIOの値は変数 odd によって制御される。

//Select
digitalWrite(ADC_CLK,0);
digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
digitalWrite(ADC_CLK,1);

CLKのパルスが4番目に低レベルから高レベルに変換されると、DIOの値は変数 sel によって制御される。

channel = 0、sel = 0、odd = 0の条件下では、 sel および odd に関する演算式は次のとおりである:

int sel = channel > 1 & 1;
int odd = channel & 1;

channel = 1、sel = 0、odd = 1という条件が満たされている場合、 次のアドレス制御ロジックテーブルを参照してください。ここで、 CH1が選択され、開始ビットがマルチプレクサレジスタの開始位置にシフトされ、変換が開始される。

_images/image313.png
digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
digitalWrite(ADC_CLK,0);
digitalWrite(ADC_DIO,1);    delayMicroseconds(2);

ここでは、DIOを1に二回設定し、それを無視してください。

for(i=0;i<8;i++)
    {
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

        pinMode(ADC_DIO, INPUT);
        dat1=dat1<<1 | digitalRead(ADC_DIO);
    }

最初の for() statement で、CLKの五番目のパルスがHighレベルから低レベルに変換したらすぐに、 DIOを入力モードに設定してください。 それから、変換が開始され、変換された値が変数dat1に保存される。8クロック周期後、変換が完了する。

for(i=0;i<8;i++)
    {
        dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
    }

2番目最初の for()statement では、 他の最初の8つの後にDOを介して値を変換を出力し、変数dat2に保存する。

digitalWrite(ADC_CS,1);
pinMode(ADC_DIO, OUTPUT);
return(dat1==dat2) ? dat1 : 0;

return(dat1 == dat2)? dat1:0; は、変換中に得られた値と出力値を比較するために使用される。 それらが互いに等しい場合、変換値dat1を出力する。 それ以外の場合は、0を出力する。これで、ADC0834の処理が完了した。

softPwmCreate(LedPin,  0, 100);

この機能はソフトウェアを使用してPWMピンLedPinを作成し、 初期パルス幅を0に設定し、PWMの周期を100 x 100usにするために使用される。

while(1){
        analogVal = get_ADC_Result(0);
        printf("Current analogVal : %d\n", analogVal);
        softPwmWrite(LedPin, analogVal);
        delay(100);
    }

メイ プログラムで、 ポテンショメーターに最初接続されているチャンネル0 0 の値 を 読み取る 。 そして、最初値を最初変数analogValに保存してから LedPinに書き込む。 これで、ポテンショメータの値によってLEDの輝度が変化することを見ることができる。

Pythonユーザー向け

ステップ2: コードファイルを開く

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 2.1.4_Potentiometer.py

コードの実行後、ポテンショメーターのノブを回すと、それに応じてLEDの輝度が変化する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import ADC0834
import time

LedPin = 22

def setup():
    global led_val
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    # Set all LedPin's mode to output and initial level to High(3.3v)
    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)
    ADC0834.setup()
    # Set led as pwm channel and frequece to 2KHz
    led_val = GPIO.PWM(LedPin, 2000)
    # Set all begin with value 0
    led_val.start(0)

def destroy():
    # Stop all pwm channel
    led_val.stop()
    # Release resource
    GPIO.cleanup()
def loop():
    while True:
        analogVal = ADC0834.getResult()
        print ('analog value = %d' % analogVal)
        led_val.ChangeDutyCycle(analogVal*100/255)
        time.sleep(0.2)
if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()

コードの説明

import ADC0834

ADC0834ライブラリをインポートする。コマンド nano ADC0834.py を呼び出して、ライブラリの内容を確認できる。

def setup():
    global led_val
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    # Set all LedPin's mode to output and initial level to High(3.3v)
    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)
    ADC0834.setup()
    # Set led as pwm channel and frequece to 2KHz
    led_val = GPIO.PWM(LedPin, 2000)

    # Set all begin with value 0
    led_val.start(0)

setup() で、命名方法をBCMとして定義し、LedPinをPWMチャネルとして設定し、2Khzの周波数にレンダリングする。

ADC0834.setup(): ADC0834を初期化し、ADC0834の定義されたCS、CLK、DIOをそれぞれGPIO17、GPIO18、GPIO27に接続する。

def loop():
    while True:
        res = ADC0834.getResult()
        print ('res = %d' % res)
        R_val = MAP(res, 0, 255, 0, 100)
        led_val.ChangeDutyCycle(R_val)
        time.sleep(0.2)

関数 getResult() はADC0834の4つのチャンネルのアナログ値を読み取るために使用される。 デフォルトでは、関数はCH0の値を読み取り、 他のチャネルを読み取りたい場合は、() にチャネル番号を入力してください(例えば getResult(1) )。

関数 loop() は最初にCH0の値を読み取り、それから変数resに値を割り当てる。 その後、関数MAPを呼び出して、ポテンショメーターの読み取り値を0〜100にマッピングする。 このステップはLedPinのデューティサイクルを制御するために使用される。 これで、ポテンショメータの値によってLEDの輝度が変化していることがわかる。

現象画像
_images/image181.jpeg

2.1.5 キーパッド

前書き

キーパッドは、ボタンの長方形の配列である。このプロジェクトでは、入力文字を使用する。

部品
_images/list_2.1.5_keypad.png
原理

キーパッド

キーパッドは12個または16個のOFF-(ON)ボタンの長方形配列である。 リボンケーブルとの接続またはプリント基板への挿入に適したヘッダーを介してそれらの接点にアクセスする。 一部のキーパッドでは、 各ボタンはヘッダーの個別の連絡先に接続されるが、すべてのボタンは共通の接地を共有する。

_images/image314.png

多くの場合、ボタンはマトリックスエンコードされている。 つまり、各ボタンはマトリックス内の一意のコンダクターペアをブリッジしている。 この構成は、マイクロコントローラーによるポーリングに適し、 4本の水平線のそれぞれに順番に出力パルスを送信するようにプログラムできる。 各パルス中に、残りの4本の垂直ワイヤを順番にチェックして、信号を伝送しているのがどれかを判断する。 信号が存在しない場合にマイクロコントローラの入力が予期しない動作をすることを防ぐため、 入力ワイヤにプルアップまたはプルダウン抵抗を追加してください。

回路図
_images/image315.png _images/image316.png
実験手順

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

_images/image186.png
C言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.1.5/

ステップ3: コードをコンパイルする。

gcc 2.1.5_Keypad.cpp -lwiringPi

ステップ4: 実行する。

sudo ./a.out

コードの実行後、キーパッドで押されたボタンの値(ボタン値)が画面にプリントされる。

コード

#include <wiringPi.h>
#include <stdio.h>

#define ROWS  4
#define COLS  4
#define BUTTON_NUM (ROWS * COLS)

unsigned char KEYS[BUTTON_NUM] {
'1','2','3','A',
'4','5','6','B',
'7','8','9','C',
'*','0','#','D'};

unsigned char rowPins[ROWS] = {1, 4, 5, 6};
unsigned char colPins[COLS] = {12, 3, 2, 0};

void keyRead(unsigned char* result);
bool keyCompare(unsigned char* a, unsigned char* b);
void keyCopy(unsigned char* a, unsigned char* b);
void keyPrint(unsigned char* a);
void keyClear(unsigned char* a);
int keyIndexOf(const char value);

void init(void) {
    for(int i=0 ; i<4 ; i++) {
        pinMode(rowPins[i], OUTPUT);
        pinMode(colPins[i], INPUT);
    }
}

int main(void){
    unsigned char pressed_keys[BUTTON_NUM];
    unsigned char last_key_pressed[BUTTON_NUM];

    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    init();
    while(1){
        keyRead(pressed_keys);
        bool comp = keyCompare(pressed_keys, last_key_pressed);
        if (!comp){
            keyPrint(pressed_keys);
            keyCopy(last_key_pressed, pressed_keys);
        }
        delay(100);
    }
    return 0;
}

void keyRead(unsigned char* result){
    int index;
    int count = 0;
    keyClear(result);
    for(int i=0 ; i<ROWS ; i++ ){
        digitalWrite(rowPins[i], HIGH);
        for(int j =0 ; j < COLS ; j++){
            index = i * ROWS + j;
            if(digitalRead(colPins[j]) == 1){
                result[count]=KEYS[index];
                count += 1;
            }
        }
        delay(1);
        digitalWrite(rowPins[i], LOW);
    }
}

bool keyCompare(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        if (a[i] != b[i]){
            return false;
        }
    }
    return true;
}

void keyCopy(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        a[i] = b[i];
    }
}

void keyPrint(unsigned char* a){
    if (a[0] != 0){
        printf("%c",a[0]);
    }
    for (int i=1; i<BUTTON_NUM; i++){
        if (a[i] != 0){
            printf(", %c",a[i]);
        }
    }
    printf("\n");
}

void keyClear(unsigned char* a){
    for (int i=0; i<BUTTON_NUM; i++){
        a[i] = 0;
    }
}

int keyIndexOf(const char value){
    for (int i=0; i<BUTTON_NUM; i++){
        if ((const char)KEYS[i] == value){
            return i;
        }
    }
    return -1;
}

コードの説明

unsigned char KEYS[BUTTON_NUM] {
'1','2','3','A',
'4','5','6','B',
'7','8','9','C',
'*','0','#','D'};

unsigned char rowPins[ROWS] = {1, 4, 5, 6};
unsigned char colPins[COLS] = {12, 3, 2, 0};

マトリックスキーボードの各キーを配列 keys[] に表示し、各行と列にピンを定義する。

while(1){
        keyRead(pressed_keys);
        bool comp = keyCompare(pressed_keys, last_key_pressed);
        if (!comp){
            keyPrint(pressed_keys);
            keyCopy(last_key_pressed, pressed_keys);
        }
        delay(100);
    }

これは、ボタン値を読み取り、プリントするメイン関数の一部である。

関数 keyRead() は、すべてのボタンの状態を読み取る。

KeyCompare()keyCopy() は、ボタンの状態が変化したかどうか(つまり、ボタンが押されたか離されたか)を判断するために使用される。

keyPrint() は現在のレベルが高レベル(ボタンが押されている)のボタンのボタン値をプリントする。

void keyRead(unsigned char* result){
    int index;
    int count = 0;
    keyClear(result);
    for(int i=0 ; i<ROWS ; i++ ){
        digitalWrite(rowPins[i], HIGH);
        for(int j =0 ; j < COLS ; j++){
            index = i * ROWS + j;
            if(digitalRead(colPins[j]) == 1){
                result[count]=KEYS[index];
                count += 1;
            }
        }
        delay(1);
        digitalWrite(rowPins[i], LOW);
    }
}

この関数は各行に順番に高レベルを割り当て、列のキーが押されると、 キーが配置されている列が高レベルになる。two- layer loopの判定後、 キー状態のコンパイルにより配列( reasult[] )が生成される。

ボタン3を押すとき:

_images/image187.png

RowPin[0] は高レベルで書き込み、 colPin[2] は高レベルになる。 ColPin[0]colPin[1]colPin[3] は低レベルになる。

これにより、 0,0,1,0 が得られる。 rowPin[1]rowPin[2]rowPin[3] が高レベルで書き込まれると、 colPin[0]colPin[4] は低レベルになる。

ループ判定が完了すると、配列が生成される:

result[BUTTON_NUM] {
0, 0, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0};
bool keyCompare(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        if (a[i] != b[i]){
            return false;
        }
    }
    return true;
}

void keyCopy(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        a[i] = b[i];
    }
}

これら二つの関数は、キーの状態が変化したかどうかを判断するために使用され、たとえば、 「3」または「2」を押したときに手を離すと、 keyCompare() はfalseを返す。

KeyCopy() ``はそれぞれの比較後に配列( ``last_key_pressed[BUTTON_NUM] ) の現在のボタン値を書き換えるために使用される。ですから次回にそれらを比較できる。

void keyPrint(unsigned char* a){
//printf("{");
    if (a[0] != 0){
        printf("%c",a[0]);
    }
    for (int i=1; i<BUTTON_NUM; i++){
        if (a[i] != 0){
            printf(", %c",a[i]);
        }
    }
    printf("\n");
}

この関数は現在押されているボタンの値をプリントするために使用される。 「1」ボタンを押すと、「1」がプリントされる。 ボタン「1」と「3」が押されると、「1、3」がプリントされる。

Python言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 2.1.5_Keypad.py

コードの実行後、キーパッドで押されたボタンの値(ボタン値)が画面にプリントされる。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

class Keypad():

    def __init__(self, rowsPins, colsPins, keys):
        self.rowsPins = rowsPins
        self.colsPins = colsPins
        self.keys = keys
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

    def read(self):
        pressed_keys = []
        for i, row in enumerate(self.rowsPins):
            GPIO.output(row, GPIO.HIGH)
            for j, col in enumerate(self.colsPins):
                index = i * len(self.colsPins) + j
                if (GPIO.input(col) == 1):
                    pressed_keys.append(self.keys[index])
            GPIO.output(row, GPIO.LOW)
        return pressed_keys

def setup():
    global keypad, last_key_pressed
    rowsPins = [18,23,24,25]
    colsPins = [10,22,27,17]
    keys = ["1","2","3","A",
            "4","5","6","B",
            "7","8","9","C",
            "*","0","#","D"]
    keypad = Keypad(rowsPins, colsPins, keys)
    last_key_pressed = []

def loop():
    global keypad, last_key_pressed
    pressed_keys = keypad.read()
    if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
        print(pressed_keys)
    last_key_pressed = pressed_keys
    time.sleep(0.1)

# Define a destroy function for clean up everything after the script finished
def destroy():
    # Release resource
    GPIO.cleanup()

if __name__ == '__main__':     # Program start from here
    try:
        setup()
        while True:
            loop()
    except KeyboardInterrupt:   # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()

コードの説明

def setup():
    global keypad, last_key_pressed
    rowsPins = [18,23,24,25]
    colsPins = [10,22,27,17]
    keys = ["1","2","3","A",
            "4","5","6","B",
            "7","8","9","C",
            "*","0","#","D"]
    keypad = Keypad(rowsPins, colsPins, keys)
    last_key_pressed = []

マトリックスキーボードの各キーを配列 keys[] に表示し、各行と列にピンを定義する。

def loop():
    global keypad, last_key_pressed
    pressed_keys = keypad.read()
    if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
        print(pressed_keys)
    last_key_pressed = pressed_keys
    time.sleep(0.1)

これは、ボタン値を読み取り、プリントするメイン関数の一部である。

関数 keyRead() は、すべてのボタンの状態を読み取る。

if len(pressed_keys)!= 0last_key_pressed != Pressed_keys のステートメントは、

キーが押されたかどうか、押されたボタンの状態を判断するために使用される。(「1」を押したときに「3」を押した場合、判断は受け入れられる。)

条件が主張できる場合、現在押されているキーの値をプリントする。

ステートメント last_key_pressed = pressed_keys は、それぞれの判断の状態を配列 last_key_pressed に割り当て、次の条件判断を容易にする。

def read(self):
        pressed_keys = []
        for i, row in enumerate(self.rowsPins):
            GPIO.output(row, GPIO.HIGH)
            for j, col in enumerate(self.colsPins):
                index = i * len(self.colsPins) + j
                if (GPIO.input(col) == 1):
                    pressed_keys.append(self.keys[index])
            GPIO.output(row, GPIO.LOW)
        return pressed_keys

この関数は各行に順番に高レベルを割り当て、列のボタンが押されると、 キーが配置されている列が高レベルになる。 2層ループが判定された後、状態が1のボタンの値は、 pressed_keys 配列に保存される。

キー「3」を押すと:

_images/image187.png

rowPins[0] は高レベルで書き込まれ、 colPins[2] は高レベルになり。

colPins[0]colPins[1]colPins[3] は低レベルになる。

4つの状態がある: 0、0、1、0 。そして、 pressed_keys に「3」を書き込む。

rowPins[1]rowPins[2]rowPins[3] が高レベルに書き込まれると、 colPins[0]colPins[4] は低レベルになる。

ループが停止し、 pressed_keys = '3' が返される。

ボタン「1」と「3」を押すと、 pressed_keys =['1'、'3'] が返される。

現象画像
_images/image188.jpeg

2.1.6 ジョイスティック

前書き

このプロジェクトでは、ジョイスティックの仕組みを学習する。 ジョイスティックを操作して、結果を画面に表示する。

部品
_images/image317.png
原理

ジョイスティック

ジョイスティックの基本的な原理は、スティックの動きをコンピューターが処理できる電子情報に変換することである。

モーションの全範囲をコンピューターに通信するために、ジョイスティックはX軸(左から右)とY軸(上下)の二つの軸でスティックの位置を測定する必要がある。基本的なジオメトリと同様に、X-Y座標はスティックの位置を正確に特定する。

スティックの位置を決定するために、ジョイスティック制御システムは各シャフトの位置を監視する。従来のアナログジョイスティックの設計では、これを二つのポテンショメーターまたは可変抵抗器で行う。

ジョイスティックには、ジョイスティックを押し下げたときに作動するデジタル入力もある。

_images/image318.png
回路図

ジョイスティックのデータを読み取ると、 軸間でいくつかの違いがある:X軸とY軸のデータはアナログであり、 ADC0834を使用してアナログ値をデジタル値に変換する必要がある。 Z軸のデータはデジタルであるため、GPIOを直接使用して読み取るか、 またはADCを使用して読み取ることができる。

_images/image319.png _images/image320.png
実験手順

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

_images/image193.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.1.6/

ステップ3: コードをコンパイルする。

gcc 2.1.6_Joystick.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行後、ジョイスティックを回すと、対応するx、y、Btnの値が画面に表示される。

コード

#include <wiringPi.h>
#include <stdio.h>
#include <softPwm.h>

typedef unsigned char uchar;
typedef unsigned int uint;

#define     ADC_CS    0
#define     ADC_CLK   1
#define     ADC_DIO   2
#define     BtnPin    3

uchar get_ADC_Result(uint channel)
{
    uchar i;
    uchar dat1=0, dat2=0;
    int sel = channel > 1 & 1;
int odd = channel & 1;
    pinMode(ADC_DIO, OUTPUT);
    digitalWrite(ADC_CS, 0);
    // Start bit
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
//Single End mode
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    // ODD
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Select
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
digitalWrite(ADC_CLK,1);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    for(i=0;i<8;i++)
    {
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
        pinMode(ADC_DIO, INPUT);
        dat1=dat1<<1 | digitalRead(ADC_DIO);
    }
    for(i=0;i<8;i++)
    {
        dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
    }
    digitalWrite(ADC_CS,1);
    pinMode(ADC_DIO, OUTPUT);
    return(dat1==dat2) ? dat1 : 0;
}
int main(void)
{
    uchar x_val;
    uchar y_val;
    uchar btn_val;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    pinMode(BtnPin,  INPUT);
    pullUpDnControl(BtnPin, PUD_UP);
    pinMode(ADC_CS,  OUTPUT);
    pinMode(ADC_CLK, OUTPUT);

    while(1){
        x_val = get_ADC_Result(0);
        y_val = get_ADC_Result(1);
        btn_val = digitalRead(BtnPin);
        printf("x = %d, y = %d, btn = %d\n", x_val, y_val, btn_val);
        delay(100);
    }
    return 0;
}

コードの説明

uchar get_ADC_Result(uint channel)
{
    uchar i;
    uchar dat1=0, dat2=0;
    int sel = channel > 1 & 1;
    int odd = channel & 1;
    pinMode(ADC_DIO, OUTPUT);
    digitalWrite(ADC_CS, 0);
    // Start bit
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Single End mode
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    ......

機能の動作プロセスについては、2.1.4ポテンショメーターで詳しく説明している。

while(1){
        x_val = get_ADC_Result(0);
        y_val = get_ADC_Result(1);
        btn_val = digitalRead(BtnPin);
        printf("x = %d, y = %d, btn = %d\n", x_val, y_val, btn_val);
        delay(100);
    }

ジョイスティックのVRXとVRYは、それぞれADC0834のCH0、CH1に接続されている。 したがって、関数 getResult() が呼び出されて、CH0とCH1の値が読み取られる。 それから、読み取った値を変数 x_valy_val に保存してください。 さらに、ジョイスティックのSWの値を読み取り、変数 Btn_val に保存する。 最後に、 x_valy_val 、と Btn_val の値は print() 関数で出力される。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 2.1.6_Joystick.py

コードの実行後、ジョイスティックを回すと、対応するx、y、Btnの値が画面に表示される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import ADC0834
import time

BtnPin = 22

def setup():
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    ADC0834.setup()

def destroy():
    # Release resource
    GPIO.cleanup()

def loop():
    while True:
        x_val = ADC0834.getResult(0)
        y_val = ADC0834.getResult(1)
        Btn_val = GPIO.input(BtnPin)
        print ('X: %d  Y: %d  Btn: %d' % (x_val, y_val, Btn_val))
        time.sleep(0.2)

if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()

コードの説明

def loop():
    while True:
        x_val = ADC0834.getResult(0)
        y_val = ADC0834.getResult(1)
        Btn_val = GPIO.input(BtnPin)
        print ('X: %d  Y: %d  Btn: %d' % (x_val, y_val, Btn_val))
        time.sleep(0.2)

ジョイスティックのVRXとVRYは、それぞれADC0834のCH0、CH1に接続されている。 したがって、関数 getResult() が呼び出されて、CH0とCH1の値が読み取られる。 それから、読み取った値を変数 x_valy_val に保存してください。 さらに、ジョイスティックのSWの値を読み取り、変数 Btn_val に保存する。 最後に、 x_valy_val 、と Btn_val の値は print() 関数で出力される。

現象画像
_images/image194.jpeg

2.2 センサー

2.2.1 フォトレジスタ

前書き

フォトレジスタは生活の中で環境光の強度によく使用される部品である。 コントローラーが昼と夜を認識し、夜間ランプなどの調光機能を実現することに役立つ。 このプロジェクトはポテンショメータによく似ており、光を感知するための電圧を変えると思うかもしれない。

部品
_images/list_2.2.1_photoresistor.png
原理

フォトレジスタまたはフォトセルは光制御可変抵抗器である。 フォトレジストの抵抗は入射光強度の増加とともに減少する。つまり、光伝導性を示す。 フォトレジスタは、光に敏感な検出回路、および光・暗闇で作動する切換回路に適用できる。

_images/image196.png
回路図
_images/image321.png _images/image322.png
実験手順

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

_images/image198.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.2.1/

ステップ3: コードをコンパイルする。

gcc 2.2.1_Photoresistor.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードを実行すると、LEDの輝度はフォトレジスターが感知する光の強度に応じて変化する。

コード

#include <wiringPi.h>
#include <stdio.h>
#include <softPwm.h>

typedef unsigned char uchar;
typedef unsigned int uint;

#define     ADC_CS    0
#define     ADC_CLK   1
#define     ADC_DIO   2
#define     LedPin    3

uchar get_ADC_Result(uint channel)
{
    uchar i;
    uchar dat1=0, dat2=0;
    int sel = channel > 1 & 1;
    int odd = channel & 1;

    pinMode(ADC_DIO, OUTPUT);
    digitalWrite(ADC_CS, 0);
    // Start bit
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Single End mode
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    // ODD
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Select
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);

    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);

    for(i=0;i<8;i++)
    {
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

        pinMode(ADC_DIO, INPUT);
        dat1=dat1<<1 | digitalRead(ADC_DIO);
    }

    for(i=0;i<8;i++)
    {
        dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
    }

    digitalWrite(ADC_CS,1);
    pinMode(ADC_DIO, OUTPUT);
    return(dat1==dat2) ? dat1 : 0;
}

int main(void)
{
    uchar analogVal;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    softPwmCreate(LedPin,  0, 100);
    pinMode(ADC_CS,  OUTPUT);
    pinMode(ADC_CLK, OUTPUT);

    while(1){
        analogVal = get_ADC_Result(0);
        printf("Current analogVal : %d\n", analogVal);
        delay(100);
        softPwmWrite(LedPin, analogVal);
        delay(100);
    }
    return 0;
}

コードの説明

ここのコードは、2.1.4ポテンショメーターのコードと同じである。他に質問がある場合は、 2.1.4Potentiometer.c のコード説明を参照してください。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 2.2.1_Photoresistor.py

コードを実行すると、LEDの輝度はフォトレジスターが感知する光の強度に応じて変化する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import ADC0834
import time

LedPin = 22

def setup():
    global led_val
    # Set the GPIO modes to BCM Numbering
    GPIO.setmode(GPIO.BCM)
    # Set all LedPin's mode to output and initial level to High(3.3v)
    GPIO.setup(LedPin, GPIO.OUT, initial=GPIO.HIGH)
    ADC0834.setup()
    # Set led as pwm channel and frequece to 2KHz
    led_val = GPIO.PWM(LedPin, 2000)

    # Set all begin with value 0
    led_val.start(0)

def destroy():
    # Stop all pwm channel
    led_val.stop()
    # Release resource
    GPIO.cleanup()

def loop():
    while True:
        analogVal = ADC0834.getResult()
        print ('analog value = %d' % analogVal)
        led_val.ChangeDutyCycle(analogVal*100/255)
        time.sleep(0.2)

if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()

コードの説明

def loop():
    while True:
        analogVal = ADC0834.getResult()
        print ('analog value = %d' % analogVal)
        led_val.ChangeDutyCycle(analogVal*100/255)
        time.sleep(0.2)

ADC0834のCH0のアナログ値を読み取る。 デフォルトでは、関数 getResult() を使用してCH0の値を読み取る。 したがって、他のチャネルを読み取る場合は、 関数 getResult() の()に1、2、または3を入力してください。 次に、プリント機能を使用して値をプリントする必要がある。 変化する要素は計算式である LedPin のデューティサイクルであるため、 analogVal をパーセンテージに変換するには analogVal * 100/255 が必要である。 最後に、 ChangeDutyCycle() が呼び出されて、パーセンテージが LedPin に書き込まれる。

現象画像
_images/image199.jpeg

2.2.2 サーミスタ

前書き

フォトレジスターが光を感知できるように、サーミスターは温度に敏感な電子デバイスであり、 過熱警報装置の作成など、温度制御の機能を実現するために使用できる。

部品
_images/list_2.2.2_thermistor.png
原理

サーミスタは、温度のわずかな変化に比例して抵抗の予測可能な変化を正確に示す熱に敏感な抵抗器である。その抵抗がどの程度変化するかは、その独自の構成に依存する。サーミスタは、受動部品の大きなグループの一部である。また、対応するアクティブコンポーネントとは異なり、パッシブデバイスは回路に電力上昇または増幅を提供できない。

サーミスタは敏感な要素であり、負の温度係数(NTC)と正の温度係数(PTC)の2つのタイプがあり、NTCとPTCとも呼ばれる。その抵抗は温度によって大きく異なる。PTCサーミスタの抵抗は温度とともに増加するが、NTCの条件は前者とは逆である この実験では、NTCを使用する。

_images/image325.png

その動作原理は、NTCサーミスタの抵抗が外部環境の温度とともに変化することである。環境のリアルタイム温度を検出できる。温度が高くなると、サーミスタの抵抗が減少する。次に、電圧データはA/Dアダプターによってデジタル量に変換される。摂氏または華氏の温度はプログラミングにより出力される。

この実験では、サーミスタと10kプルアップ抵抗が使用される。各サーミスタには通常の抵抗がある。ここでは、25℃で測定されると、10k ohmである。

抵抗と温度の関係は次の通りである:

RT =RN expB(1/TK – 1/TN)

RT は温度が TK のときのNTCサーミスタの抵抗である。

RN は、定格温度 TN でのNTCサーミスタの抵抗である。ここで、 RN の数値は10kである。

TK はケルビン温度で、単位はKである。ここで、 TK の数値は273.15である。+摂氏度である。

TN は定格ケルビン温度で、単位もKである。ここで、 TN の数値は273.15 + 25である。

また、NTCサーミスタの構成要素定数である B(ベータ)は、数値3950の熱感受性指数とも呼ばれる。

exp は指数の略語で、基数eは自然数であり、約2.7に等しくなる。

この式 TK=1/(ln(RT/RN)/B+1/TN) を変換して、マイナス273.15が摂氏温度に相当するケルビン温度を取得する。

この関係は実験式である。温度と抵抗が有効範囲内にある場合にのみそれは正確である。

回路図
_images/image323.png _images/image324.png
実験手順

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

_images/image202.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.2.2/

ステップ3: コードをコンパイルする。

gcc 2.2.2_Thermistor.c -lwiringPi -lm

注釈

-lm はライブラリの数学をロードする。省略すると、エラーが発生する。

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードを実行すると、サーミスタは周囲温度を検出する。周囲温度は、プログラムの計算が終了すると画面に出力される。

コード

#include <wiringPi.h>
#include <stdio.h>
#include <math.h>

typedef unsigned char uchar;
typedef unsigned int uint;

#define     ADC_CS    0
#define     ADC_CLK   1
#define     ADC_DIO   2

uchar get_ADC_Result(uint channel)
{
    uchar i;
    uchar dat1=0, dat2=0;
    int sel = channel > 1 & 1;
    int odd = channel & 1;

    pinMode(ADC_DIO, OUTPUT);
    digitalWrite(ADC_CS, 0);
    // Start bit
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Single End mode
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    // ODD
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,odd);  delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
    //Select
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,sel);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,1);

    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);
    digitalWrite(ADC_CLK,0);
    digitalWrite(ADC_DIO,1);    delayMicroseconds(2);

    for(i=0;i<8;i++)
    {
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);

        pinMode(ADC_DIO, INPUT);
        dat1=dat1<<1 | digitalRead(ADC_DIO);
    }

    for(i=0;i<8;i++)
    {
        dat2 = dat2 | ((uchar)(digitalRead(ADC_DIO))<<i);
        digitalWrite(ADC_CLK,1);    delayMicroseconds(2);
        digitalWrite(ADC_CLK,0);    delayMicroseconds(2);
    }

    digitalWrite(ADC_CS,1);
    pinMode(ADC_DIO, OUTPUT);
    return(dat1==dat2) ? dat1 : 0;
}

int main(void)
{
    unsigned char analogVal;
double Vr, Rt, temp, cel, Fah;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    pinMode(ADC_CS,  OUTPUT);
    pinMode(ADC_CLK, OUTPUT);

    while(1){
        analogVal = get_ADC_Result(0);
        Vr = 5 * (double)(analogVal) / 255;
        Rt = 10000 * (double)(Vr) / (5 - (double)(Vr));
        temp = 1 / (((log(Rt/10000)) / 3950)+(1 / (273.15 + 25)));
        cel = temp - 273.15;
        Fah = cel * 1.8 +32;
        printf("Celsius: %.2f C  Fahrenheit: %.2f F\n", cel, Fah);
        delay(100);
    }
    return 0;
}

コードの説明

#include <math.h>

一般的な数学的操作と変換を計算する一連の関数を宣言するC数値ライブラリがある。

analogVal = get_ADC_Result(0);

この関数はサーミスタの値を読み取るために使用される。

Vr = 5 * (double)(analogVal) / 255;
Rt = 10000 * (double)(Vr) / (5 - (double)(Vr));
temp = 1 / (((log(Rt/10000)) / 3950)+(1 / (273.15 + 25)));
cel = temp - 273.15;
Fah = cel * 1.8 +32;
printf("Celsius: %.2f C  Fahrenheit: %.2f F\n", cel, Fah);

これらの計算により、サーミスタ値が摂氏値に変換される。

Vr = 5 * (double)(analogVal) / 255;
Rt = 10000 * (double)(Vr) / (5 - (double)(Vr));

Rt(サーミスタの抵抗)を取得するために、これらの2行のコードは読み取り値アナログを使って電圧分布を計算している。

temp = 1 / (((log(Rt/10000)) / 3950)+(1 / (273.15 + 25)));

このコードは、Rtを式 TK=1/(ln(RT/RN)/B+1/TN) に挿入してケルビン温度を取得することを意味する。

temp = temp - 273.15;

ケルビン温度を摂氏に変換する。

Fah = cel * 1.8 +32;

摂氏を華氏に変換する。

printf("Celsius: %.2f C  Fahrenheit: %.2f F\n", cel, Fah);

ディスプレイに摂氏度、華氏度とそれらの単位を表示する。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 2.2.2_Thermistor.py

コードを実行すると、サーミスタは周囲温度を検出する。周囲温度は、プログラムの計算が終了すると画面に出力される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import ADC0834
import time
import math

def init():
    ADC0834.setup()

def loop():
    while True:
        analogVal = ADC0834.getResult()
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
        Cel = temp - 273.15
        Fah = Cel * 1.8 + 32
        print ('Celsius: %.2f C  Fahrenheit: %.2f F' % (Cel, Fah))
        time.sleep(0.2)

if __name__ == '__main__':
    init()
    try:
        loop()
    except KeyboardInterrupt:
        ADC0834.destroy()

コードの説明

import math

一般的な数学的操作と変換を計算する一連の関数を宣言するC数値ライブラリがある。

analogVal = ADC0834.getResult()

この関数はサーミスタの値を読み取るために使用される。

Vr = 5 * float(analogVal) / 255
Rt = 10000 * Vr / (5 - Vr)
temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
Cel = temp - 273.15
Fah = Cel * 1.8 + 32
print ('Celsius: %.2f °C  Fahrenheit: %.2f ℉' % (Cel, Fah))

これらの計算はサーミスタの値を摂氏度と華氏度に変換する。

Vr = 5 * float(analogVal) / 255
Rt = 10000 * Vr / (5 - Vr)

Rt(サーミスタの抵抗)を取得するために、これらの2行のコードは読み取り値アナログを使って電圧分布を計算している。

temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))

このコードは、Rtを式 TK=1/(ln(RT/RN)/B+1/TN) に挿入してケルビン温度を取得することを意味する。

temp = temp - 273.15

ケルビン温度を摂氏に変換する。

Fah = Cel * 1.8 + 32

摂氏を華氏に変換する。

print ('Celsius: %.2f °C  Fahrenheit: %.2f ℉' % (Cel, Fah))

ディスプレイに摂氏度、華氏度とそれらの単位を表示する。

現象画像
_images/image203.jpeg

2.2.3 DHT-11

前書き

デジタル温湿度センサーDHT11は、温度と湿度の校正済みデジタル信号出力を含む複合センサーである。専用のデジタルモジュールコレクションの技術と温湿度検知の技術を適用して、製品の高い信頼性と優れた安定性を確保している。

センサーには、湿式素子抵抗センサーとNTC温度センサーが含まれており、高性能の8ビットマイクロコントローラーに接続されている。

部品
_images/list_2.2.3_dht-11.png
原理

DHT11は基本的な超低コストのデジタル温湿度センサーである。 容量性湿度センサーとサーミスタを使用して周囲の空気を測定し、 データピンにデジタル信号を出力する(アナログ入力ピンは不要)。

_images/image205.png

VCC、GND、とDATAの三つのピンのみが利用できる。 通信プロセスは開始信号をDHT11に送信するDATAラインから始まり、 DHT11は信号を受信して応答信号を返す。次に、ホストは応答信号を受信し、 40ビットの湿度データ(8ビット湿度整数+ 8ビット湿度10進数+ 8ビット温度整数+ 8ビット温度10進数+ 8ビットチェックサム)の受信を開始する。 詳細については、DHT11データシートを参照してください。

回路図
_images/image326.png
実験手順

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

_images/image207.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.2.3/

ステップ3: コードをコンパイルする。

gcc 2.2.3_DHT.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行後、プログラムはDHT11によって検出された温度と湿度をコンピューター画面にプリントする。

コード

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define maxTim 85
#define dhtPin 0

int dht11_dat[5] = {0,0,0,0,0};

void readDht11() {
    uint8_t laststate = HIGH;
    uint8_t counter = 0;
    uint8_t j = 0, i;
    float Fah; // fahrenheit
    dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
    // pull pin down for 18 milliseconds
    pinMode(dhtPin, OUTPUT);
    digitalWrite(dhtPin, LOW);
    delay(18);
    // then pull it up for 40 microseconds
    digitalWrite(dhtPin, HIGH);
    delayMicroseconds(40);
    // prepare to read the pin
    pinMode(dhtPin, INPUT);

    // detect change and read data
    for ( i=0; i< maxTim; i++) {
        counter = 0;
        while (digitalRead(dhtPin) == laststate) {
            counter++;
            delayMicroseconds(1);
            if (counter == 255) {
                break;
            }
        }
        laststate = digitalRead(dhtPin);

        if (counter == 255) break;
        // ignore first 3 transitions
        if ((i >= 4) && (i%2 == 0)) {
            // shove each bit into the storage bytes
            dht11_dat[j/8] <<= 1;
            if (counter > 50)
                dht11_dat[j/8] |= 1;
            j++;
        }
    }
    // check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
    // print it out if data is good
    if ((j >= 40) &&
            (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF)) ) {
        Fah = dht11_dat[2] * 9. / 5. + 32;
        printf("Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n",
                dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], Fah);
    }
}

int main (void) {
    if(wiringPiSetup() == -1){ //when initialize wiring failed, print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    while (1) {
        readDht11();
        delay(500); // wait 1sec to refresh
    }
    return 0 ;
}

コードの説明

void readDht11() {
    uint8_t laststate = HIGH;
    uint8_t counter = 0;
    uint8_t j = 0, i;
    float Fah; // fahrenheit
    dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
    // ...
}

この機能はDHT11の機能を実現するために使用される。

通常、次の3つの部分に分けることができる:

  1. ピンを読む準備ができた:

// pull pin down for 18 milliseconds
pinMode(dhtPin, OUTPUT);
digitalWrite(dhtPin, LOW);
delay(18);
// then pull it up for 40 microseconds
digitalWrite(dhtPin, HIGH);
delayMicroseconds(40);
// prepare to read the pin
pinMode(dhtPin, INPUT);

その通信フローは、作業のタイミングによって決まる。

_images/image208.png

DHT11が起動すると、MCUは低レベルの信号を送信し、40usの間信号を高レベルに保つ。 その後、外部環境の状態の検出が開始される。

  1. データの読み取り:

// detect change and read data
for ( i=0; i< maxTim; i++) {
        counter = 0;
        while (digitalRead(dhtPin) == laststate) {
            counter++;
            delayMicroseconds(1);
            if (counter == 255) {
                break;
            }
        }
        laststate = digitalRead(dhtPin);
        if (counter == 255) break;
        // ignore first 3 transitions
        if ((i >= 4) && (i%2 == 0)) {
            // shove each bit into the storage bytes
            dht11_dat[j/8] <<= 1;
            if (counter > 50)
                dht11_dat[j/8] |= 1;
            j++;
        }
    }

ループは検出されたデータを dht11_dat[] 配列に保存する。DHT11は一度に40ビットのデータを転送する。最初の16ビットは湿度に関連し、中央の16ビットは温度に関連し、最後の8ビットは検証に使用される。データ形式は次のとおりである:

8ビット湿度整数データ + 8ビット湿度10進データ + 8ビット温度整数データ + 8ビット温度10進データ + 8ビットチェックビット。

  1. 湿度と温度をプリントする。

// check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
// print it out if data is good
if ((j >= 40) &&
        (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF)) ) {
    Fah = dht11_dat[2] * 9. / 5. + 32;
    printf("Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n",
            dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], Fah);
}

データストレージが最大40ビットの場合、 チェックビット ( dht11_dat[4] ) を通じてデータの有効性をチェックし、温度と湿度をプリントする。

たとえば、受信データが00101011(湿度整数の8ビット値)00000000(湿度10進数の8ビット値)00111100(温度整数の8ビット値)00000000(温度10進数の8ビット値)01100111(チェックビット)の場合、

計算:

00101011+00000000+00111100+00000000=01100111.

最終結果はチェックビットデータに等しく、受信データは正しいである:

湿度= 43%、温度= 60 ℃。

チェックビットデータと等しくない場合、データ送信は正常ではなく、データが再度受信される。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 2.2.3_DHT.py

コードの実行後、プログラムはDHT11によって検出された温度と湿度をコンピューター画面にプリントする。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

dhtPin = 17

GPIO.setmode(GPIO.BCM)

MAX_UNCHANGE_COUNT = 100

STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5

def readDht11():
    GPIO.setup(dhtPin, GPIO.OUT)
    GPIO.output(dhtPin, GPIO.HIGH)
    time.sleep(0.05)
    GPIO.output(dhtPin, GPIO.LOW)
    time.sleep(0.02)
    GPIO.setup(dhtPin, GPIO.IN, GPIO.PUD_UP)

    unchanged_count = 0
    last = -1
    data = []
    while True:
        current = GPIO.input(dhtPin)
        data.append(current)
        if last != current:
            unchanged_count = 0
            last = current
        else:
            unchanged_count += 1
            if unchanged_count > MAX_UNCHANGE_COUNT:
                break

    state = STATE_INIT_PULL_DOWN

    lengths = []
    current_length = 0

    for current in data:
        current_length += 1

        if state == STATE_INIT_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_INIT_PULL_UP
            else:
                continue
        if state == STATE_INIT_PULL_UP:
            if current == GPIO.HIGH:
                state = STATE_DATA_FIRST_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_FIRST_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_DATA_PULL_UP
            else:
                continue
        if state == STATE_DATA_PULL_UP:
            if current == GPIO.HIGH:
                current_length = 0
                state = STATE_DATA_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_PULL_DOWN:
            if current == GPIO.LOW:
                lengths.append(current_length)
                state = STATE_DATA_PULL_UP
            else:
                continue
    if len(lengths) != 40:
        #print ("Data not good, skip")
        return False

    shortest_pull_up = min(lengths)
    longest_pull_up = max(lengths)
    halfway = (longest_pull_up + shortest_pull_up) / 2
    bits = []
    the_bytes = []
    byte = 0

    for length in lengths:
        bit = 0
        if length > halfway:
            bit = 1
        bits.append(bit)
    #print ("bits: %s, length: %d" % (bits, len(bits)))
    for i in range(0, len(bits)):
        byte = byte << 1
        if (bits[i]):
            byte = byte | 1
        else:
            byte = byte | 0
        if ((i + 1) % 8 == 0):
            the_bytes.append(byte)
            byte = 0
    #print (the_bytes)
    checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
    if the_bytes[4] != checksum:
        #print ("Data not good, skip")
        return False

    return the_bytes[0], the_bytes[2]

def main():

    while True:
        result = readDht11()
        if result:
            humidity, temperature = result
            print ("humidity: %s %%,  Temperature: %s C`" % (humidity, temperature))
        time.sleep(1)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの説明

def readDht11():
    GPIO.setup(dhtPin, GPIO.OUT)
    GPIO.output(dhtPin, GPIO.HIGH)
    time.sleep(0.05)
    GPIO.output(dhtPin, GPIO.LOW)
    time.sleep(0.02)
    GPIO.setup(dhtPin, GPIO.IN, GPIO.PUD_UP)
    unchanged_count = 0
    last = -1
    data = []
    #...

この関数はDHT11の関数を実装するために使用される。それは検出されたデータを the_bytes[] 配列に保存する。 DHT11は一度に40ビットのデータを点灯する。 最初の16ビットは湿度に関連し、中央の16ビットは温度に関連し、最後の8ビットは検証に使用される。 データ形式は次のとおりである:

8ビット湿度整数データ +8ビット湿度10進データ +8ビット温度整数データ + 8ビット温度10進データ + 8ビットチェックビット。

チェックビットを介して有効性が検出されると、関数は2つの結果を返す:1. エラー; 2.湿度と温度。

checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
if the_bytes[4] != checksum:
    #print ("Data not good, skip")
    return False

return the_bytes[0], the_bytes[2]

たとえば、受信した日付が00101011(湿度整数の8ビット値)00000000(湿度10進数の8ビット値)00111100(温度整数の8ビット値)00000000(温度10進数の8ビット値)01100111(チェックビット)の場合

計算:

00101011+00000000+00111100+00000000=01100111.

最終結果がチェックビットデータと等しい場合、データ送信は異常である:Falseを返す。

最終結果がチェックビットデータと等しく、受信データは正しい場合、 the_bytes[0]the_bytes[2] が返され、「Humidity = 43%、Temperature= 60C」が出力される。

現象画像
_images/image209.jpeg

2.2.4 PIR

前書き

このプロジェクトでは、人体の赤外線焦電センサーを使用してデバイスを作成する。誰かがLEDに近づくと、LEDは自動的に点灯する。そうでない場合、ライトは消灯する。この赤外線モーションセンサーは、人間や動物が発する赤外線を検出できるセンサーの一種である。

部品
_images/list_2.2.4_pir.png
原理

PIRセンサーは、赤外線熱放射を検出し、赤外線熱放射を放出する生物の存在を検出するために使用できる。

PIRセンサーは差動増幅器に接続される2つのスロットに分割される。 静止物体がセンサーの前にあるときはいつでも、二つのスロットは同じ量の放射線を受け取り、 出力はゼロである。動いている物体がセンサーの前にあるときはいつでも、 スロットの一つが他のスロットよりも多くの放射線を受け取り、出力を上下に変動させる。 この出力電圧の変化は、動きの検出の結果である。

_images/image211.png

検知モジュールの配線後、1分間の初期化が行われる。初期化中に、モジュールは間隔を置いて0〜3回出力する。その後、モジュールはスタンバイモードになる。干渉信号によって引き起こされる誤動作を避けるために、光源と他の源の干渉をモジュールの表面から遠ざけてください。 風はセンサーにも干渉する可能性があるため、風があまり無くてモジュールを使用することをお勧めする。

_images/image212.png

距離調整

距離調整ポテンショメータのノブを時計回りに回すと、検知距離の範囲が広がり、 最大検知距離範囲は約0〜7メートルである。 反時計回りに回すと、検知距離の範囲が狭くなり、最小検知距離の範囲は約0〜3メートルである。

遅延調整

遅延調整ポテンショメーターのノブを時計回りに回すと、検知遅延が増加することも分かる。 検知遅延の最大値は、最大300秒に達する可能性がある。 逆に、反時計回りに回転させると、最小5秒で遅延を短縮できる。

二つのトリガーモード:(ジャンパーキャップを使用して異なるモードを選択する)。

  • H: 繰り返し可能なトリガーモード、人体を感知した後、モジュールは高レベルを出力します。 その後の遅延期間中に、誰かが検知範囲に入ると、出力は高レベルのままになります。

  • L: 繰り返し不可のトリガーモード、人体を感知すると高レベルを出力します。 遅延後、出力は自動的に高レベルから低レベルに変わります。

回路図
_images/image327.png
実験手順

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

_images/image214.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.2.4/

ステップ3: コードをコンパイルする。

gcc 2.2.4_PIR.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行後、PIR は周囲を検出し、誰かが通り過ぎるのを感知すると、 RGB LED を黄色に点灯させます。 PIR モジュールには 2 つのポテンショメータがあり、 1 つは感度を調整するためのもので、もう 1 つは検出距離を調整するためのものです。 PIR モジュールがうまく機能するためには、両方を完全に反時計回りに回す必要があります。

_images/PIR_TTE.png

コード

#include <wiringPi.h>
#include <softPwm.h>
#include <stdio.h>
#define uchar unsigned char

#define pirPin    0     //the pir connect to GPIO0
#define redPin    1
#define greenPin  2
#define bluePin   3

void ledInit(void){
    softPwmCreate(redPin,  0, 100);
    softPwmCreate(greenPin,0, 100);
    softPwmCreate(bluePin, 0, 100);
}
void ledColorSet(uchar r_val, uchar g_val, uchar b_val){
    softPwmWrite(redPin,   r_val);
    softPwmWrite(greenPin, g_val);
    softPwmWrite(bluePin,  b_val);
}
int main(void)
{
    int pir_val;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    ledInit();
    pinMode(pirPin, INPUT);
    while(1){
    pir_val = digitalRead(pirPin);
        if(pir_val== 1){ //if read pir is HIGH level
            ledColorSet(0xff,0xff,0x00);
        }
        else {
        ledColorSet(0x00,0x00,0xff);
        }
    }
    return 0;
}

コードの 説明

void ledInit(void);
void ledColorSet(uchar r_val, uchar g_val, uchar b_val);

これらのコードは、RGB LEDの色を設定するために使用されます。詳細については、 1.1.2 RGB LED を参照してください。

int main(void)
{
    int pir_val;
    //……
    pinMode(pirPin, INPUT);
    while(1){
    pir_val = digitalRead(pirPin);
        if(pir_val== 1){ //if read pir is HIGH level
            ledColorSet(0xff,0xff,0x00);
        }
        else {
        ledColorSet(0x00,0x00,0xff);
        }
    }
    return 0;
}

PIRが人間の赤外線スペクトルを検出すると、RGB LEDが黄色の光を発する。そうでない場合は、青色の光を発する。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 2.2.4_PIR.py

コードの実行後、PIR は周囲を検出し、誰かが通り過ぎるのを感知すると、 RGB LED を黄色に点灯させます。 PIR モジュールには 2 つのポテンショメータがあり、 1 つは感度を調整するためのもので、もう 1 つは検出距離を調整するためのものです。 PIR モジュールがうまく機能するためには、両方を完全に反時計回りに回す必要があります。

_images/PIR_TTE.png

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

rgbPins = {'Red':18, 'Green':27, 'Blue':22}
pirPin = 17    # the pir connect to pin17

def setup():
    global p_R, p_G, p_B
    GPIO.setmode(GPIO.BCM)          # Set the GPIO modes to BCM Numbering
    GPIO.setup(pirPin, GPIO.IN)    # Set pirPin to input
    # Set all LedPin's mode to output and initial level to High(3.3v)
    for i in rgbPins:
        GPIO.setup(rgbPins[i], GPIO.OUT, initial=GPIO.HIGH)

    # Set all led as pwm channel and frequece to 2KHz
    p_R = GPIO.PWM(rgbPins['Red'], 2000)
    p_G = GPIO.PWM(rgbPins['Green'], 2000)
    p_B = GPIO.PWM(rgbPins['Blue'], 2000)

    # Set all begin with value 0
    p_R.start(0)
    p_G.start(0)
    p_B.start(0)

# Define a MAP function for mapping values.  Like from 0~255 to 0~100
def MAP(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

# Define a function to set up colors
def setColor(color):
# configures the three LEDs' luminance with the inputted color value .
    # Devide colors from 'color' veriable
    R_val = (color & 0xFF0000) >> 16
    G_val = (color & 0x00FF00) >> 8
    B_val = (color & 0x0000FF) >> 0
    # Map color value from 0~255 to 0~100
    R_val = MAP(R_val, 0, 255, 0, 100)
    G_val = MAP(G_val, 0, 255, 0, 100)
    B_val = MAP(B_val, 0, 255, 0, 100)

    #Assign the mapped duty cycle value to the corresponding PWM channel to change the luminance.
    p_R.ChangeDutyCycle(R_val)
    p_G.ChangeDutyCycle(G_val)
    p_B.ChangeDutyCycle(B_val)
    #print ("color_msg: R_val = %s, G_val = %s,     B_val = %s"%(R_val, G_val, B_val))

def loop():
    while True:
        pir_val = GPIO.input(pirPin)
        if pir_val==GPIO.HIGH:
            setColor(0xFFFF00)
        else :
            setColor(0x0000FF)

def destroy():
    p_R.stop()
    p_G.stop()
    p_B.stop()
    GPIO.cleanup()                     # Release resource

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

コードの 説明

rgbPins = {'Red':18, 'Green':27, 'Blue':22}

def setup():
    global p_R, p_G, p_B
    GPIO.setmode(GPIO.BCM)
    # ……
    for i in rgbPins:
        GPIO.setup(rgbPins[i], GPIO.OUT, initial=GPIO.HIGH)
    p_R = GPIO.PWM(rgbPins['Red'], 2000)
    p_G = GPIO.PWM(rgbPins['Green'], 2000)
    p_B = GPIO.PWM(rgbPins['Blue'], 2000)
    p_R.start(0)
    p_G.start(0)
    p_B.start(0)

def MAP(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

def setColor(color):
...

これらのコードは、RGB LEDの色を設定するために使用されます。詳細については、 1.1.2 RGB LED を参照してください。

def loop():
    while True:
        pir_val = GPIO.input(pirPin)
        if pir_val==GPIO.HIGH:
            setColor(0xFFFF00)
        else :
            setColor(0x0000FF)

PIRが人間の赤外線スペクトルを検出すると、RGB LEDが黄色の光を発する。そうでない場合は、青色の光を発する。

現象画像
_images/image215.jpeg

2.2.5 超音波センサーモジュール

前書き

超音波センサーは超音波を使用して物体を正確に検出し、距離を測定する。超音波を送り出し、電子信号に変換する。

部品
_images/list_2.2.5.png
原理

超音波

超音波測距モジュールは2cm-400cmの非接触測定機能を提供し、測距精度は3mmに達することができる。信号が5m以内で安定し、5m後に信号が徐々に弱まり、7mの位置が消えることを確認できる。

モジュールには、超音波送信機、受信機、と制御回路が含まれている。基本的な原理は次のとおりである:

(1)IOフリップフロップを使用して、少なくとも10usの高レベル信号を処理する。

(2)モジュールは8つの40khzを自動的に送信し、パルス信号が戻すかどうかを検出する。

(3)信号が戻し、高レベルを通過する場合、高出力IO持続時間は、超音波の送信から信号の戻りまでの時間である。ここでは、テスト距離=(高時間x音速(340 m/s)/ 2。

_images/image217.png _images/image328.png

タイミング図を以下に示す。トリガー入力に10usの短いパルスを供給してレンジングを開始するだけで、モジュールは40 kHzで8サイクルの超音波バーストを送信し、エコーを上げる。トリガー信号を送信してからエコー信号を受信するまでの時間間隔で範囲を計算できる。

式:us/58 =センチメートルまたはus/148 =インチ;または:範囲=高レベル時間 * 速度(340M/S)/ 2;トリガー信号とエコー信号の信号衝突を防ぐために、60ms以上の測定サイクルを使用することをお勧めする。

_images/image218.png
回路図
_images/image329.png
実験手順

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

_images/image220.png
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.2.5/

ステップ3: コードをコンパイルする。

gcc 2.2.5_Ultrasonic.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードを実行すると、超音波センサーモジュールが前方の障害物とモジュール自体の間の距離を検出し、距離値が画面に出力される。

コード

#include <wiringPi.h>
#include <stdio.h>
#include <sys/time.h>

#define Trig    4
#define Echo    5

void ultraInit(void)
{
    pinMode(Echo, INPUT);
    pinMode(Trig, OUTPUT);
}

float disMeasure(void)
{
    struct timeval tv1;
    struct timeval tv2;
    long time1, time2;
float dis;

    digitalWrite(Trig, LOW);
    delayMicroseconds(2);

    digitalWrite(Trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(Trig, LOW);

    while(!(digitalRead(Echo) == 1));
    gettimeofday(&tv1, NULL);

    while(!(digitalRead(Echo) == 0));
    gettimeofday(&tv2, NULL);

    time1 = tv1.tv_sec * 1000000 + tv1.tv_usec;
    time2  = tv2.tv_sec * 1000000 + tv2.tv_usec;

    dis = (float)(time2 - time1) / 1000000 * 34000 / 2;

    return dis;
}

int main(void)
{
    float dis;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }

    ultraInit();

    while(1){
        dis = disMeasure();
        printf("%0.2f cm\n\n",dis);
        delay(300);
    }

    return 0;
}

コードの説明

void ultraInit(void)
{
    pinMode(Echo, INPUT);
    pinMode(Trig, OUTPUT);
}

超音波ピンを初期化する。一方、Echoを入力、Trigを出力に設定する。

float disMeasure(void){};

戻り検出距離を計算することにより、この機能は超音波センサーの機能を実現するために使用される。

struct timeval tv1;
struct timeval tv2;

構造体 timeval は、現在の時刻を保存するために使用される構造体である。完全な構造は次の通りである:

struct timeval
{
__time_t tv_sec;        /* Seconds. */
__suseconds_t tv_usec;  /* Microseconds. */
};

ここで、 tv_sec は、エポックが struct timeval を作成するときに費やした秒を表す。 Tv_usec はマイクロ秒または秒の一部を表す。

digitalWrite(Trig, HIGH);
delayMicroseconds(10);
digitalWrite(Trig, LOW);

10usの超音波パルスが送信されている。

while(!(digitalRead(Echo) == 1));
gettimeofday(&tv1, NULL);

このempty loopは、トリガー信号が送信されたときに、干渉エコー信号がないことを確認してから現在の時刻を取得するために使用される。

while(!(digitalRead(Echo) == 0));
gettimeofday(&tv2, NULL);

このempty loopは、エコー信号が受信されて現在の時刻が取得されるまで次のステップが実行されないようにするために使用される。

time1 = tv1.tv_sec * 1000000 + tv1.tv_usec;
time2  = tv2.tv_sec * 1000000 + tv2.tv_usec;

struct timevalによって保存された時間を完全なマイクロ秒時間に変換する。

dis = (float)(time2 - time1) / 1000000 * 34000 / 2;

距離は時間間隔と音の伝播速度によって計算される。空気中の音速:34000cm/s。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 2.2.5_Ultrasonic.py

コードを実行すると、超音波センサーモジュールが前方の障害物とモジュール自体の間の距離を検出し、距離値が画面に出力される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

TRIG = 16
ECHO = 18

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(TRIG, GPIO.OUT)
    GPIO.setup(ECHO, GPIO.IN)

def distance():
    GPIO.output(TRIG, 0)
    time.sleep(0.000002)

    GPIO.output(TRIG, 1)
    time.sleep(0.00001)
    GPIO.output(TRIG, 0)


    while GPIO.input(ECHO) == 0:
        a = 0
    time1 = time.time()
    while GPIO.input(ECHO) == 1:
        a = 1
    time2 = time.time()

    during = time2 - time1
    return during * 340 / 2 * 100

def loop():
    while True:
        dis = distance()
        print ('Distance: %.2f' % dis)
        time.sleep(0.3)

def destroy():
    GPIO.cleanup()

if __name__ == "__main__":
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コードの説明

def distance():

戻り検出距離を計算することにより、この機能は超音波センサーの機能を実現するために使用される。

GPIO.output(TRIG, 1)
time.sleep(0.00001)
GPIO.output(TRIG, 0)

これは10usの超音波パルスを送信している。

while GPIO.input(ECHO) == 0:
    a = 0
time1 = time.time()

このempty loopは、トリガー信号が送信されたときに、干渉エコー信号がないことを確認してから現在の時刻を取得するために使用される。

while GPIO.input(ECHO) == 1:
    a = 1
time2 = time.time()

このempty loopは、エコー信号が受信されて現在の時刻が取得されるまで次のステップが実行されないようにするために使用される。

during = time2 - time1

間隔計算を実行する。

return during * 340 / 2 * 100

距離は時間間隔の光と音の伝播速度によって計算される。空気中の音速:340m / s。

現象画像
_images/image221.jpeg

2.2.6 MPU6050モジュール

前書き

MPU-6050は、低消費電力、低コスト、高性能などの機能を備えたスマートフォン、タブレット、ウェアラブルセンサー向けに設計された世界初で唯一の6軸物標追跡装置(3軸ジャイロスコープと3軸加速度センサー)である。

この実験では、I2Cを使用して、MPU6050の3軸加速度センサーと3軸ジャイロスコープの値を取得し、画面に表示する。

部品
_images/list_2.2.6.png
原理

MPU6050

MPU-6050は、6軸(3軸ジャイロスコープ、3軸加速度計を組み合わせた)物標追跡装置である。

その三つの座標系は次のように定義される:

MPU6050をテーブルの上に平らに置き、ラベルのある面が上向きで、 この表面のドットが左上隅にあることを確認してください。 次に、上向きの直立方向がチップのz軸である。左から右への方向はX軸と見なされる。 したがって、後ろから前への方向はY軸として定義される。

_images/image223.png

3-軸加速度計

加速度計は加えられた機械応力に応答して電荷を生成する特定の材料の能力である圧電効果の原理で動作する。

ここで、上記の写真のように、小さなボールの中に直方体の箱があることを想像してください。 この箱の壁は圧電結晶で作られている。箱を傾けると、重力によりボールが傾斜の方向に移動する。 ボールが衝突する壁は、小さな圧電電流を生成する。 合計で、立方体には3組の向かい合った壁がある。 各ペアは、3D空間の軸:X、Y、Z軸に対応する。 圧電壁から生成される電流に応じて、傾斜の方向とその大きさを決定できる。

_images/image224.png

MPU6050を使用して、各座標軸の加速度を検出できる(静止デスクトップ状態では、Z軸の加速度は1重力単位で、X軸とY軸は0である)。傾斜または無重量/重量超過の状態にある場合、対応する測定値が変化する。

プログラムで選択できる測定範囲には、+/-2g、+/-4g、+/-8g、と各精度に対応する+/-16g(デフォルトでは2g)の4種類がある。値の範囲は-32768〜32767である。

読み取り値を測定範囲にマッピングすることにより、加速度計の読み取り値は加速度値に変換される。

加速度=(加速度計軸の生データ / 65536 * フルスケールの加速度範囲)g

X軸を例として、加速度計X軸の生データは16384の場合、範囲を +/-2gに選択する:

X軸による加速度 = (16384 / 65536 * 4) g =1g

3軸ジャイロスコープ

ジャイロスコープはコリオリ加速の原理で動作する。 フォークのような構造があり、常に前後に動いていると想像してください。 圧電結晶を使用して所定の位置に保持される。 この配置を傾けようとするたびに、結晶は傾斜の方向に力を受ける。 これは、可動フォークの慣性の結果によって引き起こされる。 したがって、結晶は圧電効果と一致して電流を生成し、この電流は増幅される。

_images/image225.png

また、ジャイロスコープには、+ /-250、+ /-500、+ /-1000、+/- 2000.計算方法と加速は基本的に一貫している。

読み取り値を角速度に変換する式は次の通りである:

角速度=(ジャイロスコープの軸生データ/ 65536 *フルスケールジャイロスコープの範囲)°/ s

X軸、たとえば、加速度計のX軸の生データは16384で、範囲は+ /-250°/ sである:

X軸による角速度 = (16384 / 65536 * 500)°/s =125°/s

回路図

MPU6050はI2Cバスインターフェイスを介してマイクロコントローラーと通信する。 SDA1とSCL1を対応するピンに接続する必要がある。

_images/image330.png
実験手順

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

_images/image227.png

ステップ2: I2C構成 (付録を参照してください。I2Cを設定している場合は、この手順をスキップしてください。)

C言語ユーザー向け

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

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.2.6/

ステップ4: コードをコンパイルする。

gcc 2.2.6_mpu6050.c -lwiringPi -lm

ステップ5: EXEファイルを実行する。

sudo ./a.out

コードを実行すると、MPU6050によって読み取られたx軸、y軸の転向角、加速度、各軸の角速度が計算後に画面に入力される。

コード

#include  <wiringPiI2C.h>
#include <wiringPi.h>
#include  <stdio.h>
#include  <math.h>
int fd;
int acclX, acclY, acclZ;
int gyroX, gyroY, gyroZ;
double acclX_scaled, acclY_scaled, acclZ_scaled;
double gyroX_scaled, gyroY_scaled, gyroZ_scaled;

int read_word_2c(int addr)
{
int val;
val = wiringPiI2CReadReg8(fd, addr);
val = val << 8;
val += wiringPiI2CReadReg8(fd, addr+1);
if (val >= 0x8000)
    val = -(65536 - val);
return val;
}

double dist(double a, double b)
{
return sqrt((a*a) + (b*b));
}

double get_y_rotation(double x, double y, double z)
{
double radians;
radians = atan2(x, dist(y, z));
return -(radians * (180.0 / M_PI));
}

double get_x_rotation(double x, double y, double z)
{
double radians;
radians = atan2(y, dist(x, z));
return (radians * (180.0 / M_PI));
}

int main()
{
fd = wiringPiI2CSetup (0x68);
wiringPiI2CWriteReg8 (fd,0x6B,0x00);//disable sleep mode
printf("set 0x6B=%X\n",wiringPiI2CReadReg8 (fd,0x6B));

while(1) {

    gyroX = read_word_2c(0x43);
    gyroY = read_word_2c(0x45);
    gyroZ = read_word_2c(0x47);

    gyroX_scaled = gyroX / 131.0;
    gyroY_scaled = gyroY / 131.0;
    gyroZ_scaled = gyroZ / 131.0;

    //Print values for the X, Y, and Z axes of the gyroscope sensor.
    printf("My gyroX_scaled: %f\n", gyroY X_scaled);
    delay(100);
    printf("My gyroY_scaled: %f\n", gyroY Y_scaled);
    delay(100);
    printf("My gyroZ_scaled: %f\n", gyroY Z_scaled);
    delay(100);

    acclX = read_word_2c(0x3B);
    acclY = read_word_2c(0x3D);
    acclZ = read_word_2c(0x3F);

    acclX_scaled = acclX / 16384.0;
    acclY_scaled = acclY / 16384.0;
    acclZ_scaled = acclZ / 16384.0;

    //Print the X, Y, and Z values of the acceleration sensor.
    printf("My acclX_scaled: %f\n", acclX_scaled);
    delay(100);
    printf("My acclY_scaled: %f\n", acclY_scaled);
    delay(100);
    printf("My acclZ_scaled: %f\n", acclZ_scaled);
    delay(100);

    printf("My X rotation: %f\n", get_x_rotation(acclX_scaled, acclY_scaled, acclZ_scaled));
    delay(100);
    printf("My Y rotation: %f\n", get_y_rotation(acclX_scaled, acclY_scaled, acclZ_scaled));
    delay(100);

    delay(100);
}
return 0;
}

コードの説明

int read_word_2c(int addr)
{
int val;
val = wiringPiI2CReadReg8(fd, addr);
val = val << 8;
val += wiringPiI2CReadReg8(fd, addr+1);
if (val >= 0x8000)
    val = -(65536 - val);
return val;
}

MPU6050から送信されたセンサーデータを読み取る。

double get_y_rotation(double x, double y, double z)
{
double radians;
radians = atan2(x, dist(y, z));
return -(radians * (180.0 / M_PI));
}

Y軸の転向角を取得する。

double get_x_rotation(double x, double y, double z)
{
double radians;
radians = atan2(y, dist(x, z));
return (radians * (180.0 / M_PI));
}

x軸の転向角を計算する。

gyroX = read_word_2c(0x43);
gyroY = read_word_2c(0x45);
gyroZ = read_word_2c(0x47);

gyroX_scaled = gyroX / 131.0;
gyroY_scaled = gyroY / 131.0;
gyroZ_scaled = gyroZ / 131.0;

//Print values for the X, Y, and Z axes of the gyroscope sensor.
printf("My gyroX_scaled: %f\n", gyroY X_scaled);
printf("My gyroY_scaled: %f\n", gyroY Y_scaled);
printf("My gyroZ_scaled: %f\n", gyroY Z_scaled);

ジャイロセンサーのx軸、y軸、z軸の値を読み取り、メタデータを角速度値に変換してから出力する。

acclX = read_word_2c(0x3B);
acclY = read_word_2c(0x3D);
acclZ = read_word_2c(0x3F);

acclX_scaled = acclX / 16384.0;
acclY_scaled = acclY / 16384.0;
acclZ_scaled = acclZ / 16384.0;

//Print the X, Y, and Z values of the acceleration sensor.
printf("My acclX_scaled: %f\n", acclX_scaled);
printf("My acclY_scaled: %f\n", acclY_scaled);
printf("My acclZ_scaled: %f\n", acclZ_scaled);

加速度センサーのx軸、y軸、z軸の値を読み取り、メタデータを加速速度値(重力単位)に変換してから出力する。

printf("My X rotation: %f\n", get_x_rotation(acclX_scaled, acclY_scaled, acclZ_scaled));
printf("My Y rotation: %f\n", get_y_rotation(acclX_scaled, acclY_scaled, acclZ_scaled));

x軸とy軸の転向角をプリントする。

Python言語ユーザー向け

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

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ4: EXEファイルを実行する。

sudo python3 2.2.6_mpu6050.py

コードを実行し、x軸とy軸の転向角、加速度とMPU6050によって読み取られた各軸の角速度は、計算後に画面に入力される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import smbus
import math
import time

# Power management registers
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

def read_byte(adr):
    return bus.read_byte_data(address, adr)

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val

def dist(a,b):
    return math.sqrt((a*a)+(b*b))

def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)

def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)


bus = smbus.SMBus(1) # or bus = smbus.SMBus(1) for Revision 2 boards
address = 0x68       # This is the address value read via the i2cdetect command

# Now wake the 6050 up as it starts in sleep mode
bus.write_byte_data(address, power_mgmt_1, 0)

while True:
    time.sleep(0.1)
    gyro_xout = read_word_2c(0x43)
    gyro_yout = read_word_2c(0x45)
    gyro_zout = read_word_2c(0x47)

    print ("gyro_xout : ", gyro_xout, " scaled: ", (gyro_xout / 131))
    print ("gyro_yout : ", gyro_yout, " scaled: ", (gyro_yout / 131))
    print ("gyro_zout : ", gyro_zout, " scaled: ", (gyro_zout / 131))

    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)

    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0

    print ("accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled)
    print ("accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled)
    print ("accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled)

    print ("x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
    print ("y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))

    time.sleep(0.5)

コードの説明

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val

MPU6050から送信されたセンサーデータを読み取る。

def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)

y軸の転向角を計算する。

def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)

x軸の転向角を計算する。

gyro_xout = read_word_2c(0x43)
gyro_yout = read_word_2c(0x45)
gyro_zout = read_word_2c(0x47)

print ("gyro_xout : ", gyro_xout, " scaled: ", (gyro_xout / 131))
print ("gyro_yout : ", gyro_yout, " scaled: ", (gyro_yout / 131))
print ("gyro_zout : ", gyro_zout, " scaled: ", (gyro_zout / 131))

ジャイロセンサーのx軸、y軸、z軸の値を読み取り、メタデータを角速度値に変換してから出力する。

accel_xout = read_word_2c(0x3b)
accel_yout = read_word_2c(0x3d)
accel_zout = read_word_2c(0x3f)

accel_xout_scaled = accel_xout / 16384.0
accel_yout_scaled = accel_yout / 16384.0
accel_zout_scaled = accel_zout / 16384.0

print ("accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled)
print ("accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled)
print ("accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled)

加速度センサーのx軸、y軸、z軸の値を読み取り、メタデータを加速速度値(重力単位)に変換してから出力する。

print ("x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
print ("y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))

x軸とy軸の転向角をプリントする。

現象画像
_images/image228.jpeg

2.2.7 MFRC522 RFIDモジュール

前書き

無線周波数識別(RFID)は、オブジェクト(またはタグ)と質問デバイス(またはリーダー)の間の無線通信を使用して、そのようなオブジェクトを自動的に追跡したり識別したりする技術を指す。

この技術の最も一般的なアプリケーションには、小売サプライチェーン、軍事サプライチェーン、自動決済方法、荷物の追跡と管理、ドキュメントの追跡と医薬品管理などが含まれておる。

このプロジェクトでは、読み取りと書き込みにRFIDを使用する。

部品
_images/list_2.2.7.png
原理

RFID

無線周波数識別(RFID)は、オブジェクト(またはタグ)と質問デバイス(またはリーダー)の間の無線通信を使用して、 そのようなオブジェクトを自動的に追跡したり識別したりする技術を指す。 タグの送信範囲はリーダーから数メートルに制限されている。 リーダーとタグの間の明確な見通し線は必ずしも必要ではない。

ほとんどのタグには、少なくとも1つの集積回路(IC)とアンテナが含まれている。 マイクロチップは情報を保存し、リーダーとの無線周波数(RF)通信を管理する。 パッシブタグは独立したエネルギー源を持たず、リーダーによって提供される外部電磁信号に依存して動作する。 しかしアクティブタグバッテリーなどの独立したエネルギー源が含まれている。 したがって、処理、送信機能と範囲が拡大している可能性がある。

_images/image230.png

MFRC522

MFRC522は、読み取りと書き込みカードチップの一種である。通常、13.56MHzの無線で使用される。NXP Companyによって発売された低電圧、低コスト、小型の非接触カードチップであり、インテリジェント機器と持ち転びやすい手持ちデバイスの最良の選択である。

MF RC522はすべてのタイプの13.56MHzパッシブ非接触通信方法とプロトコルで完全に開示された高度な変調と復調の概念を使用している。 さらに、MIFARE製品を検証するための高速CRYPTO1暗号化アルゴリズムをサポートしている。 MFRC522は最大424kbit/sの双方向データ伝送速度で、MIFAREシリーズの高速非接触通信もサポートしている。 13.56MHz高集積リーダーカードシリーズの新しいメンバーとして、MF RC522は既存のMF RC500とMF RC530と非常に似ているが、多くの違いがある。 配線が少ないシリアル方式でホストマシンと通信する。SPI、I2C、とシリアルUARTモード(RS232に類似)から選択できる。 これにより、接続の削減、PCBボードスペースの節約(サイズの縮小)、およびコストの削減に役立つ。

回路図
_images/image331.png
実験手順

ステップ1: 回路を作る

_images/image232.png

ステップ2: SPI構成 (SPIを設定している場合は、このステップをスキップしてください。)

C言語ユーザー向け

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

cd /home/pi/davinci-kit-for-raspberry-pi/c/2.2.7/

ステップ4: コードをコンパイルする。

make read
make write

注釈

カードIDの読み取りまたは書き込みには二つの例があり、必要に応じていずれかを選択できる。

ステップ5: EXEファイルを実行する。

sudo ./read
sudo ./write

コードの説明

InitRc522();

この関数はRFID RC522モジュールを初期化するために使用される。

uint8_t read_card_data();

この関数はカードのデータを読み取るために使用され、読み取りが成功すると「1」が返されます。

uint8_t write_card_data(uint8_t *data);

この関数はカードのデータを書き込むために使用され、書き込みが成功すると「1」を返します。 *data は、カードに書き込まれる情報です。

Python言語ユーザー向け

ステップ2: 仮想環境の有効化。

注意

  • 有効化する前に、仮想環境を作成していることを確認してください。詳細はこちらを参照してください: 仮想環境の作成.

  • Raspberry Piを再起動するたびや、新しいターミナルを開くたびに、仮想環境を有効化するために次のコマンドを再度実行する必要があります。

source myenv/bin/activate

仮想環境が有効化されると、コマンドラインのプロンプトの前に環境名が表示され、仮想環境内で作業していることが示されます。

ステップ3: ライブラリのインストール。

spidev ライブラリはSPIとのやり取りを処理し、このチュートリアルの重要なコンポーネントであり、Raspberry PiがRFID RC522とのやり取りに必要です。

以下のコマンドを実行して、 pip を介して spidev をRaspberry Piにインストールします。

sudo pip3 install spidev

MFRC522ライブラリのインストールを続行します。 MFRC522ライブラリには2つのファイルが含まれています: MFRC522.pySimpleMFRC522.py

MFRC522.py

はRFID RC522インターフェースの実装であり、このライブラリはPiのSPIインターフェースを介してRFIDとの通信のすべての重い作業を処理します。

SimpleMFRC522.pyMFRC522.py ファイルを取り、わずかな関数の代わりにわずかな関数で処理できるように大幅に簡素化します。

sudo pip3 install mfrc522

ステップ4: 仮想環境の終了。

作業を完了し、仮想環境から退出したい場合は、単純に次のコマンドを実行します:

deactivate

これにより、システムのグローバルPython環境に戻ります。

ステップ5: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/2.2.7

ステップ6: EXEファイルを実行する。

sudo python3 2.2.7_read.py
sudo python3 2.2.7_write.py

注釈

2.2.7_read.py を実行すると、カードの ID とテキストがシェルに出力されます。 2.2.7_write.py を実行した後、最初にメッセージを書き込み、Enter を押して確認し、最後にカードを MFRC522 RFID モジュールに置いて書き込みを完了する必要があります。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

# read
import time
from mfrc522 import SimpleMFRC522
import RPi.GPIO as GPIO

reader = SimpleMFRC522()

def main():
    while True:
        print("Reading...Please place the card...")
        id, text = reader.read()
        print("ID: %s\nText: %s" % (id,text))
        time.sleep(3)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        main()
    # When 'Ctrl+C' is pressed, the program destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()
# write
from mfrc522 import SimpleMFRC522
import RPi.GPIO as GPIO

reader = SimpleMFRC522()

def main():
    while True:
        text = input('Please write new data:')
        print("Please place the card to complete writing")
        reader.write(text)
        print("Data writing is complete")

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        main()
    # When 'Ctrl+C' is pressed, the program destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()

コードの説明

reader = SimpleMFRC522()

SimpleMFRC522() クラスをインスタンス化します。

reader.read()

この機能は、カードデータを読み取るために使用されます。 読み取りが成功すると、IDとテキストが返されます。

reader.write(text)

この機能は、カードに情報を書き込むために使用されます。「Enter」キーを押して書き込みを終了します。 text は、カードに書き込まれる情報です。

現象画像
_images/image233.jpeg

3 拡張 (Pi 5用ではない)

3.1.1 計数装置

前書き

ここでは、PIRセンサーと4桁のセグメントディスプレイで構成される数字表示カウンターシステムを作成する。 PIRが誰かが通り過ぎていることを検出すると、4桁のセグメントディスプレイの数字に1が加算される。 このカウンターを使用して、通路を歩いている人の数をカウントできる。

部品
_images/list_Counting_Device1.png _images/list_Counting_Device2.png
回路図

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

GPIO26

Pin 37

25

26

_images/Schematic_three_one1.png
実験手順

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

计数器_bb
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.1/

ステップ3: コードをコンパイルする。

gcc 3.1.1_CountingDevice.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードの実行後、PIRが誰かが通り過ぎていることを検出すると、4桁のセグメントディスプレイの数字に1が加算される。

PIR モジュールには 2 つのポテンショメータがあり、 1 つは感度を調整するためのもので、もう 1 つは検出距離を調整するためのものです。 PIR モジュールがうまく機能するためには、両方を完全に反時計回りに回す必要があります。

コードの説明

void display()
{
    clearDisplay();
    pickDigit(0);
    hc595_shift(number[counter % 10]);

    clearDisplay();
    pickDigit(1);
    hc595_shift(number[counter % 100 / 10]);

    clearDisplay();
    pickDigit(2);
    hc595_shift(number[counter % 1000 / 100]);

    clearDisplay();
    pickDigit(3);
    hc595_shift(number[counter % 10000 / 1000]);
}

まず、4番目のセグメントディスプレイを開始し、1桁の数字を書き込む。 次に、3番目のセグメントディスプレイを開始し、10桁の数字を入力する。 その後、2番目と1番目のセグメントディスプレイをそれぞれ開始し、それぞれ数百桁と数千桁を書き込む。 リフレッシュ速度が非常に速いため、完全な4桁のディスプレイが表示される。

void loop(){
    int currentState =0;
    int lastState=0;
    while(1){
        display();
        currentState=digitalRead(sensorPin);
        if((currentState==0)&&(lastState==1)){
            counter +=1;
        }
        lastState=currentState;
    }
}

これが主な機能である:4桁のセグメントディスプレイに数字を表示し、PIR値を読み取る。 PIRが誰かが通り過ぎていることを検出すると、4桁のセグメントディスプレイの数字に1が加算される。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 3.1.1_CountingDevice.py

コードの実行後、PIRが誰かが通り過ぎていることを検出すると、 4桁のセグメントディスプレイの数字に1が加算される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

sensorPin = 26

SDI = 24
RCLK = 23
SRCLK = 18

placePin = (10, 22, 27, 17)
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

counter = 0

def clearDisplay():
    for i 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):
    for i in placePin:
        GPIO.output(i,GPIO.LOW)
    GPIO.output(placePin[digit], GPIO.HIGH)

def display():
    global counter
    clearDisplay()
    pickDigit(0)
    hc595_shift(number[counter % 10])

    clearDisplay()
    pickDigit(1)
    hc595_shift(number[counter % 100//10])

    clearDisplay()
    pickDigit(2)
    hc595_shift(number[counter % 1000//100])

    clearDisplay()
    pickDigit(3)
    hc595_shift(number[counter % 10000//1000])

def loop():
    global counter
    currentState = 0
    lastState = 0
    while True:
        display()
        currentState=GPIO.input(sensorPin)
        if (currentState == 0) and (lastState == 1):
            counter +=1
        lastState=currentState

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

def destroy():   # When "Ctrl+C" is pressed, the function is executed.
    GPIO.cleanup()

if __name__ == '__main__':  # Program starting from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コードの説明

1.1.5 4桁7セグメントディ スプレイに基づいて、このレッスンでは、 PIRモジュール を追加して、レッスン1.1.5の自動カウントをカウント検出に変更する。 PIRが誰かが通り過ぎていることを検出すると、4桁のセグメントディスプレイの数字に1が加算される。

def display():
    global counter
    clearDisplay()
    pickDigit(0)
    hc595_shift(number[counter % 10])

    clearDisplay()
    pickDigit(1)
    hc595_shift(number[counter % 100//10])

    clearDisplay()
    pickDigit(2)
    hc595_shift(number[counter % 1000//100])

    clearDisplay()
    pickDigit(3)
    hc595_shift(number[counter % 10000//1000])

まず、4番目のセグメントディスプレイを開始し、1桁の数字を書き込む。 次に、3番目のセグメントディスプレイを開始し、10桁の数字を入力する。 その後、2番目と1番目のセグメントディスプレイをそれぞれ開始し、それぞれ数百桁と数千桁を書き込む。 リフレッシュ速度が非常に速いため、完全な4桁のディスプレイが表示される。

def loop():
global counter
    currentState = 0
    lastState = 0
    while True:
        display()
        currentState=GPIO.input(sensorPin)
        if (currentState == 0) and (lastState == 1):
            counter +=1
        lastState=currentState

これが主な機能である:4桁のセグメントディスプレイに数字を表示し、PIR値を読み取る。 PIRが誰かが通り過ぎていることを検出すると、4桁のセグメントディスプレイの数字に1が加算される。

現象画像
_images/image236.jpeg

3.1.2 いらっしゃいませ

前書き

このプロジェクトでは、PIRを使用して歩行者の動きを検知し、サーボ、LED、ブザーを使用してコンビニのセンサードアの動作をシミュレートする。歩行者がPIRの検知範囲内に現れると、インジケータライトが点灯し、ドアが開き、ブザーがオープニングベルを鳴らす。

部品
_images/list_Welcome.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO17

Pin 11

0

17

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

_images/Schematic_three_one2.png
実験手順

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

C:\Users\sunfounder\Desktop\3.1.4_Welcome_bb.png3.1.4_Welcome_bb
C言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.2/

ステップ3: コンパイルする。

gcc 3.1.2_Welcome.c -lwiringPi

ステップ4: 実行する。

sudo ./a.out

コードの実行後、PIRセンサーが通り過ぎる人を検出すると、 ドアが自動的に開き(サーボによってシミュレートされる)、 インジケーターをオンにして、ドアベルの音楽を再生する。ドアベルの音楽が再生されると、 システムは自動的にドアを閉じてインジケータライトをオフにし、次に誰かが通り過ぎることを待つ。

PIR モジュールには 2 つのポテンショメータがあり、 1 つは感度を調整するためのもので、もう 1 つは検出距離を調整するためのものです。 PIR モジュールがうまく機能するためには、両方を完全に反時計回りに回す必要があります。

コードの説明

void setAngle(int pin, int angle){    //Create a funtion to control the angle of the servo.
    if(angle < 0)
        angle = 0;
    if(angle > 180)
        angle = 180;
    softPwmWrite(pin,Map(angle, 0, 180, 5, 25));
}

0〜180の角度をサーボに書き込むための関数、 setAngle を作成する。

void doorbell(){
for(int i=0;i<sizeof(song)/4;i++){
        softToneWrite(BuzPin, song[i]);
        delay(beat[i] * 250);
    }

ブザーで音楽を再生できるようにする関数、 doorbell を作成する。

void closedoor(){
digitalWrite(ledPin, LOW);   //led off
for(int i=180;i>-1;i--){  //make servo rotate from maximum angle to minimum angle
    setAngle(servoPin,i);
    delay(1);
    }
}

ドアの閉鎖をシミュレートする関数 closedoor を作成し、 LEDをオフにし、サーボを180度から0度に回転させる。

void opendoor(){
    digitalWrite(ledPin, HIGH);   //led on
    for(int i=0;i<181;i++){  //make servo rotate from minimum angle to maximum angle
        setAngle(servoPin,i);
        delay(1);
    }
    doorbell();
    closedoor();
}

関数 opendoor() にはいくつかの部分が含まれている:インジケータライトをオンにし、 サーボを回転させ(ドアを開く動作をシミュレートする)、 コンビニのドアベル音楽を再生し、音楽を再生した後に関数 closedoor() を呼び出す。

    int main(void)
{
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    if(softToneCreate(BuzPin) == -1){
        printf("setup softTone failed !");
        return 1;
......

関数 main() で、ライブラリー wiringPi を初期化し、 softTone をセットアップしてから、 ledPin を出力状態に、 pirPin を入力状態に設定する。PIRセンサーが通り過ぎる人を検出すると、 ドアを開くことをシミュレートするために関数 opendoor が呼び出される。

Python言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 3.1.2_Welcome.py

コードの実行後、PIRセンサーが通り過ぎる人を検出すると、 ドアが自動的に開き(サーボによってシミュレートされる)、 インジケーターをオンにして、ドアベルの音楽を再生する。ドアベルの音楽が再生されると、 システムは自動的にドアを閉じてインジケータライトをオフにし、次に誰かが通り過ぎることを待つ。

PIR モジュールには 2 つのポテンショメータがあり、 1 つは感度を調整するためのもので、もう 1 つは検出距離を調整するためのものです。 PIR モジュールがうまく機能するためには、両方を完全に反時計回りに回す必要があります。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

SERVO_MIN_PULSE = 500
SERVO_MAX_PULSE = 2500

ledPin = 18    # define the ledPin
pirPin = 17    # define the sensorPin
servoPin = 22  # define the servoPin
buzPin = 27    # define the buzzerpin


CL = [0, 131, 147, 165, 175, 196, 211, 248]        # Frequency of Low C notes

CM = [0, 262, 294, 330, 350, 393, 441, 495]        # Frequency of Middle C notes

CH = [0, 525, 589, 661, 700, 786, 882, 990]        # Frequency of High C notes

song = [    CH[5],CH[2],CM[6],CH[2],CH[3],CH[6],CH[3],CH[5],CH[3],CM[6],CH[2]    ]

beat = [    1,1,1,1,1,2,1,1,1,1,1,]


def setup():
    global p
    global Buzz                        # Assign a global variable to replace GPIO.PWM
    GPIO.setmode(GPIO.BCM)       # Numbers GPIOs by physical location
    GPIO.setup(ledPin, GPIO.OUT)   # Set ledPin's mode is output
    GPIO.setup(pirPin, GPIO.IN)    # Set sensorPin's mode is input
    GPIO.setup(servoPin, GPIO.OUT)   # Set servoPin's mode is output
    GPIO.output(servoPin, GPIO.LOW)  # Set servoPin to low
    GPIO.setup(buzPin, GPIO.OUT)    # Set pins' mode is output

    Buzz = GPIO.PWM(buzPin, 440)    # 440 is initial frequency.
    Buzz.start(50)                    # Start Buzzer pin with 50% duty ration

    p = GPIO.PWM(servoPin, 50)     # set Frequece to 50Hz
    p.start(0)                     # Duty Cycle = 0

def map(value, inMin, inMax, outMin, outMax):
    return (outMax - outMin) * (value - inMin) / (inMax - inMin) + outMin


def setAngle(angle):      # make the servo rotate to specific angle (0-180 degrees)
    angle = max(0, min(180, angle))
    pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
    pwm = map(pulse_width, 0, 20000, 0, 100)
    p.ChangeDutyCycle(pwm)#map the angle to duty cycle and output it

def doorbell():
    for i in range(1, len(song)):        # Play song 1
        Buzz.ChangeFrequency(song[i])    # Change the frequency along the song note
        time.sleep(beat[i] * 0.25)        # delay a note for beat * 0.25s
    time.sleep(1)                        # Wait a second for next song.

def closedoor():
    GPIO.output(ledPin, GPIO.LOW)
    for i in range(180, -1, -1): #make servo rotate from 180 to 0 deg
        setAngle(i)
        time.sleep(0.001)
    time.sleep(1)
def opendoor():
    GPIO.output(ledPin, GPIO.LOW)
    for i in range(0, 181, 1):   #make servo rotate from 0 to 180 deg
        setAngle(i)     # Write to servo
        time.sleep(0.001)
    time.sleep(1)
    doorbell()
    closedoor()

def loop():
    while True:
        if GPIO.input(pirPin)==GPIO.HIGH:
            opendoor()


def destroy():
    GPIO.cleanup()                     # Release resource
    p.stop()
    Buzz.stop()

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the program destroy() will be  executed.
        destroy()

コードの説明

def setup():
    global p
    global Buzz                        # Assign a global variable to replace GPIO.PWM
    GPIO.setmode(GPIO.BCM)       # Numbers GPIOs by physical location
    GPIO.setup(ledPin, GPIO.OUT)   # Set ledPin's mode is output
    GPIO.setup(pirPin, GPIO.IN)    # Set sensorPin's mode is input
    GPIO.setup(buzPin, GPIO.OUT)    # Set pins' mode is output
    Buzz = GPIO.PWM(buzPin, 440)    # 440 is initial frequency.
    Buzz.start(50)                    # Start Buzzer pin with 50% duty ration
    GPIO.setup(servoPin, GPIO.OUT)   # Set servoPin's mode is output
    GPIO.output(servoPin, GPIO.LOW)  # Set servoPin to low
    p = GPIO.PWM(servoPin, 50)     # set Frequece to 50Hz
    p.start(0)                     # Duty Cycle = 0

これらのステートメントは、各部品のピンを初期化するために使用される。

def setAngle(angle):      # make the servo rotate to specific angle (0-180 degrees)
    angle = max(0, min(180, angle))
    pulse_width = map(angle, 0, 180, SERVO_MIN_PULSE, SERVO_MAX_PULSE)
    pwm = map(pulse_width, 0, 20000, 0, 100)
    p.ChangeDutyCycle(pwm)#map the angle to duty cycle and output it

0〜180の角度をサーボに書き込むための関数、 setAngle を作成する。

def doorbell():
    for i in range(1,len(song)): # Play song1
        Buzz.ChangeFrequency(song[i]) # Change the frequency along the song note
        time.sleep(beat[i] * 0.25) # delay a note for beat * 0.25s

ブザーで音楽を再生できるようにする関数、 doorbell を作成する。

def closedoor():
    GPIO.output(ledPin, GPIO.LOW)
    Buzz.ChangeFrequency(1)
    for i in range(180, -1, -1): #make servo rotate from 180 to 0 deg
        setAngle(i)
        time.sleep(0.001)

ドアを閉じて、インジケータライトをオフにする。

def opendoor():
    GPIO.output(ledPin, GPIO.LOW)
    for i in range(0, 181, 1):   #make servo rotate from 0 to 180 deg
        setAngle(i)     # Write to servo
        time.sleep(0.001)
    doorbell()
    closedoor()

関数 opendoor() にはいくつかの部分が含まれている:インジケータライトをオンにし、 サーボを回転させ(ドアを開く動作をシミュレートする)、コンビニのドアベル音楽を再生し、 音楽を再生した後に関数 closedoor() を呼び出す。

def loop():
while True:
    if GPIO.input(pirPin)==GPIO.HIGH:
        opendoor()

PIRは誰かが通り過ぎることを検知すると、関数 opendoor() を呼び出す。

現象画像
_images/image240.jpeg

3.1.3 後退警報装置

前書き

このプロジェクトでは、LCD、ブザー、と超音波センサーを使用して、 後退補助システムを作成する。それをリモートコントロール車両に置いて、 車をガレージに後退する実際のプロセスをシミュレートできる。

部品
_images/list_Reversing_Alarm.png
回路図

超音波センサーは障害物との間の距離を検出し、コードの形式でLCDに表示する。 同時に、超音波センサーにより、距離値に応じてブザーが異なる周波数の警告音を発する。

T-Board Name

physical

wiringPi

BCM

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO17

Pin 11

0

17

SDA1

Pin 3

SCL1

Pin 5

_images/Schematic_three_one3.png
実験手順

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

_images/image242.png
C言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.3/

ステップ3: コンパイルする。

gcc 3.1.3_ReversingAlarm.c -lwiringPi

ステップ4: 実行する。

sudo ./a.out

コードが実行されると、超音波センサーモジュールが障害物までの距離を検出し、LCD1602に距離に関する情報を表示する。また、ブザーは距離とともに周波数が変化する警告音を発する。

コード

注釈

次のコードは不完全である。完全なコードを確認する場合は、コマンド nano 3.1.1_ReversingAlarm.c を使用することをお勧めする。

#include <wiringPi.h>
#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <string.h>

#define Trig    4
#define Echo    5
#define Buzzer  0

int LCDAddr = 0x27;
int BLEN = 1;
int fd;

//here is the function of LCD
void write_word(int data){...}

void send_command(int comm){...}

void send_data(int data){...}

void lcdInit(){...}

void clear(){...}

void write(int x, int y, char data[]){...}

//here is the function of Ultrasonic
void ultraInit(void){...}

float disMeasure(void){...}

//here is the main function
int main(void)
{
    float dis;
    char result[10];
    if(wiringPiSetup() == -1){
        printf("setup wiringPi failed !");
        return 1;
    }

    pinMode(Buzzer,OUTPUT);
    fd = wiringPiI2CSetup(LCDAddr);
    lcdInit();
    ultraInit();

    clear();
    write(0, 0, "Ultrasonic Starting");
    write(1, 1, "By Sunfounder");

    while(1){
        dis = disMeasure();
        printf("%.2f cm \n",dis);
        delay(100);
        digitalWrite(Buzzer,LOW);
        if (dis > 400){
            clear();
            write(0, 0, "Error");
            write(3, 1, "Out of range");
            delay(500);
        }
        else
        {
            clear();
            write(0, 0, "Distance is");
            sprintf(result,"%.2f cm",dis);
            write(5, 1, result);

            if(dis>=50)
            {delay(500);}
            else if(dis<50 & dis>20) {
                for(int i=0;i<2;i++){
                digitalWrite(Buzzer,HIGH);
                delay(50);
                digitalWrite(Buzzer,LOW);
                delay(200);
                }
            }
            else if(dis<=20){
                for(int i=0;i<5;i++){
                digitalWrite(Buzzer,HIGH);
                delay(50);
                digitalWrite(Buzzer,LOW);
                delay(50);
                }
            }
        }
    }

    return 0;
}

コードの説明

pinMode(Buzzer,OUTPUT);
fd = wiringPiI2CSetup(LCDAddr);
lcdInit();
ultraInit();

このプログラムでは、以前の部品を総合的に適用する。 ここでは、ブザー、LCD、と超音波を使用する。 以前と同じ方法で初期化できる。

dis = disMeasure();
 printf("%.2f cm \n",dis);
digitalWrite(Buzzer,LOW);
if (dis > 400){
     write(0, 0, "Error");
     write(3, 1, "Out of range");
}
else
{
    write(0, 0, "Distance is");
    sprintf(result,"%.2f cm",dis);
    write(5, 1, result);
    }

ここで、超音波センサーの値を取得し、計算により距離を取得する。

距離の値が検出される範囲の値より大きい場合、エラーメッセージがLCDに表示される。 距離値が範囲内にある場合、対応する結果が出力される。

sprintf(result,"%.2f cm",dis);

LCDの出力モードは文字型のみをサポートし、 変数 dis はfloat型の値を保存するため、sprintf() を使わなければならない。 この関数はfloat型の値を文字に変換し、 文字列変数 result[] に保存する。 %.2f は小数点以下2桁を保持することを意味する。

if(dis>=50)
{delay(500);}
else if(dis<50 & dis>20) {
    for(int i=0;i<2;i++){
    digitalWrite(Buzzer,HIGH);
    delay(50);
    digitalWrite(Buzzer,LOW);
    delay(200);
    }
}
else if(dis<=20){
    for(int i=0;i<5;i++){
    digitalWrite(Buzzer,HIGH);
    delay(50);
    digitalWrite(Buzzer,LOW);
    delay(50);
    }
}

この判定条件でブザーの音をコントロールします。 距離の違いにより、音の周波数が異なる3つのケースに分けられます。 遅延の合計値は500なので、どのケースも超音波センサに500msの間隔を与えることができる。

Python言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 3.1.3_ReversingAlarm.py

コードが実行されると、超音波センサーモジュールが障害物までの距離を検出し、 LCD1602に距離に関する情報を表示する。 また、ブザーは距離とともに周波数が変化する警告音を発する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import LCD1602
import time
import RPi.GPIO as GPIO

TRIG = 16
ECHO = 18
BUZZER = 11

def lcdsetup():
LCD1602.init(0x27, 1)   # init(slave address, background light)
LCD1602.clear()
LCD1602.write(0, 0, 'Ultrasonic Starting')
LCD1602.write(1, 1, 'By SunFounder')
time.sleep(2)

def setup():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)
GPIO.setup(BUZZER, GPIO.OUT, initial=GPIO.LOW)
lcdsetup()

def distance():
GPIO.output(TRIG, 0)
time.sleep(0.000002)

GPIO.output(TRIG, 1)
time.sleep(0.00001)
GPIO.output(TRIG, 0)

while GPIO.input(ECHO) == 0:
    a = 0
time1 = time.time()
while GPIO.input(ECHO) == 1:
    a = 1
time2 = time.time()

during = time2 - time1
return during * 340 / 2 * 100

def destroy():
GPIO.output(BUZZER, GPIO.LOW)
GPIO.cleanup()
LCD1602.clear()

def loop():
while True:
    dis = distance()
    print (dis, 'cm')
    print ('')
    GPIO.output(BUZZER, GPIO.LOW)
    if (dis > 400):
        LCD1602.clear()
        LCD1602.write(0, 0, 'Error')
        LCD1602.write(3, 1, 'Out of range')
        time.sleep(0.5)
    else:
        LCD1602.clear()
        LCD1602.write(0, 0, 'Distance is')
        LCD1602.write(5, 1, str(round(dis,2)) +' cm')
        if(dis>=50):
            time.sleep(0.5)
        elif(dis<50 and dis>20):
            for i in range(0,2,1):
                GPIO.output(BUZZER, GPIO.HIGH)
                time.sleep(0.05)
                GPIO.output(BUZZER, GPIO.LOW)
                time.sleep(0.2)
        elif(dis<=20):
            for i in range(0,5,1):
                GPIO.output(BUZZER, GPIO.HIGH)
                time.sleep(0.05)
                GPIO.output(BUZZER, GPIO.LOW)
                time.sleep(0.05)


if __name__ == "__main__":
setup()
try:
    loop()
except KeyboardInterrupt:
    destroy()

コードの説明

def lcdsetup():
    LCD1602.init(0x27, 1)   # init(slave address, background light)

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(TRIG, GPIO.OUT)
    GPIO.setup(ECHO, GPIO.IN)
    GPIO.setup(BUZZER, GPIO.OUT, initial=GPIO.LOW)
    lcdsetup()

このプログラムでは、以前に使用した部品を総合的に適用する。 ここでは、ブザー、LCD、と超音波を使用する。以前と同じ方法で初期化できる。

dis = distance()
print (dis, 'cm')
print ('')
GPIO.output(BUZZER, GPIO.LOW)
if (dis > 400):
    LCD1602.clear()
    LCD1602.write(0, 0, 'Error')
    LCD1602.write(3, 1, 'Out of range')
    time.sleep(0.5)
else:
    LCD1602.clear()
    LCD1602.write(0, 0, 'Distance is')
    LCD1602.write(5, 1, str(round(dis,2)) +' cm')

ここで、超音波センサーの値を取得し、計算により距離を取得する。距離の値が検出される範囲の値より大きい場合、エラーメッセージがLCDに表示される。 動作値が範囲内にある場合、対応する結果が出力される

LCD1602.write(5, 1, str(round(dis,2)) +' cm')

LCD出力は文字タイプのみをサポートするため、 str() を使用して数値を文字に変換する必要がある。 小数点以下2桁に丸める

if(dis>=50)
{delay(500);}
else if(dis<50 & dis>20) {
    for(int i=0;i<2;i++){
        digitalWrite(Buzzer,HIGH);
        delay(50);
        digitalWrite(Buzzer,LOW);
        delay(200);
        }
    }
    else if(dis<=20){
        for(int i=0;i<5;i++){
        digitalWrite(Buzzer,HIGH);
        delay(50);
        digitalWrite(Buzzer,LOW);
        delay(50);
        }
    }

この判定条件はブザーの音を制御するために使用される。 距離の違いに応じて、3つのケースに分けることができる。 この場合、音の周波数は異なる。遅延の合計値は500であるため、 すべてのケースで超音波センサーに500msの間隔を提供できる。

現象画像
_images/image243.jpeg

3.1.4 スマートファン

前書き

このコースでは、モーター、ボタン、サーミスターを使用して、 風速が調整可能な手動+自動のスマートファンを作成する。

部品
_images/list_Smart_Fan.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

GPIO5

Pin 29

21

5

GPIO6

Pin 31

22

6

GPIO13

Pin 33

23

13

_images/Schematic_three_one4.png
実験手順

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

Smart Fan_bb

注釈

電源モジュールはキットの9Vバッテリーバックルで9Vバッテリーを適用できる。 電源モジュールのジャンパキャップをブレッドボードの5Vバスストリップに挿入する。

\_MG_2084
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.4/

ステップ3: コンパイルする。

gcc 3.1.4_SmartFan.c -lwiringPi -lm

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードが実行された後、ボタンを押してファンを起動する。 押すたびに、1つのレベルが上下に調整される。5 種類のレベルがある:0〜4。 4番目のレベルに設定してボタンを押すと、ファンの風速が 0 で動作が停止する。

温度が2℃以上上昇または下降すると、速度は自動的に1グレード速くまたは遅くなる。

コードの説明

int temperture(){
    unsigned char analogVal;
    double Vr, Rt, temp, cel, Fah;
    analogVal = get_ADC_Result(0);
    Vr = 5 * (double)(analogVal) / 255;
    Rt = 10000 * (double)(Vr) / (5 - (double)(Vr));
    temp = 1 / (((log(Rt/10000)) / 3950)+(1 / (273.15 + 25)));
    cel = temp - 273.15;
    Fah = cel * 1.8 +32;
    int t=cel;
    return t;
}

Temperature() は、ADC0834によって読み取られたサーミスタ値を温度値に変換することによって機能します。 詳細については、 2.2.2 サーミスタ を参照してください。

int motor(int level){
    if(level==0){
        digitalWrite(MotorEnable,LOW);
        return 0;
    }
    if (level>=4){
        level =4;
    }
    digitalWrite(MotorEnable,HIGH);
    softPwmWrite(MotorPin1, level*25);
    return level;
}

この機能は、モーターの回転速度を制御する。 レベル の範囲:0〜4 (レベル 0 は動作中のモーターを停止する)。 1つのレベル調整は風速の 25% の変化を表す。

int main(void)
{
    setup();
    int currentState,lastState=0;
    int level = 0;
    int currentTemp,markTemp=0;
    while(1){
        currentState=digitalRead(BtnPin);
        currentTemp=temperture();
        if (currentTemp<=0){continue;}
        if (currentState==1&&lastState==0){
            level=(level+1)%5;
            markTemp=currentTemp;
            delay(500);
        }
        lastState=currentState;
        if (level!=0){
            if (currentTemp-markTemp<=-2){
                level=level-1;
                markTemp=currentTemp;
            }
            if (currentTemp-markTemp>=2){
                level=level+1;
                markTemp=currentTemp;
            }
        }
        level=motor(level);
    }
    return 0;
}

関数 main() 上 には、次のようにプログラムプロセス全体が含まれている:

  1. ボタンの状態と現在の温度を常に読み取る。

  2. ボタンを押すごとに、レベル+1 になり、同時に温度が更新される。レ れベル 範囲 1〜4 。

  3. ファンが作動すると(レベルは 0ではない )、温度は検出中である。2℃+ 以上変更すると、レベルが上下に変化する。

  4. モーターは レベル に応じて回転速度を変更する。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: 実行する。

sudo python3 3.1.4_SmartFan.py

コードが実行された後、ボタンを押してファンを起動する。 押すたびに、1つのレベルが上下に調整される。5 種類のレベルがある:0〜4。 4番目のレベルに設定してボタンを押すと、ファンの風速が 0 で動作が停止する。

温度が2℃以上上昇または下降すると、速度は自動的に1グレード速くまたは遅くなる。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import ADC0834
import math

# Set up pins
MotorPin1   = 5
MotorPin2   = 6
MotorEnable = 13
BtnPin  = 22


def setup():
    global p_M1,p_M2
    ADC0834.setup()
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(MotorPin1, GPIO.OUT)
    GPIO.setup(MotorPin2, GPIO.OUT)
    p_M1=GPIO.PWM(MotorPin1,2000)
    p_M2=GPIO.PWM(MotorPin2,2000)
    p_M1.start(0)
    p_M2.start(0)
    GPIO.setup(MotorEnable, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(BtnPin, GPIO.IN)

def temperature():
    analogVal = ADC0834.getResult()
    Vr = 5 * float(analogVal) / 255
    Rt = 10000 * Vr / (5 - Vr)
    temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
    Cel = temp - 273.15
    Fah = Cel * 1.8 + 32
    return Cel

def motor(level):
    if level == 0:
        GPIO.output(MotorEnable, GPIO.LOW)
        return 0
    if level>=4:
        level = 4
    GPIO.output(MotorEnable, GPIO.HIGH)
    p_M1.ChangeDutyCycle(level*25)
    return level


def main():
    lastState=0
    level=0
    markTemp = temperature()
    while True:
        currentState =GPIO.input(BtnPin)
        currentTemp=temperature()
        if currentState == 1 and lastState == 0:
            level=(level+1)%5
            markTemp = currentTemp
            time.sleep(0.5)
        lastState=currentState
        if level!=0:
            if currentTemp-markTemp <= -2:
                level = level -1
                markTemp=currentTemp
            if currentTemp-markTemp >= 2:
                level = level +1
                markTemp=currentTemp
        level = motor(level)


def destroy():
    GPIO.output(MotorEnable, GPIO.LOW)
    p_M1.stop()
    p_M2.stop()
    GPIO.cleanup()

if __name__ == '__main__':
    setup()
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの説明

def temperature():
    analogVal = ADC0834.getResult()
    Vr = 5 * float(analogVal) / 255
    Rt = 10000 * Vr / (5 - Vr)
    temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
    Cel = temp - 273.15
    Fah = Cel * 1.8 + 32
    return Cel

Temperature() は、ADC0834 によって読み取られたサーミスタ値を温度値に変換することによって機能します。 詳細については、 2.2.2 サーミスタ を参照してください。

def motor(level):
    if level == 0:
        GPIO.output(MotorEnable, GPIO.LOW)
        return 0
    if level>=4:
        level = 4
    GPIO.output(MotorEnable, GPIO.HIGH)
    p_M1.ChangeDutyCycle(level*25)
    return level

この機能はモーターの回転速度を制御する。 レバー の範囲: 0〜4 (レベル 0 は動作中のモーターを停止する)。 1つのレベル調整は風速の 25% の変化を表す。

def main():
    lastState=0
    level=0
    markTemp = temperature()
    while True:
        currentState =GPIO.input(BtnPin)
        currentTemp=temperature()
        if currentState == 1 and lastState == 0:
            level=(level+1)%5
            markTemp = currentTemp
            time.sleep(0.5)
        lastState=currentState
        if level!=0:
            if currentTemp-markTemp <= -2:
                level = level -1
                markTemp=currentTemp
            if currentTemp-markTemp >= 2:
                level = level +1
                markTemp=currentTemp
        level = motor(level)

関数 main() 上 には、次のようにプログラムプロセス全体が含まれている:

  1. ボタンの状態と現在の温度を常に読み取る。

  2. ボタンを押すごとに、レベル+1 になり、同時に温度が更新される。レ れベル 範囲 1〜4 。

  3. ファンが作動すると(レベルは 0ではない )、温度は検出中である。2℃+ 以上変更すると、レベルが上下に変化する。

  4. モーターは レベル に応じて回転速度を変更する。

現象画像
_images/image246.png

3.1.5 バッテリーインジケーター

前書き

このコースでは、LEDバーグラフにバッテリーレベルを視覚的に表示できるバッテリー指示装置を作成する。

部品
_images/list_Battery_Indicator.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO25

Pin 22

6

25

GPIO12

Pin 32

26

12

GPIO16

Pin 36

27

16

GPIO20

Pin 38

28

20

GPIO21

Pin 40

29

21

GPIO5

Pin 29

21

5

GPIO6

Pin 31

22

6

GPIO13

Pin 33

23

13

GPIO19

Pin 35

24

19

GPIO26

Pin 37

25

26

_images/Schematic_three_one5.png
実験手順

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

电量计_bb
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.5/

ステップ3: コードをコンパイルする。

gcc 3.1.5_BatteryIndicator.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

プログラムの実行後、ADC0834の3番目のピンとGNDに個別にリード線を配線し、 それらを別々にバッテリーの2つの極に導く。 LEDバーグラフの対応するLEDが点灯し、電力レベルが表示される(測定範囲:0〜5V)。

コードの説明

void LedBarGraph(int value){
    for(int i=0;i<10;i++){
        digitalWrite(pins[i],HIGH);
    }
    for(int i=0;i<value;i++){
        digitalWrite(pins[i],LOW);
    }
}

この機能は、LED棒グラフの10個のLEDの点灯/消灯を制御するために機能する。 これらの10個のLEDを最初にオフにするために高レベルを指定し、 次に受信したアナログ値を変更することでいくつのLEDを点灯させるかを決定する。

int main(void)
{
    uchar analogVal;
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    pinMode(ADC_CS,  OUTPUT);
    pinMode(ADC_CLK, OUTPUT);
    for(int i=0;i<10;i++){       //make led pins' mode is output
        pinMode(pins[i], OUTPUT);
        digitalWrite(pins[i],HIGH);
    }
    while(1){
        analogVal = get_ADC_Result(0);
        LedBarGraph(analogVal/25);
        delay(100);
    }
    return 0;
}

analogVal は、さまざまな電圧値(0-5V)で値(0-255)を生成する。 たとえば、バッテリーで3Vが検出されると、対応する値 152 が電圧計に表示される。

LED棒グラフの10個のLEDはanalogVal測定値を表示するために使用される。255/10 = 25。 したがって、25ごとにアナログ値が増加し、もう1つのLEDが点灯する。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 3.1.5_BatteryIndicator.py

プログラムの実行後、ADC0834の3番目のピンとGNDに個別にリード線を配線し、 それらを別々にバッテリーの2つの極に導く。 LEDバーグラフの対応するLEDが点灯し、電力レベルが表示される(測定範囲:0〜5V)。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import ADC0834
import time

ledPins = [25, 12, 16, 20, 21, 5, 6, 13, 19, 26]

def setup():
    GPIO.setmode(GPIO.BCM)
    ADC0834.setup()
    for i in ledPins:
        GPIO.setup(i, GPIO.OUT)
        GPIO.output(i, GPIO.HIGH)

def LedBarGraph(value):
    for i in ledPins:
        GPIO.output(i,GPIO.HIGH)
    for i in range(value):
        GPIO.output(ledPins[i],GPIO.LOW)

def destroy():
    GPIO.cleanup()

def loop():
    while True:
        analogVal = ADC0834.getResult()
        LedBarGraph(int(analogVal/25))

if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()

コードの説明

def LedBarGraph(value):
    for i in ledPins:
        GPIO.output(i,GPIO.HIGH)
    for i in range(value):
        GPIO.output(ledPins[i],GPIO.LOW)

この機能は、LED棒グラフの 10 個のLEDの点灯/消灯を制御するために機能する。 これらの 10 個のLEDを最初に オフ にするために高レベルを指定し、 次に受信したアナログ値を変更することでいくつのLEDを点灯させるかを決定する。

def loop():
    while True:
        analogVal = ADC0834.getResult()
        LedBarGraph(int(analogVal/25))

analogValは、さまざまな電圧値(0-5V)で値(0-255)を生成する。 たとえば、バッテリーで3Vが検出されると、対応する値 152 が電圧計に表示される。

LED棒グラフの10個のLEDはanalogVal測定値を表示するために使用される。 255/10 = 25。したがって、25ごとにアナログ値が増加し、もう1つのLEDが点灯する。

現象画像
_images/image249.jpeg

3.1.6 モーション制御

前書き

このレッスンでは、簡単なモーション検知と制御装置を作成する。 MPU6050はセンサーとして使用され、ステッピングモーターは制御装置として使用される。 MPU6050をグローブに取り付けた状態で、手首を回すことでステッピングモーターを制御できる。

部品
_images/list_Motion_Control.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

SDA1

Pin 3

SCL1

Pin 5

_images/Schematic_three_one6.png
実験手順

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

3.1.6 Motion Control_bb
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.6/

ステップ3: コードをコンパイルする。

gcc 3.1.6_MotionControl.c -lwiringPi -lm

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードが実行されている間、もし mpu6050 のチルト角度が Y-axis 45 ℃より大きい場合、 ステッピングモーターは反時計回りに回転します。 -45 ℃未満の場合、ステッピングモーターは時計回りに回転します。

コードの説明

double mpu6050(){
    acclX = read_word_2c(0x3B);
    acclY = read_word_2c(0x3D);
    acclZ = read_word_2c(0x3F);
    acclX_scaled = acclX / 16384.0;
    acclY_scaled = acclY / 16384.0;
    acclZ_scaled = acclZ / 16384.0;
    double angle=get_y_rotation(acclX_scaled, acclY_scaled, acclZ_scaled);
    return angle;
}

mpu6050はY軸の方向の傾斜角を取得する。

void rotary(char direction){
    if(direction == 'c'){
        for(int j=0;j<4;j++){
            for(int i=0;i<4;i++)
                {digitalWrite(motorPin[i],0x99>>j & (0x08>>i));}
            delayMicroseconds(stepSpeed);
        }
    }
    else if(direction =='a'){
        for(int j=0;j<4;j++){
            for(int i=0;i<4;i++)
                {digitalWrite(motorPin[i],0x99<<j & (0x80>>i));}
            delayMicroseconds(stepSpeed);
        }
    }
}

受信方向 キー が「c」の場合、ステッピングモーターは時計回りに回転します。 キー が「a 」の場合、 モーターは反時計回りに回転します。 ステッピングモーターの回転方向の計算の詳細については 1.3.3 ステッピングモーター を参照してください。

int main()
{
    setup();
    double angle;
    while(1) {
        angle = mpu6050();
        if (angle >=45){rotary('a');}
        else if (angle<=-45){rotary('c');}
    }
    return 0;
}

Y軸方向の傾斜角は mpu6050 から読み取られ、45 ℃より大きい場合、 ステッピングモーターは反時計回りに回転する。 -45 ℃未満の場合、ステッピングモーターは時計回りに回転する。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 3.1.6_MotionControl.py

コードの実行中に、Y軸上の mpu6050 の傾斜角が 45℃ より大きい場合、 ステッピングモーターは反時計回りに回転する。 -45℃ 未満の場合、ステッピングモーターは時計回りに回転する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import smbus
import math
import time



# Power management registers
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

bus = smbus.SMBus(1)
address = 0x68
bus.write_byte_data(address, power_mgmt_1, 0)

#Stepper motor pins
motorPin = (18,23,24,25)
rolePerMinute =15
stepsPerRevolution = 2048
stepSpeed = (60/rolePerMinute)/stepsPerRevolution

#mpu6050
def read_byte(adr):
    return bus.read_byte_data(address, adr)

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val

def dist(a,b):
    return math.sqrt((a*a)+(b*b))

def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)

def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)

def mpu6050():
    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)
    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0
    angle=get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)
    return angle

#Stepper Motor
def rotary(direction):
    if(direction == 'c'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99>>j & (0x08>>i))
            time.sleep(stepSpeed)

    elif(direction == 'a'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99<<j & (0x80>>i))
            time.sleep(stepSpeed)


def setup():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    for i in motorPin:
        GPIO.setup(i, GPIO.OUT)


def loop():
    while True:
        angle=mpu6050()
        if angle >=45 :
            rotary('a')
        elif angle <=-45:
            rotary('c')

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コードの説明

def mpu6050():
    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)
    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0
    angle=get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)
    return angle

mpu6050はY軸の方向の傾斜角を取得する。

def rotary(direction):
    if(direction == 'c'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99>>j & (0x08>>i))
            time.sleep(stepSpeed)

    elif(direction == 'a'):
        for j in range(4):
            for i in range(4):
                GPIO.output(motorPin[i],0x99<<j & (0x80>>i))
            time.sleep(stepSpeed)

受信方向 キー が「c」の場合、ステッピングモーターは時計回りに回転します。 キー が「a 」の場合、モーターは反時計回りに回転します。 ステッピングモーターの回転方向の計算の詳細については、 1.3.3 ステッピングモーター を参照してください。

def loop():
    while True:
        angle=mpu6050()
        if angle >=45 :
            rotary('a')
        elif angle <=-45:
            rotary('c')

mpu6050 から Y 軸方向の傾斜角を読み取り、45°C より大きい場合は、 rotary() を呼び出して、 ステッピング モーターを反時計回りに回転させます。 -45°C 未満の場合、ステッピング モーターは時計回りに回転します。

現象画像
_images/image252.jpeg

3.1.7 信号機

前書き

このプロジェクトでは、3色のLEDを使用して交通信号の変化を実現し、 4桁の7セグメントディスプレイを使用して各交通状態のタイミングを表示する。

部品
_images/list_Traffic_Light.png
回路図

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

GPIO25

Pin 22

6

25

SPICE0

Pin 24

10

8

SPICE1

Pin 26

11

7

_images/Schematic_three_one7.png
実験手順

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

_images/image254.png
C言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.7/

ステップ3: コンパイルする。

gcc 3.1.7_TrafficLight.c -lwiringPi

ステップ4: 実行する。

sudo ./a.out

コードが実行されると、LEDは交通信号の色の変化をシミュレートする。 まず、赤色のLEDが60秒間点灯し、それから緑色のLEDが30秒間点灯し、最後に、黄色のLEDが5秒間点灯する。 その後、赤いLEDが60秒間再び点灯する。 このようにして、この一連のアクションは繰り返し実行される。

コードの説明

#define     SDI     5
#define     RCLK    4
#define     SRCLK    1

const int placePin[] = {12, 3, 2, 0};
unsigned char number[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

void pickDigit(int digit);
void hc595_shift(int8_t data);
void clearDisplay();
void display();

これらのコードは、4桁7セグメントディスプレイの数値表示機能を実現するために使用されます。 詳細については、ドキュメントの 1.1.5 4桁7セグメントディスプレイ を参照してください。 ここでは、コードを使用して信号時間のカウントダウンを表示します。

const int ledPin[]={6,10,11};

int colorState = 0;

void lightup()
{
    for(int i=0;i<3;i++){
        digitalWrite(ledPin[i],HIGH);
    }
    digitalWrite(ledPin[colorState],LOW);
}

コードはLEDのオンとオフを切り替えるために使用される。

int greenLight = 30;
int yellowLight = 5;
int redLight = 60;
int colorState = 0;
char *lightColor[]={"Red","Green","Yellow"};
int counter = 60;

void timer(int  timer1){       //Timer function
    if(timer1 == SIGALRM){
        counter --;
        alarm(1);
        if(counter == 0){
            if(colorState == 0) counter = greenLight;
            if(colorState == 1) counter = yellowLight;
            if(colorState == 2) counter = redLight;
            colorState = (colorState+1)%3;
        }
        printf("counter : %d \t light color: %s \n",counter,lightColor[colorState]);
    }
}

コードは、タイマーのオンとオフを切り替えるために使用されます。 詳細については、 1.1.5 4桁7セグメントディスプレイ を参照してください。 ここで、タイマーがゼロに戻ると、 colorState が切り替えられてLEDが切り替わり、タイマーが新しい値に割り当てられます。

void loop()
{
    while(1){
    display();
    lightup();
    }
}

int main(void)
{
    //…
    signal(SIGALRM,timer);
    alarm(1);
    loop();
    return 0;
}

タイマーは main() 関数で始まる。 loop() 関数では、 while(1) loopを使用して、4桁7セグメントとLEDの関数を呼び出す。

Python言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 3.1.7_TrafficLight.py

コードが実行されると、LEDは交通信号の色の変化をシミュレートする。 まず、赤色のLEDが60秒間点灯し、それから緑色のLEDが30秒間点灯し、最後に、黄色のLEDが5秒間点灯する。 その後、赤いLEDが60秒間再び点灯する。このようにして、この一連のアクションは繰り返し実行される。 一方、4桁の7セグメントディスプレイには、カウントダウン時間が連続して表示される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import threading

#define the pins connect to 74HC595
SDI   = 24      #serial data input(DS)
RCLK  = 23     #memory clock input(STCP)
SRCLK = 18      #shift register clock input(SHCP)
number = (0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90)

placePin = (10,22,27,17)
ledPin =(25,8,7)

greenLight = 30
yellowLight = 5
redLight = 60
lightColor=("Red","Green","Yellow")

colorState=0
counter = 60
timer1 = 0


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)
    for pin in ledPin:
        GPIO.setup(pin,GPIO.OUT)
    global timer1
    timer1 = threading.Timer(1.0,timer)
    timer1.start()

def clearDisplay():
    for i 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):
    for i in placePin:
        GPIO.output(i,GPIO.LOW)
    GPIO.output(placePin[digit], GPIO.HIGH)

def timer():        #timer function
    global counter
    global colorState
    global timer1
    timer1 = threading.Timer(1.0,timer)
    timer1.start()
    counter-=1
    if (counter is 0):
        if(colorState is 0):
            counter= greenLight
        if(colorState is 1):
            counter=yellowLight
        if (colorState is 2):
            counter=redLight
        colorState=(colorState+1)%3
    print ("counter : %d    color: %s "%(counter,lightColor[colorState]))

def lightup():
    global colorState
    for i in range(0,3):
        GPIO.output(ledPin[i], GPIO.HIGH)
    GPIO.output(ledPin[colorState], GPIO.LOW)

def display():
    global counter

    a = counter % 10000//1000 + counter % 1000//100
    b = counter % 10000//1000 + counter % 1000//100 + counter % 100//10
    c = counter % 10000//1000 + counter % 1000//100 + counter % 100//10 + counter % 10

    if (counter % 10000//1000 == 0):
        clearDisplay()
    else:
        clearDisplay()
        pickDigit(3)
        hc595_shift(number[counter % 10000//1000])

    if (a == 0):
        clearDisplay()
    else:
        clearDisplay()
        pickDigit(2)
        hc595_shift(number[counter % 1000//100])

    if (b == 0):
        clearDisplay()
    else:
        clearDisplay()
        pickDigit(1)
        hc595_shift(number[counter % 100//10])

    if(c == 0):
        clearDisplay()
    else:
        clearDisplay()
        pickDigit(0)
        hc595_shift(number[counter % 10])

def loop():
    while True:
        display()
        lightup()

def destroy():   # When "Ctrl+C" is pressed, the function is executed.
    global timer1
    GPIO.cleanup()
    timer1.cancel()      #cancel the timer

if __name__ == '__main__': # Program starting from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コードの説明

SDI   = 24      #serial data input(DS)
RCLK  = 23     #memory clock input(STCP)
SRCLK = 18      #shift register clock input(SHCP)
number = (0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90)
placePin = (10,22,27,17)

def clearDisplay():
def hc595_shift(data):
def pickDigit(digit):
def display():

これらのコードは、4桁7セグメントの数値表示機能を実現するために使用されます。 詳細については、ドキュメントの 1.1.5 4桁7セグメントディスプレイ を参照してください。 ここでは、コードを使用して信号時間のカウントダウンを表示します。

ledPin =(25,8,7)
colorState=0

def lightup():
    global colorState
    for i in range(0,3):
        GPIO.output(ledPin[i], GPIO.HIGH)
    GPIO.output(ledPin[colorState], GPIO.LOW)

コードはLEDのオンとオフを切り替えるために使用される。

greenLight = 30
yellowLight = 5
redLight = 60
lightColor=("Red","Green","Yellow")

colorState=0
counter = 60
timer1 = 0

def timer():        #timer function
    global counter
    global colorState
    global timer1
    timer1 = threading.Timer(1.0,timer)
    timer1.start()
    counter-=1
    if (counter is 0):
        if(colorState is 0):
            counter= greenLight
        if(colorState is 1):
            counter=yellowLight
        if (colorState is 2):
            counter=redLight
        colorState=(colorState+1)%3
    print ("counter : %d    color: %s "%(counter,lightColor[colorState]))

コードは、タイマーのオンとオフを切り替えるために使用されます。 詳細については、 1.1.5 4桁7セグメントディスプレイ を参照してください。 ここで、タイマーがゼロに戻ると、 colorState が切り替えられてLEDが切り替わり、タイマーが新しい値に割り当てられます。

def setup():
    # ...
    global timer1
    timer1 = threading.Timer(1.0,timer)
    timer1.start()

def loop():
    while True:
        display()
        lightup()

def destroy():   # When "Ctrl+C" is pressed, the function is executed.
    global timer1
    GPIO.cleanup()
    timer1.cancel()      #cancel the timer

if __name__ == '__main__': # Program starting from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

setup() 関数で、タイマーを開始する。 loop() 関数では、 while True が使用される:4-桁の7-セグメントとLEDの相対関数を循環的に呼び出す。

現象画像
_images/IMG_8319.jpg

3.1.8 過熱モニター

前書き

回路の過熱が発生したときに警報装置とタイムリーな自動電源切断を希望する場合は、 工場などのさまざまな状況に適用される過熱監視装置を作成することができる。 このレッスンでは、サーミスタ、ジョイスティック、ブザー、LED、とLCDを使用して、 しきい値が調整可能なスマートな温度監視装置を作成する。

部品
_images/list_Overheat_Monitor.png _images/list_Overheat_Monitor2.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO22

Pin15

3

22

GPIO23

Pin16

4

23

GPIO24

Pin18

5

24

SDA1

Pin 3

SCL1

Pin 5

_images/Schematic_three_one8.png
実験手順

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

Overheat Monitor_bb
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.8/

ステップ3: コードをコンパイルする。

gcc 3.1.8_OverheatMonitor.c -lwiringPi -lm

ステップ4: EXEファイルを実行する。

sudo ./a.out

コードが実行されると、現在の温度と高温のしきい値 40 が I2C LCD1602 に表示される。 現在の温度がしきい値よりも大きい場合、ブザーとLEDが起動して警告を発する。

ここの ジョイスティック は高温のしきい値を調整するために使用される。 ジョイスティック をX軸とY軸の方向に切り替えると、現在の高温しきい値を調整できる(上/下)。 ジョイスティック をもう一度押して、しきい値を初期値にリセットする。

コードの説明

int get_joystick_value(){
    uchar x_val;
    uchar y_val;
    x_val = get_ADC_Result(1);
    y_val = get_ADC_Result(2);
    if (x_val > 200){
        return 1;
    }
    else if(x_val < 50){
        return -1;
    }
    else if(y_val > 200){
        return -10;
    }
    else if(y_val < 50){
        return 10;
    }
    else{
        return 0;
    }
}

この関数は、XとYの値を読み取る。X>200 の場合、「1」が返される。 X<50 の場合、「-1」が返される。 y>200 の場合、「-10」を返し、 y<50 の場合、「10」を返す。

void upper_tem_setting(){
    write(0, 0, "Upper Adjust:");
    int change = get_joystick_value();
    upperTem = upperTem + change;
    char str[6];
    snprintf(str,3,"%d",upperTem);
write(0,1,str);
int len;
  len = strlen(str);
  write(len,1,"             ");
    delay(100);
}

この機能は、しきい値を調整し、I2C LCD1602に表示するために使用される。

double temperature(){
    unsigned char temp_value;
    double Vr, Rt, temp, cel, Fah;
    temp_value = get_ADC_Result(0);
    Vr = 5 * (double)(temp_value) / 255;
    Rt = 10000 * (double)(Vr) / (5 - (double)(Vr));
    temp = 1 / (((log(Rt/10000)) / 3950)+(1 / (273.15 + 25)));
    cel = temp - 273.15;
    Fah = cel * 1.8 +32;
    return cel;
}

ADC0834 の CH0 (サーミスタ)のアナログ値を読み取り、温度値に変換する。

void monitoring_temp(){
    char str[6];
    double cel = temperature();
    snprintf(str,6,"%.2f",cel);
    write(0, 0, "Temp: ");
    write(6, 0, str);
    snprintf(str,3,"%d",upperTem);
    write(0, 1, "Upper: ");
    write(7, 1, str);
    delay(100);
    if(cel >= upperTem){
        digitalWrite(buzzPin, HIGH);
        digitalWrite(LedPin, HIGH);
    }
    else if(cel < upperTem){
        digitalWrite(buzzPin, LOW);
        digitalWrite(LedPin, LOW);
    }
}

コードが実行されると、現在の温度と高温のしきい値 40 が I2C LCD1602 に表示される。 現在の温度がしきい値よりも大きい場合、ブザーとLEDが起動して警告を発する。

int main(void)
{
    setup();
    int lastState =1;
    int stage=0;
    while (1)
    {
        int currentState = digitalRead(Joy_BtnPin);
        if(currentState==1 && lastState == 0){
            stage=(stage+1)%2;
            delay(100);
            lcd_clear();
        }
        lastState=currentState;
        if (stage==1){
            upper_tem_setting();
        }
        else{
            monitoring_temp();
        }
    }
    return 0;
}

関数 main() には、次のようにプログラムプロセス全体が含まれる:

  • プログラムが開始すると、 ステージ の初期値は 0 になり、現在の温度と高温しきい値 40 が I2C LCD1602 に表示される。現在の温度がしきい値よりも大きい場合、ブザーとLEDが起動して警告を出す。

  • ジョイスティックを押すと、 ステージ が 1 になり、高温しきい値を調整できる。ジョイスティックをX軸とY軸の方向に切り替えると、現在のしきい値を調整(上下)できる。ジョイスティックをもう一度押して、しきい値を初期値にリセットする。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 3.1.8_OverheatMonitor.py

コードが実行されると、現在の温度と高温のしきい値 40 が I2C LCD1602 に表示される。 現在の温度がしきい値よりも大きい場合、ブザーとLEDが起動して警告を発する。

ここの ジョイスティック は高温のしきい値を調整するために使用される。 ジョイスティック をX軸とY軸の方向に切り替えると、現在の高温しきい値を調整できる(上/下)。 ジョイスティック をもう一度押して、しきい値を初期値にリセットする。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import LCD1602
import RPi.GPIO as GPIO
import ADC0834
import time
import math

Joy_BtnPin = 22
buzzPin = 23
ledPin = 24


upperTem = 40

def setup():
    ADC0834.setup()
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(ledPin, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(buzzPin, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(Joy_BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    LCD1602.init(0x27, 1)

def get_joystick_value():
    x_val = ADC0834.getResult(1)
    y_val = ADC0834.getResult(2)
    if(x_val > 200):
        return 1
    elif(x_val < 50):
        return -1
    elif(y_val > 200):
        return -10
    elif(y_val < 50):
        return 10
    else:
        return 0

def upper_tem_setting():
    global upperTem
    LCD1602.write(0, 0, 'Upper Adjust: ')
    change = int(get_joystick_value())
    upperTem = upperTem + change
    strUpperTem = str(upperTem)
    LCD1602.write(0, 1, strUpperTem)
    LCD1602.write(len(strUpperTem),1, '              ')
    time.sleep(0.1)

def temperature():
    analogVal = ADC0834.getResult()
    Vr = 5 * float(analogVal) / 255
    Rt = 10000 * Vr / (5 - Vr)
    temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
    Cel = temp - 273.15
    Fah = Cel * 1.8 + 32
    return round(Cel,2)

def monitoring_temp():
    global upperTem
    Cel=temperature()
    LCD1602.write(0, 0, 'Temp: ')
    LCD1602.write(0, 1, 'Upper: ')
    LCD1602.write(6, 0, str(Cel))
    LCD1602.write(7, 1, str(upperTem))
    time.sleep(0.1)
    if Cel >= upperTem:
        GPIO.output(buzzPin, GPIO.HIGH)
        GPIO.output(ledPin, GPIO.HIGH)
    else:
        GPIO.output(buzzPin, GPIO.LOW)
        GPIO.output(ledPin, GPIO.LOW)

def loop():
    lastState=1
    stage=0
    while True:
        currentState=GPIO.input(Joy_BtnPin)
        if currentState==1 and lastState ==0:
            stage=(stage+1)%2
            time.sleep(0.1)
            LCD1602.clear()
        lastState=currentState
        if stage == 1:
            upper_tem_setting()
        else:
            monitoring_temp()

def destroy():
    LCD1602.clear()
    ADC0834.destroy()
    GPIO.cleanup()

if __name__ == '__main__':     # Program start from here
    try:
        setup()
        while True:
            loop()
    except KeyboardInterrupt:   # When 'Ctrl+C' is pressed, the program destroy() will be executed.
        destroy()

コードの説明

def get_joystick_value():
    x_val = ADC0834.getResult(1)
    y_val = ADC0834.getResult(2)
    if(x_val > 200):
        return 1
    elif(x_val < 50):
        return -1
    elif(y_val > 200):
        return -10
    elif(y_val < 50):
        return 10
    else:
        return 0

この関数は、XとYの値を読み取る。 X>200 の場合、「1」が返される。 X<50 の場合、「-1」が返される。 y>200 の場合、「-10」を返し、 y<50 の場合、「10」を返す。

def upper_tem_setting():
    global upperTem
    LCD1602.write(0, 0, 'Upper Adjust: ')
    change = int(get_joystick_value())
    upperTem = upperTem + change
LCD1602.write(0, 1, str(upperTem))
LCD1602.write(len(strUpperTem),1, '              ')
    time.sleep(0.1)

この機能は、しきい値を調整し、I2C LCD1602に表示するために使用される。

def temperature():
    analogVal = ADC0834.getResult()
    Vr = 5 * float(analogVal) / 255
    Rt = 10000 * Vr / (5 - Vr)
    temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
    Cel = temp - 273.15
    Fah = Cel * 1.8 + 32
    return round(Cel,2)

ADC0834 の CH0 (サーミスタ)のアナログ値を読み取り、温度値に変換する。

def monitoring_temp():
    global upperTem
    Cel=temperature()
    LCD1602.write(0, 0, 'Temp: ')
    LCD1602.write(0, 1, 'Upper: ')
    LCD1602.write(6, 0, str(Cel))
    LCD1602.write(7, 1, str(upperTem))
    time.sleep(0.1)
    if Cel >= upperTem:
        GPIO.output(buzzPin, GPIO.HIGH)
        GPIO.output(ledPin, GPIO.HIGH)
    else:
        GPIO.output(buzzPin, GPIO.LOW)
        GPIO.output(ledPin, GPIO.LOW)

コードが実行されると、現在の温度と高温のしきい値 40 が I2C LCD1602 に表示される。 現在の温度がしきい値よりも大きい場合、ブザーとLEDが起動して警告を発する。

def loop():
    lastState=1
    stage=0
    while True:
        currentState=GPIO.input(Joy_BtnPin)
        if currentState==1 and lastState ==0:
            stage=(stage+1)%2
            time.sleep(0.1)
            LCD1602.clear()
        lastState=currentState
        if stage == 1:
            upper_tem_setting()
        else:
            monitoring_temp()

関数 main() には、次のようにプログラムプロセス全体が含まれる:

  • プログラムが開始すると、 ステージ の初期値は 0 になり、現在の温度と高温しきい値 40 が I2C LCD1602 に表示される。現在の温度がしきい値よりも大きい場合、ブザーとLEDが起動して警告を出す。

  • ジョイスティックを押すと、ステージ が 1 になり、高温しきい値を調整できる。ジョイスティックをX軸とY軸の方向に切り替えると、現在の高温しきい値を調整(上下)できる。ジョイスティックをもう一度押して、しきい値を初期値にリセットする。

現象画像
_images/image259.jpeg

3.1.9 パスワードロック

前書き

このプロジェクトでは、キーパッドとLCDを使用してコンビネーションロックを作成する。LCDはキーパッドでパスワードを入力するための対応するプロンプトを表示する。パスワードが正しく入力されると、「Correct」と表示される。

このプロジェクトに基づいて、ブザー、LEDなどの電子部品を追加して、パスワード入力にさまざまな実験現象を追加できる。

部品
_images/list_Password_Lock.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

GPIO17

Pin 11

0

17

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

SPIMOSI

Pin 19

12

10

SDA1

Pin 3

SCL1

Pin 5

_images/Schematic_three_one9.png
実験手順

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

3.1.3_PasswordLock_bb_看图王
C言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.9/

ステップ3: コンパイルする。

gcc 3.1.9_PasswordLock.cpp -lwiringPi

ステップ4: 実行する。

sudo ./a.out

コードの実行後、キーパッドを使用してパスワードを入力する。LCD1602に「CORRECT」と表示されている場合、パスワードに問題はない。そうでない場合、「WRONG KEY」が表示される。

コードの説明

#define ROWS  4
#define COLS  4
#define BUTTON_NUM (ROWS * COLS)
#define LENS  4

unsigned char KEYS[BUTTON_NUM] {
'1','2','3','A',
'4','5','6','B',
'7','8','9','C',
'*','0','#','D'};

char password[LENS]={'1','9','8','4'};

ここでは、パスワードLENS、 ストレージマトリックスキーボードキー値配列KEYSと正しいパスワードを保存する配列の長さを定義する。

void keyRead(unsigned char* result);
bool keyCompare(unsigned char* a, unsigned char* b);
void keyCopy(unsigned char* a, unsigned char* b);
void keyPrint(unsigned char* a);
void keyClear(unsigned char* a);
int keyIndexOf(const char value);

マトリックスキーボードコードのサブ機能の宣言があります。 詳細については、このドキュメントの 2.1.5 キーパッド を参照してください。

void write_word(int data);
void send_command(int comm);
void send_data(int data);
void lcdInit();
void clear();
void write(int x, int y, char const data[]);

LCD1062コードのサブ機能の宣言があります。参照してください。 詳細については、このドキュメントの 1.1.7 I2C LCD1602 を参照してください。

while(1){
        keyRead(pressed_keys);
        bool comp = keyCompare(pressed_keys, last_key_pressed);
        ...
                testword[keyIndex]=pressed_keys[0];
                keyIndex++;
                if(keyIndex==LENS){
                    if(check()==0){
                        clear();
                        write(3, 0, "WRONG KEY!");
                        write(0, 1, "please try again");
                        }
                ...

キー値を読み取り、テスト配列テストワードに保存する。保存されているキー値の数が4を超える場合、 パスワードの正確さが自動的に検証され、検証結果がLCDインターフェイスに表示される。

int check(){
    for(int i=0;i<LENS;i++){
        if(password[i]!=testword[i])
        {return 0;}
    }
    return 1;
}

パスワードの正確さを確認してください。 パスワードが正しく入力された場合は1を返し、そうでない場合は0を返す。

Python言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 3.1.9_PasswordLock.py

コードの実行後、キーパッドを使用してパスワードを入力する:1984。LCD1602に「CORRECT」と表示されている場合、 パスワードに問題はない。そうでない場合、「WRONG KEY」が表示される。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import LCD1602

##################### HERE IS THE KEYPAD LIBRARY TRANSPLANTED FROM Arduino ############
#class Key:Define some of the properties of Key
class Keypad():

    def __init__(self, rowsPins, colsPins, keys):
        self.rowsPins = rowsPins
        self.colsPins = colsPins
        self.keys = keys
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

    def read(self):
        pressed_keys = []
        for i, row in enumerate(self.rowsPins):
            GPIO.output(row, GPIO.HIGH)
            for j, col in enumerate(self.colsPins):
                index = i * len(self.colsPins) + j
                if (GPIO.input(col) == 1):
                    pressed_keys.append(self.keys[index])
            GPIO.output(row, GPIO.LOW)
        return pressed_keys

################ EXAMPLE CODE START HERE ################
LENS = 4
password=['1','9','8','4']
testword=['0','0','0','0']
keyIndex=0

def check():
    for i in range(0,LENS):
        if(password[i]!=testword[i]):
            return 0
    return 1

def setup():
    global keypad, last_key_pressed
    rowsPins = [18,23,24,25]
    colsPins = [10,22,27,17]
    keys = ["1","2","3","A",
            "4","5","6","B",
            "7","8","9","C",
            "*","0","#","D"]
    keypad = Keypad(rowsPins, colsPins, keys)
    last_key_pressed = []
    LCD1602.init(0x27, 1)    # init(slave address, background light)
    LCD1602.clear()
    LCD1602.write(0, 0, 'WELCOME!')
    LCD1602.write(2, 1, 'Enter password')
    time.sleep(2)

def destroy():
    LCD1602.clear()
    GPIO.cleanup()

def loop():
    global keyIndex
    global LENS
    global keypad, last_key_pressed
    while(True):
        pressed_keys = keypad.read()
        if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
            LCD1602.clear()
            LCD1602.write(0, 0, "Enter password:")
            LCD1602.write(15-keyIndex,1, pressed_keys)
            testword[keyIndex]=pressed_keys
            keyIndex+=1
            if (keyIndex is LENS):
                if (check() is 0):
                    LCD1602.clear()
                    LCD1602.write(3, 0, "WRONG KEY!")
                    LCD1602.write(0, 1, "please try again")
                else:
                    LCD1602.clear()
                    LCD1602.write(4, 0, "CORRECT!")
                    LCD1602.write(2, 1, "welcome back")
            keyIndex=keyIndex%LENS

        last_key_pressed = pressed_keys
        time.sleep(0.1)

if __name__ == '__main__':     # Program start from here
    try:
        setup()
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the program destroy() will be  executed.
        destroy()

コードの説明

LENS = 4
password=['1','9','8','4']
...
rowsPins = [18,23,24,25]
colsPins = [10,22,27,17]
keys = ["1","2","3","A",
        "4","5","6","B",
        "7","8","9","C",
        "*","0","#","D"]

ここでは、パスワードLENSの長さ、 マトリックスキーボードキーを保存する配列キーと正しいパスワードを保存する配列パスワードを定義する。

class Keypad():
    def __init__(self, rowsPins, colsPins, keys):
        self.rowsPins = rowsPins
        self.colsPins = colsPins
        self.keys = keys
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
...

このクラスは、押されたキーの値を読み取るコードです。 詳細については、このドキュメントの 2.1.5 キーパッド を参照してください。

while(True):
        pressed_keys = keypad.read()
        if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
            LCD1602.clear()
            LCD1602.write(0, 0, "Enter password:")
            LCD1602.write(15-keyIndex,1, pressed_keys)
            testword[keyIndex]=pressed_keys
            keyIndex+=1
...

キー値を読み取り、テスト配列テストワードに保存する。保存されているキー値の数が4を超える場合、パスワードの正確さが自動的に検証され、検証結果がLCDインターフェイスに表示される。

def check():
    for i in range(0,LENS):
        if(password[i]!=testword[i]):
            return 0
    return 1

パスワードの正確さを確認してください。パスワードが正しく入力された場合は1を返し、そうでない場合は0を返す。

現象画像
_images/image263.jpeg

3.1.10 警報ベル

前書き

このコースでは、手動警報装置を作成する。 トグルスイッチをサーミスタまたは感光センサーに交換して、温度警報または光警報を作成できる。

部品
_images/list_Alarm_Bell.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

_images/Schematic_three_one10.png
実験手順

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

Alarm Bell_bb
C言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.10/

ステップ3: コンパイルする。

gcc 3.1.10_AlarmBell.c -lwiringPi -lpthread

ステップ4: 実行。

sudo ./a.out

プログラムが起動すると、トグルスイッチが右に切り替わり、ブザーが警報音を出す。同時に、特定の周波数で赤と緑のLEDが点滅する。

コードの説明

#include <pthread.h>

このコードでは、新しいライブラリ thread.h を使用する。 これは、一般的なスレッドライブラリのセットであり、マルチスレッドを実現できる。 コンパイル時に -lpthread パラメーターを追加して、LEDとブザーを独立して動作させる。

void *ledWork(void *arg){
    while(1)
    {
        if(flag==0){
            pthread_exit(NULL);
        }
        digitalWrite(ALedPin,HIGH);
        delay(500);
        digitalWrite(ALedPin,LOW);
        digitalWrite(BLedPin,HIGH);
        delay(500);
        digitalWrite(BLedPin,LOW);
    }
}

関数 ledWork() は、これら2つのLEDの動作状態を設定するために役立つ: 緑色のLEDを0.5秒間点灯させた後、消灯する。同様に、赤いLEDを0.5秒間点灯させてから消灯する。

void *buzzWork(void *arg){
    while(1)
    {
        if(flag==0){
            pthread_exit(NULL);
        }
        if((note>=800)||(note<=130)){
            pitch = -pitch;
        }
        note=note+pitch;
        softToneWrite(BeepPin,note);
        delay(10);
    }
}

関数 buzzWork() は、ブザーの動作状態を設定するために使用される。 ここでは、周波数を130〜800に設定し、20の間隔で累積・減衰する。

void on(){
    flag = 1;
    if(softToneCreate(BeepPin) == -1){
        printf("setup softTone failed !");
        return;
    }
    pthread_t tLed;
    pthread_create(&tLed,NULL,ledWork,NULL);
    pthread_t tBuzz;
    pthread_create(&tBuzz,NULL,buzzWork,NULL);
}

関数 on() で:

  • 制御スレッドの終了を示すマーク「flag = 1」を定義する。

  • ソフトウェア制御のトーンピン BeepPin を作成する。

  • LEDとブザーが同時に動作できるように、二つの個別のスレッドを作成する。

pthread_t tLed : スレッド tLed を宣言する。

pthread_create(&tLed,NULL,ledWork,NULL) : スレッドを作成し、そのプロトタイプは次の通りである: int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void*(*start_rtn)(void*),void *restrict arg);

値を返す

成功した場合は「0」を返し、それ以外の場合は落下数「-1」を返します。

パラメータ

  • 最初のパラメーターは、スレッドIDへのポインターです。

  • 2つ目は、スレッド属性を設定するために使用されます。

  • 3番目は、スレッド実行関数の開始アドレスです。

  • 最後のものは、関数を実行するものです。

void off(){
    flag = 0;
    softToneStop(BeepPin);
    digitalWrite(ALedPin,LOW);
    digitalWrite(BLedPin,LOW);
}

スレッド ledWorkBuzzWork を終了するために、 関数 Off() は「flag = 0」を定義しそして、ブザーとLEDをオフにする。

int main(){
    setup();
    int lastState = 0;
    while(1){
        int currentState = digitalRead(switchPin);
        if ((currentState == 1)&&(lastState==0)){
            on();
        }
        else if((currentState == 0)&&(lastState==1)){
            off();
        }
        lastState=currentState;
    }
    return 0;
}

main() には、プログラムのプロセス全体が含まれている:まず、スライドスイッチの値を読み取る。 トグルスイッチが右に切り替えられた場合(読み取り値が1)、関数 on() が呼び出され、 ブザーが駆動されて音が鳴り、赤と緑のLEDが点滅する。そうしないと、ブザーとLEDが機能しない。

Python言語ユーザー向け

ステップ2: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: 実行する。

sudo python3 3.1.10_AlarmBell.py

プログラムが起動すると、トグルスイッチが右に切り替わり、 ブザーが警報音を出す。同時に、特定の周波数で赤と緑のLEDが点滅する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import threading

BeepPin=22
ALedPin=17
BLedPin=27
switchPin=18

Buzz=0
flag =0
note=150
pitch=20

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BeepPin, GPIO.OUT)
    GPIO.setup(ALedPin,GPIO.OUT,initial=GPIO.LOW)
    GPIO.setup(BLedPin,GPIO.OUT,initial=GPIO.LOW)
    GPIO.setup(switchPin,GPIO.IN)
    global Buzz
    Buzz=GPIO.PWM(BeepPin,note)

def ledWork():
    while flag:
        GPIO.output(ALedPin,GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(ALedPin,GPIO.LOW)
        GPIO.output(BLedPin,GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(BLedPin,GPIO.LOW)

def buzzerWork():
    global pitch
    global note
    while flag:
        if note >= 800 or note <=130:
            pitch = -pitch
        note = note + pitch
        Buzz.ChangeFrequency(note)
        time.sleep(0.01)


def on():
    global flag
    flag = 1
    Buzz.start(50)
    tBuzz = threading.Thread(target=buzzerWork)
    tBuzz.start()
    tLed = threading.Thread(target=ledWork)
    tLed.start()

def off():
    global flag
    flag = 0
    Buzz.stop()
    GPIO.output(ALedPin,GPIO.LOW)
    GPIO.output(BLedPin,GPIO.LOW)


def main():
    lastState=0
    while True:
        currentState =GPIO.input(switchPin)
        if currentState == 1 and lastState == 0:
            on()
        elif currentState == 0 and lastState == 1:
            off()
        lastState=currentState


def destroy():
    off()
    GPIO.cleanup()


if __name__ == '__main__':
    setup()
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの説明

import threading

ここでは、 Threading モジュールをインポートし、 複数のことを一度に行えるようにするが、通常のプログラムはコードを上から下にしか実行できない。 Threading モジュールを使用すると、LEDとブザーを個別に動作させることができる。

def ledWork():
    while flag:
        GPIO.output(ALedPin,GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(ALedPin,GPIO.LOW)
        GPIO.output(BLedPin,GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(BLedPin,GPIO.LOW)

関数 ledWork() は、これら2つのLEDの動作状態を設定するために役立つ:緑色のLEDを0.5秒間点灯させた後、消灯する。 同様に、赤いLEDを0.5秒間点灯させてから消灯する。

def buzzerWork():
    global pitch
    global note
    while flag:
        if note >= 800 or note <=130:
            pitch = -pitch
        note = note + pitch
        Buzz.ChangeFrequency(note)
        time.sleep(0.01)

関数 buzzWork() は、ブザーの動作状態を設定するために使用される。 ここでは、周波数を130〜800に設定し、20の間隔で累積・減衰する。

def on():
    global flag
    flag = 1
    Buzz.start(50)
    tBuzz = threading.Thread(target=buzzerWork)
    tBuzz.start()
    tLed = threading.Thread(target=ledWork)
    tLed.start()

関数 on() で:

  • 制御スレッドの終了を示すマーク「flag = 1」を定義する。

  • バズを開始し、デューティサイクルを50%に設定する。

  • LEDとブザ ー が同時に動作できるように、二つの個別のスレッドを作成する。

tBuzz = threading.Thread(target=buzzerWork) : スレッドを作成すると、そのプロトタイプは以下の通りである: class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, \*, daemon=None)

構築メソッドの中で、主要なパラメーターは ターゲット であり、呼び出し可能なオブジェクト(ここでは関数 ledWorkBuzzWork )を ターゲット に割り当てる必要がある。

次に、スレッドオブジェクトを開始するために start() が呼び出される。 たとえば、 tBuzz.start() は、新しくインストールされたtBuzzスレッドを開始するために使用される。

def off():
    global flag
    flag = 0
    Buzz.stop()
    GPIO.output(ALedPin,GPIO.LOW)
    GPIO.output(BLedPin,GPIO.LOW)

スレッド ledWorkBuzzWork を終了するために、 関数 Off() は「flag = 0」を定義しそして、ブザーとLEDをオフにする。

def main():
    lastState=0
    while True:
        currentState =GPIO.input(switchPin)
        if currentState == 1 and lastState == 0:
            on()
        elif currentState == 0 and lastState == 1:
            off()
        lastState=currentState

main() には、プログラムのプロセス全体が含まれている: まず、スライドスイッチの値を読み取る。 トグルスイッチが右に切り替えられた場合(読み取り値が1)、関数 on() が呼び出され、 ブザーが駆動されて音が鳴り、赤と緑のLEDが点滅する。そうしないと、ブザーとLEDが機能しない。

現象画像
_images/image267.jpeg

3.1.11 モールス信号発生器

前書き

このレッスンでは、モールス符号ジェネレーターを作成する。 ここでは、Raspberry Piに一連の英語の文字を入力して、モールス符号として表示する。

部品
_images/list_Morse_Code_Generator.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO22

Pin 15

3

22

_images/Schematic_three_one11.png
実験手順

ステップ1: 回路を作る。(ブザーの両極に注意してください:+ラベルが付いている方が正極で、もう一方が負極である。)

Morse_bb
C言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.11/

ステップ3: コードをコンパイルする。

gcc 3.1.11_MorseCodeGenerator.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

プログラムの実行後、一連の文字を入力すると、ブザーとLEDが対応するモールス信号を送信する。

コードの説明

struct MORSE{
    char word;
    unsigned char *code;
};

struct MORSE morseDict[]=
{
    {'A',"01"}, {'B',"1000"}, {'C',"1010"}, {'D',"100"}, {'E',"0"},
    {'F',"0010"}, {'G',"110"}, {'H',"0000"}, {'I',"00"}, {'J',"0111"},
    {'K',"101"}, {'L',"0100"}, {'M',"11"}, {'N',"10"}, {'O',"111"},
    {'P',"0110"}, {'Q',"1101"}, {'R',"010"}, {'S',"000"}, {'T',"1"},
    {'U',"001"}, {'V',"0001"}, {'W',"011"}, {'X',"1001"}, {'Y',"1011"},
    {'Z',"1100"},{'1',"01111"}, {'2',"00111"}, {'3',"00011"}, {'4',"00001"},
    {'5',"00000"},{'6',"10000"}, {'7',"11000"}, {'8',"11100"}, {'9',"11110"},
    {'0',"11111"},{'?',"001100"}, {'/',"10010"}, {',',"110011"}, {'.',"010101"},
    {';',"101010"},{'!',"101011"}, {'@',"011010"}, {':',"111000"}
};

この構造MORSEは、モールス符号のディクショナリで、文字A〜Z、数字0〜9とマークを含む「?」 「/」 「:」 「,」 「.」 「;」 「!」 「@」 .

char *lookup(char key,struct MORSE *dict,int length)
{
    for (int i=0;i<length;i++)
    {
        if(dict[i].word==key){
            return dict[i].code;
        }
    }
}

関数 lookup() は、辞書をチェックすることによって機能します。 key を定義し、 構造 morseDictkey と同じ単語を検索し、対応する情報(特定の単語の code )を返す。

void on(){
    digitalWrite(ALedPin,HIGH);
    digitalWrite(BeepPin,HIGH);
}

関数 on() を作成して、ブザーとLEDを起動する

void off(){
    digitalWrite(ALedPin,LOW);
    digitalWrite(BeepPin,LOW);
}

関数 off() はブザーとLEDをオフにする。

void beep(int dt){
    on();
    delay(dt);
    off();
    delay(dt);
}

関数 beep() を定義して、ブザーとLEDが特定の dt 間隔で音を鳴らして点滅するようにする。

void morsecode(char *code){
    int pause = 250;
    char *point = NULL;
    int length = sizeof(morseDict)/sizeof(morseDict[0]);
    for (int i=0;i<strlen(code);i++)
    {
        point=lookup(code[i],morseDict,length);
        for (int j=0;j<strlen(point);j++){
            if (point[j]=='0')
            {
                beep(pause/2);
            }else if(point[j]=='1')
            {
                beep(pause);
            }
            delay(pause);
        }
    }
}

関数 morsecode() はコードの「1」が音または光を放射し続け、「0」が音または光を短時間放射することにより、入力文字のモールス符号を処理するために使用される。たとえば、「SOS」を入力すると、 3つの短い、3つの長いと3つの短いセグメントを含む信号になる“ • • • - - - • • • ”。

int toupper(int c)
{
    if ((c >= 'a') && (c <= 'z'))
        return c + ('A' - 'a');
    return c;
}
char *strupr(char *str)
{
    char *orign=str;
    for (; *str!='\0'; str++)
        *str = toupper(*str);
return orign;
}

コーディングする前に、文字を大文字に統一しなければならない。

void main(){
    setup();
    char *code;
    int length=8;
    code = (char*)malloc(sizeof(char)*length);
    while (1){
        printf("Please input the messenger:");
        delay(100);
        scanf("%s",code);
        code=strupr(code);
        printf("%s\n",code);
        delay(100);
        morsecode(code);
    }
}

キーボードで関連する文字を入力すると、 code = strupr(code) は入力文字を大文字に変換する。

printf() はコンピューター画面にクリアテキストをプリントし、 morsecod() 関数はブザーとLEDからモールス符号を出力させる。

入力文字の長さは、 長さ を超えないことに注意してください(訂正可能)。

Python言語ユーザー向け

ステップ2: コードファイルを開く。

cd /home/pi/davinci-kit-for-raspberry-pi/python

ステップ3: 実行する。

sudo python3 3.1.11_MorseCodeGenerator.py

プログラムの実行後、一連の文字を入力すると、ブザーとLEDが対応するモールス信号を送信する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time

BeepPin=22
ALedPin=17

MORSECODE = {
    'A':'01', 'B':'1000', 'C':'1010', 'D':'100', 'E':'0', 'F':'0010', 'G':'110',
    'H':'0000', 'I':'00', 'J':'0111', 'K':'101', 'L':'0100', 'M':'11', 'N':'10',
    'O':'111', 'P':'0110', 'Q':'1101', 'R':'010', 'S':'000', 'T':'1',
    'U':'001', 'V':'0001', 'W':'011', 'X':'1001', 'Y':'1011', 'Z':'1100',
    '1':'01111', '2':'00111', '3':'00011', '4':'00001', '5':'00000',
    '6':'10000', '7':'11000', '8':'11100', '9':'11110', '0':'11111',
    '?':'001100', '/':'10010', ',':'110011', '.':'010101', ';':'101010',
    '!':'101011', '@':'011010', ':':'111000',
    }

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BeepPin, GPIO.OUT, initial=GPIO.LOW)
    GPIO.setup(ALedPin,GPIO.OUT,initial=GPIO.LOW)

def on():
    GPIO.output(BeepPin, 1)
    GPIO.output(ALedPin, 1)

def off():
    GPIO.output(BeepPin, 0)
    GPIO.output(ALedPin, 0)

def beep(dt):       # dt for delay time.
    on()
    time.sleep(dt)
    off()
    time.sleep(dt)

def morsecode(code):
    pause = 0.25
    for letter in code:
        for tap in MORSECODE[letter]:
            if tap == '0':
                beep(pause/2)
            if tap == '1':
                beep(pause)
        time.sleep(pause)

def main():
    while True:
        code=input("Please input the messenger:")
        code = code.upper()
        print(code)
        morsecode(code)

def destroy():
    print("")
    GPIO.output(BeepPin, GPIO.LOW)
    GPIO.output(ALedPin, GPIO.LOW)
    GPIO.cleanup()

if __name__ == '__main__':
    setup()
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの説明

MORSECODE = {
    'A':'01', 'B':'1000', 'C':'1010', 'D':'100', 'E':'0', 'F':'0010', 'G':'110',
    'H':'0000', 'I':'00', 'J':'0111', 'K':'101', 'L':'0100', 'M':'11', 'N':'10',
    'O':'111', 'P':'0110', 'Q':'1101', 'R':'010', 'S':'000', 'T':'1',
    'U':'001', 'V':'0001', 'W':'011', 'X':'1001', 'Y':'1011', 'Z':'1100',
    '1':'01111', '2':'00111', '3':'00011', '4':'00001', '5':'00000',
    '6':'10000', '7':'11000', '8':'11100', '9':'11110', '0':'11111',
    '?':'001100', '/':'10010', ',':'110011', '.':'010101', ';':'101010',
    '!':'101011', '@':'011010', ':':'111000',
    }

この構造MORSEは、モールス符号のディクショナリで、 文字A〜Z、数字0〜9とマークを含む「?」 「/」 「:」 「,」 「.」 「;」 「!」 「@」 .

def on():
    GPIO.output(BeepPin, 1)
    GPIO.output(ALedPin, 1)

関数 on() はブザーとLEDを起動する。

def off():
    GPIO.output(BeepPin, 0)
    GPIO.output(ALedPin, 0)

関数 off() はブザーとLEDをオフにする。

def beep(dt):   # x for dalay time.
    on()
    time.sleep(dt)
    off()
    time.sleep(dt)

関数 beep() を定義して、ブザーとLEDが特定の dt 間隔で音を鳴らして点滅するようにする。

def morsecode(code):
    pause = 0.25
    for letter in code:
        for tap in MORSECODE[letter]:
            if tap == '0':
                beep(pause/2)
            if tap == '1':
                beep(pause)
        time.sleep(pause)

関数 morsecode() はコードの「1」が音または光を放射し続け、 「0」が音または光を短時間放射することにより、入力文字のモールス符号を処理するために使用される。 たとえば、「SOS」を入力すると、 3つの短い、3つの長いと3つの短いセグメントを含む信号になる“ • • • - - - • • • ”。

def main():
    while True:
        code=input("Please input the messenger:")
        code = code.upper()
        print(code)
        morsecode(code)

キーボードで関連する文字を入力すると、 upper() は入力文字を大文字に変換する。

printf() はコンピューター画面にクリアテキストをプリントし、 morsecod() 関数はブザーとLEDからモールス符号を出力させる。

現象画像
_images/image270.jpeg

3.1.12 ゲーム–数字推測

前書き

数字を推測することは、あなたとあなたの友人が交互に数字を入力する楽しいパーティーゲームである(0〜99)。 プレーヤーがなぞなぞに正しく答えるまで、数字を入力すると範囲は小さくなる。 その後、プレイヤーは敗北し、処罰される。たとえば、ラッキーナンバーが51で、 プレーヤーがそれを見ることができず、プレーヤー①が50を入力する場合、番号範囲は50〜99に変わる。 もしプレイヤー②が70を入力する場合、番号の範囲は50〜70になる。プレイヤー③が51を入力した場合、 このプレイヤーは不運なプレイヤーである。 ここでは、キーパッドを使用して数字を入力し、LCDを使用して結果を表示させる。

部品
_images/list_GAME_Guess_Number.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

SPIMOSI

Pin 19

12

10

GPIO22

Pin 15

3

22

GPIO27

Pin 13

2

27

GPIO17

Pin 11

0

17

SDA1

Pin 3

SDA1(8)

SDA1(2)

SCL1

Pin 5

SCL1(9)

SDA1(3)

_images/Schematic_three_one12.png
実験手順

ステップ1: 回路を作る

Guess Number_bb

ステップ2: I2C構成 (付録を参照してください。I2Cを設定している場合は、この手順をスキップしてください。)

C言語ユーザー向け

ステップ3: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.12/

ステップ4: コンパイルする。

gcc 3.1.12_GAME_GuessNumber.c -lwiringPi

ステップ5: 実行する。

sudo ./a.out

プログラムの実行後、LCDに最初のページが表示される:

Welcome!
Press A to go!

「A」を押すと、ゲームが開始され、ゲームページがLCDに表示される。

Enter number:
0 ‹point‹ 99

乱数の 「point」 が生成されるが、ゲームの開始時にLCDに表示されない。 必要なのはそれを推測することである。 最終計算が完了するまで入力した数値は最初の行の最後に表示される。 (「D」を押して比較を開始し、入力値が 10 より大きい場合、自動比較が開始される。)

「point」の番号範囲が2行目に表示される。 そして、範囲内の数値を入力しなければならない。 数値を入力すると、範囲が狭くなる。 幸運にも不運にもラッキーナンバーを獲得した場合、「You've got it!」と表示される

コードの説明

コードの最初の部分は キーパッド と I2C LCD1602 の機能である。 それらの詳細については、 1.1.7 I2C LCD16022.1.5 キーパッド を参照ください。

ここで、以下のことをわかる必要がある:

/****************************************/
//Start from here
/****************************************/
void init(void){
    fd = wiringPiI2CSetup(LCDAddr);
    lcd_init();
    lcd_clear();
    for(int i=0 ; i<4 ; i++) {
        pinMode(rowPins[i], OUTPUT);
        pinMode(colPins[i], INPUT);
    }
    lcd_clear();
    write(0, 0, "Welcome!");
    write(0, 1, "Press A to go!");
}

この関数は元々 I2C LCD1602 と Keypad を定義し、「Welcome!」と「Press A to go!」を表示するために使用される。

void init_new_value(void){
    srand(time(0));
    pointValue = rand()%100;
    upper = 99;
    lower = 0;
    count = 0;
    printf("point is %d\n",pointValue);
}

この関数は乱数 point を生成し、ポイントの範囲ヒントをリセットしする。

bool detect_point(void){
    if(count > pointValue){
        if(count < upper){
            upper = count;
        }
    }
    else if(count < pointValue){
        if(count > lower){
            lower = count;
        }
    }
    else if(count = pointValue){
        count = 0;
        return 1;
    }
    count = 0;
    return 0;
}

detect_point() は入力番号を生成された point と比較する。 比較結果が同じではない場合、 count は値を 上限 と 下限 に割り当て、「 0 」を返す。 それ以外の場合、結果が同じであると示す場合、「 1 」を返す。

void lcd_show_input(bool result){
    char *str=NULL;
    str =(char*)malloc(sizeof(char)*3);
    lcd_clear();
    if (result == 1){
        write(0,1,"You've got it!");
        delay(5000);
        init_new_value();
        lcd_show_input(0);
        return;
    }
    write(0,0,"Enter number:");
    Int2Str(str,count);
    write(13,0,str);
    Int2Str(str,lower);
    write(0,1,str);
    write(3,1,"<Point<");
    Int2Str(str,upper);
    write(12,1,str);
}

この関数はゲームページを表示するために使用される。関数 Int2Str(str、count) に注意してください。 lcdを正しく表示するために、これらの変数 countlowerupper を 整数 から 文字列 に変換する。

int main(){
    unsigned char pressed_keys[BUTTON_NUM];
    unsigned char last_key_pressed[BUTTON_NUM];
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    init();
    init_new_value();
    while(1){
        keyRead(pressed_keys);
        bool comp = keyCompare(pressed_keys, last_key_pressed);
        if (!comp){
            if(pressed_keys[0] != 0){
                bool result = 0;
                if(pressed_keys[0] == 'A'){
                    init_new_value();
                    lcd_show_input(0);
                }
                else if(pressed_keys[0] == 'D'){
                    result = detect_point();
                    lcd_show_input(result);
                }
                else if(pressed_keys[0] >='0' && pressed_keys[0] <= '9'){
                    count = count * 10;
                    count = count + (pressed_keys[0] - 48);
                    if (count>=10){
                        result = detect_point();
                    }
                    lcd_show_input(result);
                }
            }
            keyCopy(last_key_pressed, pressed_keys);
        }
        delay(100);
    }
    return 0;
}

main() には、以下に示すように、プログラムのプロセス全体が含まれている:

  1. I2C LCD1602 と キーパッド を初期化する。

  2. init_new_value() を使用して、 0〜99 の乱数を作成する。

  3. ボタンが押されているかどうかを判断し、ボタンの読み取り値を取得する。

  4. ボタン「 A 」を押すと、 0〜99 の乱数が表示され、ゲームが開始される。

  5. ボタン「 D 」が押されたことが検出されると、プログラムは結果判定に入り、LCDに結果を表示する。このステップは数字を1つだけ押してからボタン「 D 」を押したときの結果を判断するために役立つ。

  6. ボタン 0-9 を押すと、coun の値が変更されます。 カウント が 10 より大きい場合、判断が開始されます。

  7. ゲームの変化とその値は LCD1602 に表示される。

Python言語ユーザー向け

ステップ3: ディレクトリを変更する。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ4: 実行。

sudo python3 3.1.12_GAME_GuessNumber.py

プログラムの実行後、LCDに最初のページが表示される:

Welcome!
Press A to go!

「A」を押すと、ゲームが開始され、ゲームページがLCDに表示される。

Enter number:
0 ‹point‹ 99

乱数の 「point」 が生成されるが、ゲームの開始時にLCDに表示されない。 必要なのはそれを推測することである。 最終計算が完了するまで入力した数値は最初の行の最後に表示される。(「D」を押して比較を開始し、入力値が 10 より大きい場合、自動比較が開始される。)

「point」の番号範囲が2行目に表示される。そして、範囲内の数値を入力しなければならない。 数値を入力すると、範囲が狭くなる。 幸運にも不運にもラッキーナンバーを獲得した場合、「You've got it!」と表示される

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import LCD1602
import random

##################### HERE IS THE KEYPAD LIBRARY TRANSPLANTED FROM Arduino ############
#class Key:Define some of the properties of Key
class Keypad():

   def __init__(self, rowsPins, colsPins, keys):
      self.rowsPins = rowsPins
      self.colsPins = colsPins
      self.keys = keys
      GPIO.setwarnings(False)
      GPIO.setmode(GPIO.BCM)
      GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW)
      GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

   def read(self):
      pressed_keys = []
      for i, row in enumerate(self.rowsPins):
            GPIO.output(row, GPIO.HIGH)
            for j, col in enumerate(self.colsPins):
               index = i * len(self.colsPins) + j
               if (GPIO.input(col) == 1):
                  pressed_keys.append(self.keys[index])
            GPIO.output(row, GPIO.LOW)
      return pressed_keys

################ EXAMPLE CODE START HERE ################

count = 0
pointValue = 0
upper=99
lower=0

def setup():
   global keypad, last_key_pressed,keys
   rowsPins = [18,23,24,25]
   colsPins = [10,22,27,17]
   keys = ["1","2","3","A",
            "4","5","6","B",
            "7","8","9","C",
            "*","0","#","D"]
   keypad = Keypad(rowsPins, colsPins, keys)
   last_key_pressed = []
   LCD1602.init(0x27, 1)    # init(slave address, background light)
   LCD1602.clear()
   LCD1602.write(0, 0, 'Welcome!')
   LCD1602.write(0, 1, 'Press A to Start!')

def init_new_value():
   global pointValue,upper,count,lower
   pointValue = random.randint(0,99)
   upper = 99
   lower = 0
   count = 0
   print('point is %d' %(pointValue))


def detect_point():
   global count,upper,lower
   if count > pointValue:
      if count < upper:
            upper = count
   elif count < pointValue:
      if count > lower:
            lower = count
   elif count == pointValue:
      count = 0
      return 1
   count = 0
   return 0

def lcd_show_input(result):
   LCD1602.clear()
   if result == 1:
      LCD1602.write(0,1,'You have got it!')
      time.sleep(5)
      init_new_value()
      lcd_show_input(0)
      return
   LCD1602.write(0,0,'Enter number:')
   LCD1602.write(13,0,str(count))
   LCD1602.write(0,1,str(lower))
   LCD1602.write(3,1,' < Point < ')
   LCD1602.write(13,1,str(upper))

def loop():
   global keypad, last_key_pressed,count
   while(True):
      result = 0
      pressed_keys = keypad.read()
      if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
            if pressed_keys == ["A"]:
               init_new_value()
               lcd_show_input(0)
            elif pressed_keys == ["D"]:
               result = detect_point()
               lcd_show_input(result)
            elif pressed_keys[0] in keys:
               if pressed_keys[0] in list(["A","B","C","D","#","*"]):
                  continue
               count = count * 10
               count += int(pressed_keys[0])
               if count >= 10:
                  result = detect_point()
               lcd_show_input(result)
            print(pressed_keys)
      last_key_pressed = pressed_keys
      time.sleep(0.1)

# Define a destroy function for clean up everything after the script finished
def destroy():
   # Release resource
   GPIO.cleanup()
   LCD1602.clear()

if __name__ == '__main__':     # Program start from here
   try:
      setup()
      while True:
            loop()
   except KeyboardInterrupt:   # When 'Ctrl+C' is pressed, the program destroy() will be executed.
      destroy()

コードの説明

コードの最初の部分は キーパッド と I2C LCD1602 の機能である。 それらの詳細については、 1.1.7 I2C LCD16022.1.5 キーパッド を参照ください。

ここで、以下のことをわかる必要がある:

def init_new_value():
    global pointValue,upper,count,lower
    pointValue = random.randint(0,99)
    upper = 99
    lower = 0
    count = 0
    print('point is %d' %(pointValue))

この関数は乱数「point」を生成し、ポイントの範囲ヒントをリセットしする。

def detect_point():
    global count,upper,lower
    if count > pointValue:
        if count < upper:
            upper = count
    elif count < pointValue:
        if count > lower:
            lower = count
    elif count == pointValue:
        count = 0
        return 1
    count = 0
    return 0

detect_point() は入力番号 count を生成された point と比較する。 比較結果が同じではない場合、 count は値を 上限 と 下限 に割り当て、「 0 」を返す。 それ以外の場合、結果が同じであると示す場合、「 1 」を返す。

def lcd_show_input(result):
    LCD1602.clear()
    if result == 1:
        LCD1602.write(0,1,'You have got it!')
        time.sleep(5)
        init_new_value()
        lcd_show_input(0)
        return
    LCD1602.write(0,0,'Enter number:')
    LCD1602.write(13,0,str(count))
    LCD1602.write(0,1,str(lower))
    LCD1602.write(3,1,' < Point < ')
    LCD1602.write(13,1,str(upper))

この関数はゲームページを表示するために使用される。

sstr(count) : Because write() はデータ型のみをサポートできるため、 文字列, str() は 数値 を 文字列 に変換するために必要である。

def loop():
    global keypad, last_key_pressed,count
    while(True):
        result = 0
        pressed_keys = keypad.read()
        if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
            if pressed_keys == ["A"]:
                init_new_value()
                lcd_show_input(0)
            elif pressed_keys == ["D"]:
                result = detect_point()
                lcd_show_input(result)
            elif pressed_keys[0] in keys:
                if pressed_keys[0] in list(["A","B","C","D","#","*"]):
                    continue
                count = count * 10
                count += int(pressed_keys[0])
                if count >= 10:
                    result = detect_point()
                lcd_show_input(result)
            print(pressed_keys)
        last_key_pressed = pressed_keys
        time.sleep(0.1)

main() には、以下に示すように、プログラムのプロセス全体が含まれている:

  1. I2C LCD1602 と キーパッド を初期化する。

  2. ボタンが押されているかどうかを判断し、ボタンの読み取り値を取得する。

  3. ボタン「 A 」を押すと、 0〜99 の乱数が表示され、ゲームが開始される。

  4. ボタン「 D 」が押されたことが検出されると、プログラムは結果判定に入る。

  5. ボタン 0-9 を押すと、coun の値が変更されます。 カウント が 10 より大きい場合、判断が開始されます。

  6. ゲームの変化とその値は LCD1602 に表示される。

現象画像
_images/image274.jpeg

3.1.13 ゲーム– 10秒

前書き

それから、あなたの集中力に挑戦できるゲームデバイスを作ろう。傾斜スイッチをスティックにつないで、魔法の棒を作る。棒を振ると、4桁のセグメントディスプレイがカウントを開始し、もう一度振るとカウントを停止する。表示されたカウントを10.00に保つことに成功した場合、あなたが勝つ。友達とゲームをプレイして、タイムウィザードが誰かを確認できる。

部品
_images/list_GAME_10_Second.png
回路図

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

GPIO26

Pin 37

25

26

_images/Schematic_three_one13.png
実験手順

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

10 second_bb
C言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.13/

ステップ3: コードをコンパイルする。

gcc 3.1.13_GAME_10Second.c -lwiringPi

ステップ4: EXEファイルを実行する。

sudo ./a.out

棒を振ると、4桁のセグメントディスプレイがカウントを開始し、もう一度振るとカウントを停止する。 表示されたカウントを 10.00 に保つことに成功した場合、あなたが勝つ。 もう一度振って、ゲームの次のラウンドを開始する。

コードの説明

void stateChange(){
    if (gameState == 0){
        counter = 0;
        delay(1000);
        ualarm(10000,10000);
    }else{
        alarm(0);
        delay(1000);
    }
    gameState = (gameState + 1)%2;
}

ゲームは二つのモードに分けられている:

gameState = 0 は「開始」モードであり、このモードでは、時間を計測してセグメントディスプレイに表示し、傾斜スイッチを振って「表示」モードに入る。

GameState = 1 は「表示」モードであり、タイミングを停止し、セグメントディスプレイに時間を表示する。傾斜スイッチを再度振ると、タイマーがリセットされ、ゲームが再起動する。

void loop(){
    int currentState =0;
    int lastState=0;
    while(1){
        display();
        currentState=digitalRead(sensorPin);
        if((currentState==0)&&(lastState==1)){
            stateChange();
        }
        lastState=currentState;
    }
}

Loop() が主な関数である。最初に、4ビットセグメントディスプレイに時間が表示され、 傾斜スイッチの値が読み取られる。傾斜スイッチの状態が変更された場合、 stateChange() が呼び出される。

Python言語ユーザー向け

ステップ2: コードのフォルダーに入る。

cd /home/pi/davinci-kit-for-raspberry-pi/python/

ステップ3: EXEファイルを実行する。

sudo python3 3.1.13_GAME_10Second.py

棒を振ると、4桁のセグメントディスプレイがカウントを開始し、 もう一度振るとカウントを停止する。表示されたカウントを 10.00 に保つことに成功した場合、あなたが勝つ。 もう一度振って、ゲームの次のラウンドを開始する。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import threading

sensorPin = 26

SDI = 24
RCLK = 23
SRCLK = 18

placePin = (10, 22, 27, 17)
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

counter = 0
timer =0
gameState =0

def clearDisplay():
    for i 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):
    for i in placePin:
        GPIO.output(i,GPIO.LOW)
    GPIO.output(placePin[digit], GPIO.HIGH)

def display():
    global counter
    clearDisplay()
    pickDigit(0)
    hc595_shift(number[counter % 10])

    clearDisplay()
    pickDigit(1)
    hc595_shift(number[counter % 100//10])

    clearDisplay()
    pickDigit(2)
    hc595_shift(number[counter % 1000//100]-0x80)

    clearDisplay()
    pickDigit(3)
    hc595_shift(number[counter % 10000//1000])

def stateChange():
    global gameState
    global counter
    global timer1
    if gameState == 0:
        counter = 0
        time.sleep(1)
        timer()
    elif gameState ==1:
        timer1.cancel()
        time.sleep(1)
    gameState = (gameState+1)%2

def loop():
    global counter
    currentState = 0
    lastState = 0
    while True:
        display()
        currentState=GPIO.input(sensorPin)
        if (currentState == 0) and (lastState == 1):
            stateChange()
        lastState=currentState

def timer():
    global counter
    global timer1
    timer1 = threading.Timer(0.01, timer)
    timer1.start()
    counter += 1

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

def destroy():   # When \"Ctrl+C\" is pressed, the function is executed.
    GPIO.cleanup()
    global timer1
    timer1.cancel()

if __name__ == '__main__':  # Program starting from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

コードの説明

def stateChange():
    global gameState
    global counter
    global timer1
    if gameState == 0:
        counter = 0
        time.sleep(1)
        timer()
    elif gameState ==1:
        timer1.cancel()
        time.sleep(1)
    gameState = (gameState+1)%2

ゲームは二つのモードに分けられている:

gameState = 0 は「開始」モードであり、このモードでは、時間を計測してセグメントディスプレイに表示し、傾斜スイッチを振って「表示」モードに入る。

GameState = 1 は「表示」モードであり、タイミングを停止し、セグメントディスプレイに時間を表示する。傾斜スイッチを再度振ると、タイマーがリセットされ、ゲームが再起動する。

def loop():
    global counter
    currentState = 0
    lastState = 0
    while True:
        display()
        currentState=GPIO.input(sensorPin)
        if (currentState == 0) and (lastState == 1):
            stateChange()
        lastState=currentState

loop() が主な関数である。最初に、4ビットセグメントディスプレイに時間が表示され、 傾斜スイッチの値が読み取られる。 傾斜スイッチの状態が変更された場合、 stateChange() が呼び出される。

def timer():
    global counter
    global timer1
    timer1 = threading.Timer(0.01, timer)
    timer1.start()
    counter += 1

間隔が0.01秒に達すると、Timer関数が呼び出される。カウンターに1を追加すると、タイマーが再び使用されて、0.01秒ごとに繰り返し実行される。

現象画像
_images/image278.jpeg

3.1.14 ゲーム–Not Not-頭脳耐久ゲーム

前書き

このレッスンでは、面白いゲームデバイスを作成し、「Not Not」と呼ぶ。

ゲーム中、ドットマトリックスは矢印をランダムに更新する。必要なのは、限られた時間内に矢印の反対方向にボタンを押すことである。時間になった場合、または矢印と同じ方向のボタンが押された場合、敗北すると意味する。

このゲームは本当にあなたの逆思考を実践することができる。

部品
_images/list_GAME_Not_Not.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO20

Pin 38

28

20

GPIO26

Pin 37

25

26

_images/Schematic_three_one14.png
実験手順

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

_images/image280.png
C言語ユーザー向け

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

cd /home/pi/davinci-kit-for-raspberry-pi/c/3.1.14/

ステップ3: コンパイルします。

gcc 3.1.14_GAME_NotNot.c -lwiringPi

ステップ4: 実行します。

sudo ./a.out

プログラムの開始後、左矢印または右矢印がドットマトリックス上でランダムに更新されます。 限られた時間内に矢印の反対方向にボタンを押す必要があります。 次に、「√」がドットマトリックスに表示されます。 時間切れの場合、または矢印と同じ方向のボタンが押された場合は、 外に出て、ドットマトリックスに「x」が表示されます。 また、2つの新しいボタンを追加したり、上下左右のジョイスティックキーに置き換えたりすることもできます。 4方向でゲームの難易度を上げることができます。

コードの説明

1.1.6 LEDドットマトリックス に基づいて、このレッスンでは 2 ボタンを追加して面白いゲームデバイスを作成します。 したがって、ドットマトリックスにあまり詳しくない場合は、 1.1.6 LEDドットマトリックス を参照してください。

プログラム全体のプロセスは次のとおりである:

  1. 矢印の方向をランダムに選択し、 タイマー1 を生成する。

  2. ドットマトリックスに矢印画像を表示する。

  3. ボタン入力を判断する。ボタンが押されるか、 タイマー1 が時間切れを想起させると、判定が開始される。

  4. 判定結果に基づいて画像を表示する。その間、 タイマー2 を生成する。

  5. タイマー2 が時間切れを想起させると、 ステップ1 を再実行する。

struct GLYPH{
    char *word;
    unsigned char code[8];
};

struct GLYPH arrow[2]=
{
    {"right",{0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF}},
    // {"down",{0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF}},
    // {"up",{0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF}},
    {"left",{0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF}}
};

struct GLYPH check[2]=
{
    {"wrong",{0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF}},
    {"right",{0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF}}
};

GLYPH構造は辞書のように動作します。 word 属性は辞書の key に対応し、 code 属性は value に対応します。

ここでは、ドットマトリックスが画像を表示するための配列(8×8ビットの配列)を格納するためのコードを使用しています。

ここでは、配列 arrow を用いて、上下左右の矢印パターンをLEDドットマトリクスに表示することができます。

上下 が付注され、必要に応じて解除できる。

配列 check を使用して、これらの2つの画像「 × 」と「 √ 」を表示する。

char *lookup(char *key,struct GLYPH *glyph,int length){
    for (int i=0;i<length;i++)
    {
        if(strcmp(glyph[i].word,key)==0){
            return glyph[i].code;
        }
    }
}

関数 lookup() は、辞書を引くことで機能します。 key を定義し、構造 GLYPH *glyphkey と同じ単語を検索し、 対応する情報(特定の単語の code )を返す。

関数 Strcmp() は、2つの文字列 glyph[i].wordkey の同一性を比較するために使用される。 同一性が判断された場合、 glyph[i].code を返す。

void display(char *glyphCode){
    for(int i;i<8;i++){
        hc595_in(glyphCode[i]);
        hc595_in(0x80>>i);
        hc595_out();
    }
}

指定したパターンをドットマトリックスに表示する。

void createGlyph(){
    srand(time(NULL));
    int i=rand()%(sizeof(arrow)/sizeof(arrow[0]));
    waypoint=arrow[i].word;
    stage="PLAY";
    alarm(2);
}

関数 createGlyph() を使用して、方向(配列 arrow[] の要素の単語属性:"left"、"right" ...)をランダムに選択する。 ステージを「PLAY」に設定し、2秒の目覚まし時計機能を開始する。

srand(time(NULL)) : システムクロックからのランダムシードを初期化する。

(sizeof(arrow)/sizeof(arrow[0])) : 配列の長さを取得し、結果は2である。

rand()%2 : 余りは 0 または 1 で、生成された乱数を2で割ったものである。

waypoint=arrow[i].word : 結果は「right」または「left」でなければならない。

void checkPoint(char *inputKey){
    alarm(0)==0;
    if(inputKey==waypoint||inputKey=="empty")
    {
        waypoint="wrong";
    }
    else{
        waypoint="right";
    }
    stage="CHECK";
    alarm(1);
}

checkPoint() は、ボタンの入力をチェックするためのもので、ボタンが押されていなかったり、 矢印と同じ方向のボタンが押されていたりすると、 ウェイポイントの結果がおかしくなり、ドットマトリクスに「x」と表示されます。 そうでなければ、ウェイポイントの結果は正しく、ドットマトリクスには「√」と表示されます。 ここでは、ステージ が CHECK となり、1秒単位の目覚まし時計機能を設定することができます。

alarm() は「目覚まし時計」とも呼ばれ、タイマーを設定し、 設定した時間が経過すると SIGALRM 信号をプログレスに送信します。

void getKey(){
    if (digitalRead(AButtonPin)==1&&digitalRead(BButtonPin)==0)
    {checkPoint("right");}
    else if (digitalRead(AButtonPin)==0&&digitalRead(BButtonPin)==1)
    {checkPoint("left");}
}

getKey() は、これら2つのボタンの状態を読み取ります。 右ボタンが押されている場合、関数 checkPoint() のパラメータは right 、 左ボタンが押されている場合、パラメータは left となります。

void timer(){
    if (stage=="PLAY"){
        checkPoint("empty");
    }
    else if(stage=="CHECK"){
        createGlyph();
    }
}

これまでは、 alarm() が鳴ったときに timer() が呼ばれていました。 そして、「PLAY」モードでは、結果を判断するために checkPoint() を呼び出すことになっています。 「CHECK」モードの場合は、 createGlyph() を呼び出してパターンを選択します。

void main(){
    setup();
    signal(SIGALRM,timer);
    createGlyph();
    char *code = NULL;
    while(1){
        if (stage == "PLAY")
        {
            code=lookup(waypoint,arrow,sizeof(arrow)/sizeof(arrow[0]));
            display(code);
            getKey();
        }
        else if(stage == "CHECK")
        {
            code = lookup(waypoint,check,sizeof(check)/sizeof(check[0]));
            display(code);
        }
    }
}

関数 signal(SIGALRM、timer) の動作:(目覚まし時計関数alarm()によって生成された)SIGALRM信号を受信したときに関数timer()を呼び出す。

プログラムが起動したら、最初に1回だけcreateGlyph()を呼び出してから、ループを開始します。

ループ内:PLAYモードでは、ドットマトリックスに矢印パターンが表示され、ボタンの状態が確認されます。 チェックモードの場合、表示されるのは「x」または「√」です。

Python言語ユーザー向け

ステップ2:コードのフォルダーに入ります。

cd /home/pi/davinci-kit-for-raspberry-pi/python

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

sudo python3 3.1.14_GAME_NotNot.py

プログラムを起動すると、ドットマトリックス上に右または左を指す矢印が表示されます。 あなたがする必要があるのは、限られた時間内に矢印の反対方向にボタンを押すことです。 次に、「√」がドットマトリックスに表示されます。 時間切れの場合、または矢印と同じ方向のボタンが押された場合は、 外に出て、ドットマトリックスに「x」が表示されます。 また、2つの新しいボタンを追加したり、上下左右のジョイスティックキーに置き換えたりすることもできます。 4方向でゲームの難易度を上げることができます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。 ただし、その前に、 davinci-kit-for-raspberry-pi/python のようなソースコードパスに移動する必要があります。

import RPi.GPIO as GPIO
import time
import threading
import random

SDI   = 17
RCLK  = 18
SRCLK = 27

timerPlay = 0
timerCheck = 0

AButtonPin = 20
BButtonPin = 26

waypoint = "NULL"
stage = "NULL"

arrow={
    #"down" :[0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF],
    #"up":[0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF],
    "right" : [0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF],
    "left":[0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF]
}
check={
    "wrong":[0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF],
    "right":[0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF]
}

def setup():
    GPIO.setmode(GPIO.BCM)    # Number GPIOs by its BCM location
    GPIO.setup(SDI, GPIO.OUT)
    GPIO.setup(RCLK, GPIO.OUT)
    GPIO.setup(SRCLK, GPIO.OUT)
    GPIO.output(SDI, GPIO.LOW)
    GPIO.output(RCLK, GPIO.LOW)
    GPIO.output(SRCLK, GPIO.LOW)
    GPIO.setup(AButtonPin,GPIO.IN)
    GPIO.setup(BButtonPin,GPIO.IN)

# Shift the data to 74HC595
def hc595_shift(dat):
    for bit in range(0, 8):
        GPIO.output(SDI, 0x80 & (dat << bit))
        GPIO.output(SRCLK, GPIO.HIGH)
        GPIO.output(SRCLK, GPIO.LOW)

def display(glyphCode):
    for i in range(0, 8):
        hc595_shift(glyphCode[i])
        hc595_shift(0x80>>i)
        GPIO.output(RCLK, GPIO.HIGH)
        GPIO.output(RCLK, GPIO.LOW)

def creatGlyph():
    global waypoint
    global stage
    global timerPlay
    waypoint=random.choice(list(arrow.keys()))
    stage = "PLAY"
    timerPlay = threading.Timer(2.0, timeOut)
    timerPlay.start()

def checkPoint(inputKey):
    global waypoint
    global stage
    global timerCheck
    if inputKey == "empty" or inputKey == waypoint:
        waypoint = "wrong"
    else:
        waypoint = "right"
    timerPlay.cancel()
    stage = "CHECK"
    timerCheck = threading.Timer(1.0, creatGlyph)
    timerCheck.start()

def timeOut():
    checkPoint("empty")

def getKey():
    if GPIO.input(AButtonPin)==1 and GPIO.input(BButtonPin)==0:
        checkPoint("right")
    elif GPIO.input(AButtonPin)==0 and GPIO.input(BButtonPin)==1:
        checkPoint("left")

def main():
    creatGlyph()
    while True:
        if stage == "PLAY":
            display(arrow[waypoint])
            getKey()
        elif stage == "CHECK":
            display(check[waypoint])

def destroy():
    global timer1
    GPIO.cleanup()
    timerPlay.cancel()  # cancel the timer
    timerCheck.cancel()

if __name__ == '__main__':
    setup()
    try:
        main()
    except KeyboardInterrupt:
        destroy()

コードの 説明

1.1.6 LEDドットマトリックス に基づいて、 このレッスンでは 2 ボタンを追加して面白いゲームデバイスを作成します。 したがって、ドットマトリックスにあまり詳しくない場合は、1.1.6 LEDドットマトリックス を参照してください。

プログラム全体のプロセスは次のとおりである:

_images/notnot3.png
  1. 矢印の方向をランダムに選択し、 タイマー1 を生成する。

  2. ドットマトリックスに対応する矢印画像を表示する。

  3. ボタン入力を判断する。ボタンが押されるか、 タイマー1 が時間切れを想起させると、判定が開始される。

  4. 判定結果に基づいて画像を表示する。その間、 タイマー2 を生成する。

  5. タイマー2 が時間切れを想起させると、 ステップ1 を再実行する。

def main():
    creatGlyph()
    while True:
        if stage == "PLAY":
            display(arrow[waypoint])
            getKey()
        elif stage == "CHECK":
            display(check[waypoint])

main() には実行中のプロセス全体が含まれている。

プログラムが起動したら、最初に1回だけ createGlyph() を呼び出してから、ループを開始します。

ループ内:PLAYモードでは、ドットマトリックスに矢印パターンが表示され、ボタンの状態が確認されます。 チェックモードの場合、表示されるのは「x」または「√」です。

arrow={
    #"down" :[0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF],
    #"up":[0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF],
    "right" : [0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF],
    "left":[0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF]
}
check={
    "wrong":[0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF],
    "right":[0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF]
}

ここで、辞書 矢印を使用して、LEDドットマトリックス上で上、下、左、右の方向に矢印パターンを表示できます。

上下が付注され、必要に応じて解除できる。

辞書 チェックは、「×」と「√」の2つの画像を表示するために使用されます。

def display(glyphCode):
    for i in range(0, 8):
        hc595_shift(glyphCode[i])
        hc595_shift(0x80>>i)
        GPIO.output(RCLK, GPIO.HIGH)
        GPIO.output(RCLK, GPIO.LOW)

指定したパターンをドットマトリックスに表示する。

def creatGlyph():
    global waypoint
    global stage
    global timerPlay
    waypoint=random.choice(list(arrow.keys()))
    stage = "PLAY"
    timerPlay = threading.Timer(2.0, timeOut)
    timerPlay.start()

関数 createGlyph() を使用して、方向(配列 arrow[] の要素の単語属性:"left"、"right" ...)をランダムに選択する。 ステージを「PLAY」に設定し、2秒の目覚まし時計機能を開始する。

arrow.keys(): 矢印配列のキー「右」と「左」を選択する。

list(arrow.keys()) : これらのキーを配列に結合する。

random.choice(list(arrow.keys())) : 配列内の要素をランダムに選択する。

したがって、 waypoint = random.choice(list(arrow.keys())) の結果は「右」または「左」になります。

def checkPoint(inputKey):
    global waypoint
    global stage
    global timerCheck
    if inputKey == "empty" or inputKey == waypoint:
        waypoint = "wrong"
    else:
        waypoint = "right"
    timerPlay.cancel()
    stage = "CHECK"
    timerCheck = threading.Timer(1.0, creatGlyph)
    timerCheck.start()

checkPoint() はボタン入力の現在の状態を検出する:

ボタンが押されていないか、 矢印と同じ方向のボタンが押されている場合、 waypoint の割り当てられた値は wrong 、 ドットマトリックスに x が表示されます。

それ以外の場合、ウェイポイントは正しく、「 √ 」が表示される。

これで、ステージは 「 CHECK 」 になり、 1秒のタイマー timerCheck を開始して、関数 creatGlyph() を1秒で呼び出します。

def timeOut():
    checkPoint("empty")

関数 timeout() で、 checkPoint() のパラメーターを「empty」に設定します。

def getKey():
    if GPIO.input(AButtonPin)==1 and GPIO.input(BButtonPin)==0:
        checkPoint("right")
    elif GPIO.input(AButtonPin)==0 and GPIO.input(BButtonPin)==1:
        checkPoint("left")

getKey() は、これら2つのボタンの状態を読み取り、 右ボタンが押された場合、 checkPoint() のパラメーターは 右 です。 左ボタンが押された場合、パラメータは 左 です。

現象画像
_images/image281.jpeg

Python ビデオコース (Pi 5用ではない)

この簡潔なPythonビデオコースで、ラズベリーパイの世界に飛び込みましょう。初心者から趣味人まで、どなたでも最適です。 ラズベリーパイの機能紹介から始まり、 Pythonプログラミングの基礎、GPIOピン制御、センサー統合を含む一連のガイドを提供します。 LEDやLCDディスプレイなどの主要部品を探索するインタラクティブなプロジェクトを通して進行します。 このコースは、実践的な実行を通じて複雑な概念をアクセスしやすくすることで、プログラミングおよびハードウェアインターフェースのための必須スキルを装備します。 デジタル世界でラズベリーパイの潜在能力を解き放つために、私たちに参加しましょう。

警告

これらのビデオは、Raphael Kitと呼ばれる私たちの別のキットの一部です。しかし、このスイートでもいくつかのコンテンツを使用することができますが、それによって特定のレッスン番号に中断が生じる場合があります。

プロジェクト

Video 1: 最初の起動

この動画では、基本的なセットアップから高度なプロジェクトまで、あらゆることを網羅するRaspberry Piチュートリアルシリーズを紹介しています。 回路、センサー、GPIOピンに焦点を当てた徹底的な学習アプローチを強調しています。SunFounderがこのシリーズをスポンサーしており、 包括的で手頃な価格のRaspberry Piキットを提供しています。これからのレッスンには、Raspberry Piのセットアップ、 基本的なLinuxの使用、Pythonの概要、GPIOピンの使用が含まれます。また、必要なハードウェアについても議論しており、 Raspberry Piモデル、SDカード、電源、HDMIアダプターが含まれます。 別の動画では、Raspberry Piデスクトップインターフェースのカスタマイズに焦点を当て、 パネル構成、アプレット管理、テーマ設定、トラブルシューティングのヒントをカバーしています。

  1. 体系的な教育リソースへの需要に応えるためのRaspberry Piチュートリアルシリーズの紹介。

  2. プロジェクトベースの学習ではなく、包括的な学習に重点を置く。

  3. Arduinoとの差別化のため、回路、センサー、GPIOピンに焦点を当てる。

  4. SunFounderのスポンサーシップにより、包括的で手頃な価格のRaspberry Piキットを提供。

  5. 基本的なセットアップ、Linuxの使用、Python、GPIOピンを含む今後のレッスンの概要。

  6. Raspberry Piモデル、SDカード、電源、HDMIアダプターなど、必要なハードウェアの説明。

  7. パネルレイアウト、アプレット、スペーサー、テーマなど、Raspberry Piデスクトップインターフェースのカスタマイズオプション。

  8. アイコンの欠如やパネル要素の誤配置など、一般的な問題に対するトラブルシューティングのヒント。

動画

Video 2: Raspberry PiでLinuxの基本とコマンドラインの基礎をマスターする

このチュートリアルでは、Raspberry Pi上でLinuxの基本とコマンドラインの基本を総合的に学ぶことができます。 必要なコマンド、ファイルシステムのナビゲーション、ファイル管理、ソフトウェアのインストール、スーパーユーザーモード、 ファイル操作、パス構造、ベストプラクティスについてカバーしています。ディレクトリのナビゲーション、ファイルの作成、名前変更、 削除、ソフトウェアパッケージのインストール、特権コマンドの実行、ディレクトリの管理、再帰的操作の実行、 nanoテキストエディタを使用したファイルの編集、パス構造の理解、ターミナル内のファイルタイプの色分けの利用方法を学びます。

  1. ファイルシステムのナビゲーション: cd、ls、pwdコマンドを使用したディレクトリのナビゲーションを学ぶ。

  2. ファイル管理: touch、mv、rmコマンドを使用したファイルの作成、名前変更、削除を理解する。

  3. ソフトウェアインストール: apt-getとsudoコマンドを使ったソフトウェアパッケージのインストールを探る。

  4. スーパーユーザーモード: スーパーユーザーモードと、特権コマンドを実行するためのその適用についての洞察を得る。

  5. ディレクトリ管理: mkdirとrmdirコマンドを使用してディレクトリを作成および削除する方法を学ぶ。

  6. 再帰的操作: rm -rコマンドを使用してファイルとディレクトリを再帰的に削除する方法を理解する。

  7. ファイル編集: コマンドラインから直接ファイルを作成および編集するためのnanoテキストエディタを探る。

  8. パス構造: 効果的なファイルシステムナビゲーションのための絶対および相対パス構造についての洞察を得る。

  9. Linuxファイルシステムのナビゲーション: Linuxファイルシステム階層のナビゲーションの基本を理解する。

  10. 色分け: ターミナルでファイルタイプを簡単に識別するための色分けについて学ぶ。

ビデオ

Video 3: 一回のセッションでPythonの基本をマスター

これらのチュートリアルは、Raspberry Piのファン、初心者、そして重要なプログラミング概念を把握したい人向けにカスタマイズされた、Pythonプログラミングの包括的な紹介を提供します。 ビデオは変数、配列、多次元配列、条件文、ループ、その他のPythonの特徴など、さまざまなトピックをカバーしています。

  1. Python vs. Arduino: Pythonのインタープリテッド言語とArduinoのコンパイル言語の違いを理解する。

  2. Pythonの構文と変数: Pythonは変数を明示的に宣言せずに扱い、整数、浮動小数点数、文字列など様々なデータ型をサポートしています。

  3. 配列: Pythonの配列は柔軟で、異なるデータ型の複数の値を保持することができます。

  4. 多次元配列: データを行と列で整理するのに重要で、画像処理のようなプロジェクトに理想的です。

  5. 配列要素へのアクセス: インデックスをマスターして配列要素にアクセスする方法を学ぶ、開始はゼロからです。

  6. 追加のPython特徴: 配列への追加や文字列内のインデクシングなど、Pythonプログラミングのレパートリーを拡大する洞察を得る。

  7. 変数への値の割り当て

  8. ユーザー入力の取得: 'input()'関数を使用してユーザーに入力を促す。

  9. 条件文: 意思決定のための'if', 'elif', 'else'文を実装する。

  10. 算術演算: 実行

ビデオ

Video 4: GPIOピンの理解と使用

この包括的なチュートリアルは、Raspberry PiのGPIOピンの基礎と、Pythonプログラミングによるその使用法をカバーしています。視聴者はGPIOピンのセットアップ方法、LEDの制御、遅延の導入、使用後のGPIOリソースのクリーンアップ方法を学びます。さらに、実践的な応用を通じて学習を強化するための宿題が提供されます。

  1. Raspberry Pi GPIOピンとその番号付けシステムの紹介。

  2. ブレッドボードの構成と使用法の説明。

  3. LED回路図の概要。

  4. 回路図をブレッドボード上の物理的なコンポーネントに翻訳するデモンストレーション。

  5. プロジェクト中にコンポーネントを整理して整頓するためのヒント。

  6. LEDの足の長さなど、コンポーネントの向きを正しく識別することの重要性。

  7. gpio.setmode() および gpio.setup() 関数を使用したGPIOピンのセットアップ。

  8. gpio.output() 関数と状態値を格納する変数を使用したLEDの制御。

  9. time.sleep() 関数を使用したPythonプログラム内での遅延の導入。

  10. gpio.cleanup() 関数による適切なリソース管理。

  11. 課題: ユーザー入力に基づいてLEDを点滅させるPythonプログラムを書く。

  12. 視聴者へのヒント: 使用後のGPIOピンをクリーンアップすることの重要性を強調し、学習の検証のために宿題の解答を共有する。

ビデオ

宿題の解答

Video 5: 二進数の理解

コンピューティングにおける二進数の重要性を探り、二進算の基本を学びます。LEDと抵抗を使用して5桁の二進カウンターを作成する、Raspberry Piの実践的な宿題に取り組みましょう。

  1. 二進数の基礎: コンピュータは二進数、すなわちゼロと一を使ってすべての計算を行います。

  2. データ表現: 二進数は、数値からテキスト、画像までさまざまなデータタイプを符号化します。

  3. ハードウェアコンポーネント: オン・オフスイッチがコンピューター内の二進表現の基礎を形成する方法を学びます。

  4. 二進算: 従来の繰り上げ方法を反映した二進加算のプロセスを理解します。

  5. Raspberry Pi宿題: LEDと抵抗を使用して5桁の二進カウンターを作成する、実践的な課題に挑戦します。

ビデオ

宿題の解答

ビデオ6: GPIO入力、プルアップ抵抗とプルダウン抵抗の理解

Paul McWhorterのこの包括的なチュートリアルで、プルアップ抵抗とプルダウン抵抗の重要性と、Raspberry PiでのGPIO入力の実践的な実装を学びます。

  1. GPIO入力の基本: GPIOピンからのデジタル入力の読み取り方を学ぶ。

  2. 回路セットアップ: 押しボタン、抵抗、マイクロコントローラーでのセットアップデモ。

  3. GPIOピンの設定: 入力モードの設定とPythonコードでの読み取り方。

  4. 浮遊入力の防止: プルアップ/プルダウン抵抗での安定化の方法。

  5. プルアップ&プルダウン抵抗: スイッチの状態に応じた入力ピンの電圧接続方法。

  6. 機能性: スイッチの開閉による回路の振る舞いと論理レベルの影響。

  7. 実装: ブレッドボード上に回路をセットアップする手順。

  8. 宿題: LED制御の実践と解決策のYouTube共有を奨励。

ビデオ

宿題の解答

Video 7: ボタンスイッチからのGPIO入力

Raspberry PiのGPIOピン内蔵のプルアップ抵抗を使用して、スイッチやプッシュボタンのGPIO回路を簡素化する方法について学びます。これには、概念のデモンストレーション、回路セットアップ、LEDをトグルするPythonコード例が含まれます。

  1. GPIO回路におけるプルアップ抵抗とプルダウン抵抗を理解する。

  2. プッシュボタン、プルアップ抵抗、LEDを使用した回路セットアップをデモンストレーションする。

  3. Raspberry PiのGPIOピン内蔵のプルアップ抵抗を使用する概念を紹介する。

  4. GPIOピン設定で内蔵プルアップ抵抗をアクティブにする方法を説明する。

  5. プッシュボタンを使用してLEDをトグルするPythonコード例を提供する。内蔵プルアップ抵抗を利用します。

  6. 実用的なアプリケーションでのトグルスイッチの重要性を強調し、既存の回路を使用してトグルスイッチを実装する宿題を割り当てる。

ビデオ

Video 8: ボタンをトグルスイッチとして使用しLEDの制御を行う

Raspberry PiとPythonプログラミングを使用して、トグルLED回路を作成する方法について学びます。

  1. 回路セットアップ: Raspberry PiのGPIOピンに接続されたLEDとプッシュボタンスイッチのセットアップ。

  2. Pythonプログラミング: RPi.GPIOライブラリを使用してGPIOピンを制御し、プッシュボタンスイッチの状態を読み取る。

  3. トグルロジック: プッシュボタンスイッチの状態に基づいてLEDをトグルするPython内のロジックを実装する。

  4. 変数管理: プッシュボタンスイッチとLEDの現在および以前の状態を追跡するために変数を使用する。

ビデオ

Video 9: GPIOピンを使用したPWMによるアナログ出力のシミュレーション

このビデオでは、Raspberry PiのGPIOピンを使用したPWM(パルス幅変調)の基本について案内し、LEDの明るさ制御とリアルタイムな周波数調整をデモンストレーションします。

  1. PWMとそのアナログ信号のシミュレーションにおける役割の紹介。

  2. デューティサイクルの理解とPWM信号におけるその重要性。

  3. Raspberry PiのGPIOピンを使用したPWMによるLEDの明るさ制御の実践デモンストレーション。

  4. オシロスコープを使用してPWM信号を視覚化し、デューティサイクルと周波数を確認。

  5. 周波数の説明とPWM信号への影響。

  6. Raspberry PiのターミナルでPythonコマンドを使用してデューティサイクルと周波数をリアルタイムに変更するデモンストレーション。

  7. プッシュボタンを使用した正確なLEDの明るさ制御を含む宿題。実践的な学習と実験を促進します。

  8. LED、モーター、センサーなど様々なコンポーネントを制御する際のGPIOピンの重要性。

ビデオ

Video 10: 2つのプッシュボタンで調光可能なLEDを作る

在本教程中,我们将使用 Raspberry Pi 的 GPIO 引脚构建一个可调光 LED 电路,以实现平滑的亮度控制。Paul McQuarter 逐步演示了从电路设置到编码实现的过程。

  1. 回路セットアップ: Raspberry PiのGPIOピンを使用して調光可能なLED回路を構築し、制御のためにプッシュボタンを利用する方法の説明とデモンストレーション。

  2. Pythonコーディング: PWM制御とLEDの明るさ制御のための指数スケールをそれぞれ実装するPythonコードのウォークスルー。

  3. PWMの原理: PWMデューティサイクルの理解とLEDの明るさ制御への応用。

  4. 指数スケール: コーディングにおいてスムーズかつ線形な明るさ制御を実現するために指数スケールを利用する。

  5. 対数概念: 明るさ調整のための特定のボタン押下数に必要な定数を決定するために対数を適用する。

  6. 非線形の明るさ調整: スムーズな明るさの遷移のためのデューティサイクルの非線形変化を探る。

  7. 同期問題: PWM周波数とカメラのスキャンレート間の同期問題に対処する。

  8. トラブルシューティングと洗練: LEDの調光機能を最適化するためのコードのデバッグと洗練技術。

ビデオ

Video 11: RGB LEDの理解と使用方法

このチュートリアルでは、Raspberry PiのGPIOピンを使用してRGB LEDを制御する方法について学びます。セットアップ、配線、そしてPythonコーディングの手順をカバーしています。

  1. RGB LEDコンポーネント: RGB LEDの赤、緑、青のピンを理解する。

  2. GPIOセットアップ: Raspberry Pi上でのGPIOセットアップにおける物理ピン番号システムについて学ぶ。

  3. 配線ガイド: 電流制限抵抗を含む、Raspberry PiのGPIOピンにRGB LEDを配線するためのステップバイステップガイドに従う。

  4. Pythonコーディング: GPIOピンを使用してRGB LEDの色を制御するPythonコードのデモンストレーションを見る。

  5. トラブルシューティングのヒント: コンポーネントと接続の効果的な取り扱いのための有用なヒントを得る。

ビデオ

Video 12: プッシュボタンによるRGB LEDの制御

Raspberry Piプラットフォームを使用してRGB LEDを制御する方法を探究します。ハードウェアのセットアップ、コードの組織化、GPIOピンの設定、カラーミキシング、調光可能なLED制御、デバッグ、プロジェクトの拡張可能性についてカバーしています。

  1. ハードウェアセットアップ: RGB LED、ボタン、GPIO接続を設定します。

  2. コードの組織化: 保守が容易になるようにコードを体系的に整理します。

  3. GPIOピンセットアップ: 入出力機能のためのGPIOピンを設定します。

  4. メインループの実装: ボタンの状態を監視し、LEDの状態を更新するメインループを作成します。

  5. デバッグとテスト: デバッグ手順を通じて、ハードウェアとソフトウェアの機能を確実にします。

  6. RGB LEDカラーミキシング: 赤、緑、青を使用した色の組み合わせを実験します。

  7. 調光可能なLED制御: 正確な色と明るさの調整のためにLEDを調光する方法を探究します。

  8. 回路トラブルシューティング: 接続不良などの回路問題を特定し、解決します。

  9. プログラミングロジック: RGB LEDの振る舞いを制御するためのコードロジックを開発します。

  10. プロジェクトの拡張: 調光可能なLED制御などの高度な機能でプロジェクトを拡張することを検討します。

ビデオ

Video 13: プッシュボタンでRGB LEDの色を設定する

このビデオでは、Raspberry Piを使ってボタンでRGB LEDを制御する方法をデモンストレーションしています。ハードウェアのセットアップ、コーディング、トラブルシューティングを網羅しています。

  1. Raspberry Pi GPIOにRGB LEDとボタンを接続する方法を学びます。

  2. デバッグが容易になるように、コードを体系的に整理する重要性を理解します。

  3. 入力(ボタン)と出力(LED制御)の両方のGPIOピンをセットアップします。

  4. ボタンの状態を連続的に読み取り、LEDの状態を更新するメインループを実装します。

  5. 適切な機能性を保証するために、デバッグとテストの手順に従います。

  6. 赤、緑、青の値を調整して、色のスペクトラムを作り出すカラーミキシングを探求します。

ビデオ

Video 14: Raspberry PiにVisual Pythonをインストールする

このビデオでは、Raspberry Piを使用してボタンでRGB LEDを制御する方法に焦点を当て、Visual Pythonのインストール、シンプルな3Dアニメーションの作成、および以前のレッスンからのLED制御コードとの統合についてデモンストレーションしています。チュートリアルでは、Visual Pythonのインストール、既存の回路とRGB LED制御のためのコードの統合、LEDの状態を表す3Dアニメーションの作成、LED制御に使用されるPWMデューティサイクルとVisual Python内の色表現の変換の理解、コード実行と実際のLEDと仮想LEDのキャリブレーションの問題のトラブルシューティング、さらにアニメーションとLED制御のカスタマイズと最適化の可能性の探求についてカバーしています。

  1. Raspberry PiにVisual Pythonをインストールし、環境を設定します。

  2. 以前のレッスンからの既存の回路とRGB LED制御のためのコードを統合します。

  3. LEDの状態を表すためにVisual Pythonを使用して3Dアニメーションを作成します。

  4. LED制御に使用されるPWMデューティサイクルとVisual Pythonでの色表現の間の変換を理解します。

  5. コード実行と実際のLEDと仮想LED間のキャリブレーションに関する問題のトラブルシューティングを行います。

  6. アニメーションとLED制御のさらなるカスタマイズと最適化の可能性を探求します。

ビデオ

Video 15: ADC0834を使用したRaspberry Piでのアナログ入力

ADC0834アナログ・デジタルコンバーターを使用してRaspberry Piでアナログ入力を有効にする方法を学びます。ハードウェアのセットアップ、ライブラリのインストール、そしてPython開発のためのThonny IDEへの移行を含みます。

  1. アナログ入力とRaspberry PiにADCが必要な理由についての紹介。

  2. ADC0834チップのためのハードウェアセットアップとGPIOピン接続。

  3. コンポーネントのための適切な電源とグラウンド接続の確立。

  4. Python用ADC0834ライブラリのインストールと使用。

  5. クリーンで効率的なコーディングのための現代的なIDE、Thonnyへの移行。

  6. プログラミング前に接続をトラブルシューティングして確認するためのベストプラクティス。

  7. ライブラリインストール: Raspberry Pi用のADCライブラリをインストールします。

  8. Pythonセットアップ: ライブラリコードをPythonファイルに保存し、正しいディレクトリに移動します。

  9. GPIOの使用: GPIOピンを使用してアナログ入力を読み取るPythonプログラムをセットアップします。

  10. アナログ読み取り: ポテンショメーターからアナログ値を連続的に読み取るPythonスクリプトを書きます。

  11. チャンネル切り替え: ADCチップの異なるチャンネル間での切り替えをデモンストレーションします。

  12. 宿題: ポテンショメーターの位置で制御される調光可能なLEDを作成します。

ビデオ

Video 16: ポテンショメーターで制御する調光可能なLEDの作成

このビデオでは、Raspberry Pi、ADC-0834アナログ・デジタルコンバーター、PWM(パルス幅変調)技術を使用して調光可能なLEDを作成する方法をデモンストレーションします。ハードウェアのセットアップからPythonでのコーディングまで、包括的なガイドを提供します。

  1. 紹介: SunFounderが提供するチュートリアルシリーズの概要。

  2. 宿題の課題: 前回のレッスンの課題、ポテンショメーターで制御される調光可能なLEDを作成することのまとめ。

  3. ハードウェアセットアップ: 必要なコンポーネント、Raspberry Pi、ADC-0834、ポテンショメーター、および電流制限抵抗付きLEDの説明。

  4. GPIOピンセットアップ: GPIOピンのセットアップとLED制御のためのPWMの初期化。

  5. Pythonコーディング: Thonnyを使用したPythonでのコーディングのステップバイステップガイド。ライブラリのインポート、ピンセットアップ、デューティサイクル計算をカバーします。

  6. 数学的計算: ポテンショメーターの読み取り値をLEDの明るさレベルにマッピングする際の数学的な説明。

  7. デモンストレーション: 調光可能なLED機能のライブデモンストレーション。

  8. 次の宿題の課題: RGB LEDと複数のポテンショメーターを使用して色の混合を行う次の課題の発表。

  9. 謝辞: Patreonサポーターの認識と、将来のコンテンツをサポートするために寄付を検討するよう視聴者に促すこと。

ビデオ

Video 17: RGB LEDで任意の色を混合する

このビデオは、Raspberry PiとADC0834チップを使用してRGB LEDの制御を構築し、マスターするプロセスについて説明しています。SunFounderが提供するチュートリアルシリーズの紹介から始まり、Raspberry Piプロジェクトに焦点を当てています。前回のエピソードの課題は調光可能なLEDの作成でしたが、今回はそれをRGB LEDに置き換えることに焦点を当てています。

回路の概要には、RGB LEDセットアップのためのADC0834チップ、ポテンショメーター、抵抗の利用が含まれます。配線指示では、清潔な構築とGPIOピンの割り当てのために直線ジャンパーワイヤーの使用の重要性が強調されます。RGB LED制御のコーディングに進むと、PythonとThonny IDEが使用され、各色チャネルのPWM制御のためにLED制御プログラムを変更します。

  1. SunFounderが提供するRaspberry Piプロジェクトのためのチュートリアルシリーズの紹介。

  2. 前回のエピソードの課題は調光可能なLEDの作成でしたが、今回はRGB LEDに置き換えることが課題です。

  3. 回路の概要には、RGB LEDセットアップのためのADC0834チップ、ポテンショメーター、抵抗が含まれます。

  4. 清潔な構築とGPIOピンの割り当てのために直線ジャンパーワイヤーを使用する重要性。

  5. 各色チャネルのPWM制御のためにPythonとThonny IDEを使用してRGB LED制御をコーディング。

  6. RGB LEDの制御のためにRaspberry Pi上でPWMのセットアップ。

  7. アナログ入力値の読み取りのためのADC0834の初期化。

  8. LEDの明るさを決定するためにADC0834チップからアナログ値を読み取る。

  9. 正確なPWM制御のためにアナログ値をデューティサイクルに変換するデューティサイクル変換。

  10. アナログ入力値に基づいてLEDの明るさを動的に調整。

  11. 効率的なLED制御のためのコードの組織化とトラブルシューティング。

ビデオ

Video 18: Raspberry Piでジョイスティックを使用する

SunFounderキットを使用してRaspberry Piプロジェクトにジョイスティックを組み込む方法を学びましょう。セットアップ、配線、コーディング、テストについてカバーします。

  1. 紹介: Raspberry Piプロジェクトでジョイスティックを使用する多様性を探ります。

  2. SunFounderキットデモンストレーション: SunFounderキットに含まれるコンポーネントの概要。

  3. ジョイスティックの理解: ジョイスティックのコンポーネントと機能性の説明。

  4. 配線セットアップ: Raspberry PiのGPIOピンにジョイスティックを配線するステップバイステップガイド。

  5. コーディングプロセス: PythonとRPi.GPIOライブラリを使用して、ジョイスティックからのアナログ値を読み取り、ボタン押下を検出します。

  6. テストと検証: テストを通じてジョイスティックとボタンの適切な機能性を確認します。

ビデオ

Video 19: Raspberry Piからサーボモーターを簡単に制御する

Raspberry Piを使用してサーボモーターを制御する方法を、Paul McQuarterがセットアップ、コーディング、テストプロセスを通じて案内します。

  1. ハードウェアセットアップ: Paulは、サーボモーターをRaspberry Piに正しく配線し、整列させる方法をデモンストレーションします。

  2. 電源に関する考慮事項: 大型のサーボを使用する際はRaspberry Piを損傷から守るために外部電源を使用する重要性を説明します。

  3. PWMの基礎: パルス幅変調(PWM)がPWM信号のデューティサイクルを調整することにより、サーボモーターの位置をどのように制御するかを理解します。

  4. Pythonコード実装: GPIOピンを使用してサーボモーターをセットアップし、制御するためのPythonコードのウォークスルー。

  5. テストとキャリブレーション: 異なるPWMパーセンテージを入力することにより、サーボモーターの動作範囲をテストし、キャリブレーションする方法を学びます。

  6. エラーハンドリング: Pythonのtry-exceptブロックを使用してGPIOピンの適切なクリーンアップを保証し、エラーを処理する方法を発見します。

ビデオ

Video 20: ポテンショメーターでサーボの位置を制御する

このビデオでは、ポテンショメーターとRaspberry Pi GPIOを使用してサーボ位置を制御する方法をデモンストレーションします。回路セットアップ、Pythonコーディング、ADC、PWM、数学的計算、エラーハンドリング、接続の重要性についての説明が含まれます。

  1. 回路セットアップ: Raspberry Pi用ADC0834を使用した前回のレッスンのアナログ入力回路のレビュー。

  2. サーボセットアップ: 回路内でのサーボの設定方法についての指示、配線と電源に関する考慮事項を含む。

  3. ADCとPWMを理解する: アナログ・デジタルコンバーター(ADC)とパルス幅変調(PWM)の概念に慣れる。

  4. アナログ信号の読み取り: Raspberry Piに接続されたポテンショメーターからアナログ信号を読み取る方法を発見する。

  5. PWMパーセンテージの計算: 取得したアナログ信号値に基づいてPWMパーセンテージを計算する式を学ぶ。

  6. サーボモーターの制御: 計算したPWMパーセンテージを適用してサーボモーターの位置を制御するプロセスを探る。

  7. 同期: ポテンショメーターの位置とサーボモーターの位置の間の同期を確保し、正確な制御を行う。

  8. 数学的計算: ポテンショメーターの読み取りに基づいてPWM値を決定するために使用される数学的計算の説明。

  9. エラーハンドリング: プログラム終了とGPIOのクリーンアップのためのtry-exceptブロックの実装。

  10. 接続の重要性: 正確な読み取りと出力のために信頼性の高い接続を確立することの重要性を理解する。

ビデオ

Video 21: HC-SR04超音波センサーを使ったエコーロケーション

このチュートリアルでは、HC-SR04センサーを使用してRaspberry Piで超音波距離センサーを作成するプロセスを説明します。このビデオでは、エコーロケーションの原理を説明し、必要なコンポーネントを紹介し、配線セットアップをデモンストレーションし、コーディングプロセスをステップバイステップで説明します。正確な距離測定のためのコード実行における正確なタイミングの重要性を強調し、良いエンジニアリングの実践を促します。

  1. エコーロケーションの紹介: コウモリやクジラに着想を得た、音を使って物体の位置を検出する方法。

  2. コンポーネントの概要: HC-SR04超音波センサーとRaspberry Piへの接続についての紹介。

  3. 配線セットアップ: 電源、グランド、トリガー、エコーのためにHC-SR04センサーをRaspberry PiのGPIOピンに接続する。

  4. コーディングプロセス: 超音波パルスを生成し、センサーをトリガーし、エコーの帰還時間を測定するPythonコードのウォークスルー。

  5. タイミングの考慮: 正確な距離測定のための正確なタイミングの重要性。

  6. 良いエンジニアリングの実践: 実装前に計画とコードの理解を重視する。

  7. エコーピンの待機: エコーピンが高くなるのを待つためにwhileループを使用する。

  8. 開始時間の記録: 測定開始をマークするために、エコーピンが高くなったときのシステム時間をキャプチャする。

  9. ピングの移動時間の測定: エコーピンが高くなってから低くなるまでの時間差を決定することにより、ピングの移動時間を計算する。

  10. 単位の変換: 読みやすさのためにピングの移動時間を1万倍する。

  11. 遅延の追加: 複数のエコーを防ぐために各測定後に遅延を導入する。

  12. 距離の計算: 音速とピングの移動時間を使用して目標までの距離を計算する。

ビデオ

Video 22: HC-SR04超音波センサーで距離を測定する

HC-SR04超音波センサーとRaspberry Piを使用して距離を測定する方法を学びます。配線、コーディング、単位変換を含みます。トラブルシューティングのヒントを探索し、距離測定の原理を理解し、実用的な応用を発見し、センサーを使用して音速を実験的に測定する宿題を受け取ります。

  1. 紹介: チュートリアルの概要とスポンサーシップの謝辞。

  2. 前回の課題: 前回のレッスンからのHC-SR04センサー課題の復習。

  3. セットアップと配線: Raspberry Piへの接続を含む配線セットアップの説明。

  4. コード説明: ピンの移動時間と距離を測定するコードを理解する。

  5. トラブルシューティング: コーディングエラーを特定して修正するためのヒント。

  6. 距離測定の理解: 超音波センサーの原理についての説明。

  7. 補正係数: 正確な距離測定のために必要な補正を認識する。

  8. 単位変換: 正確な測定のための単位変換についての議論。

  9. 実用的な応用: 超音波センサーの実世界での使用を探る。

  10. Fusion 360の統合: Raspberry Piのスキルと3Dプリントの知識を組み合わせることを奨励する。

  11. 宿題: センサーを使用して音速を実験的に測定する課題。

ビデオ

Video 23: 超音波センサーを使用して音速を測定する

このステップバイステップのチュートリアルでは、Raspberry PiとHC-SR04超音波センサーを使用して音速を測定する方法を学びます。

  1. 音速を測定するためのHC-SR04超音波センサーの使用についての紹介。

  2. 距離、速度、時間の基本方程式を理解する。

  3. Raspberry Piと超音波センサーを使用したハードウェアセットアップ。

  4. センサーを制御し、音速を計算するPythonコードの作成。

  5. 最終的な速度計算のための単位変換を行うための次元分析の実行。

  6. 定規とターゲットを使用したセットアップと測定プロセスの実践的デモンストレーション。

ビデオ

Video 24: Raspberry PiでPIR動作センサーを使用する

Paul McQuarterによるこのチュートリアルでは、Raspberry PiでPIR動作センサーを使用する方法について学びます。彼はセンサーのコンポーネント、セットアップ、コーディング、動作検出プロジェクトのためのセンサーのテストについて説明します。

  1. PIR動作センサーの紹介: PIR動作センサーが何であり、どのように機能するかを理解します。

  2. センサーコンポーネント: 赤外線センサーやフレネルレンズを含むPIR動作センサーの主要コンポーネントについて学びます。

  3. 検出メカニズム: センサーがどのように動作と熱を検出し、正確にトリガーするかを発見します。

  4. センサーセットアップ: PaulがGPIOピンを使用してPIRセンサーをRaspberry Piに接続する方法をデモンストレーションします。

  5. センサーのコーディング: RPi.GPIOライブラリを使用して動作を検出する簡単なPythonスクリプトを書く方法を見ます。

  6. テストと微調整: 最適なセンサー性能のためのテスト手順と微調整オプションについて学びます。

ビデオ

Video 25: DHT-11センサーで温度と湿度を測定する

このチュートリアルでは、DHT11温度湿度センサーをRaspberry Piに接続し、Pythonを使用してデータを読み取る方法を学びます。

  1. 紹介: SunFounderが提供するRaspberry Piチュートリアルシリーズにご参加ください。

  2. 必要なコンポーネント: Raspberry Pi、ジャンパーケーブル、DHT11センサー、10k抵抗を用意しましょう。

  3. 配線指示: センサーを損傷しないように、コンポーネントを正しく配線するための詳細な指示に従います。

  4. Pythonライブラリのインストール: DHT11センサーとやり取りするために必要なPythonライブラリのインストール方法を学びます。

  5. コードの実装: センサーから温度と湿度データを読み取り、ターミナルに表示するPythonコードを書きます。

  6. コードの実行: センサーの読み取り値を解釈するコードを実行してみましょう。

  7. 今後のプロジェクト: SunFounderキットからのコンポーネントを組み合わせた潜在的なプロジェクトを探求します。

ビデオ

Video 26: I2Cを使用したLCD1602 LCDディスプレイの使用方法

Paul McWhorterによるこの包括的なチュートリアルで、I2C通信を使用してLCD 1602ディスプレイをRaspberry Piにセットアップし、接続する方法を学びます。

  1. Raspberry Piキットを提供してくれたSunFounderへのスポンサーシップの謝辞。

  2. プロジェクトの説明: I2Cを使用してRaspberry PiにLCD 1602ディスプレイを接続する。

  3. I2C通信の利点: 以前の方法と比べて4つの接続のみで配線が簡素化される。

  4. ハードウェアセットアップ: ブレイクアウトボードを介してLCDディスプレイをRaspberry PiのGPIOピンに接続する。

  5. Raspberry PiでのI2Cの設定: raspi-configを介してI2Cインターフェイスを有効にする。

ビデオ

Video 27: LCDディスプレイを使用した温度と湿度のシステムの構築

このチュートリアルでは、視聴者はRaspberry Pi、DHT11センサー、LCDディスプレイ、押しボタンを使用して温度と湿度を感知するデバイスを構築する方法を学びます。このビデオでは、プロジェクトに必要なハードウェアセットアップとPythonコーディングについて詳細なガイダンスを提供します。

  1. Raspberry Piを使用した温度と湿度を感知するデバイスの構築についての紹介。

  2. 必要なコンポーネントには、Raspberry Pi、DHT11センサー、LCDディスプレイ、押しボタン、メス-オスワイヤー、ジャンパーワイヤーが含まれます。

  3. ハードウェアセットアップは、Raspberry PiをSunFounderブレイクアウトボードに接続し、その後、ジャンパーワイヤーを使用してDHT11センサー、LCDディスプレイ、押しボタンを接続することを含みます。

  4. LCD1602、GPIO、DHT11、timeなどの必要なライブラリの設定。

  5. GPIOモードの設定、DHT11センサー、LCDディスプレイ、押しボタンの初期化を含むコンポーネントの初期化。

  6. GPIO入力を通じてボタンの状態を読み取り、LCDディスプレイ上で華氏と摂氏の読み取りを切り替える。

ビデオ

Video 28: アクティブ・パッシブブザーの理解と使用

この包括的なチュートリアルでは、Raspberry Piプロジェクトにブザーを組み込み、温度センサーアラームシステムを作成する方法を学びます。ハードウェアセットアップ、プログラミング、テスト、コミュニティとのエンゲージメントについてカバーしています。

  1. アクティブブザーとパッシブブザー: アクティブブザーとパッシブブザーの違いと特性を理解します。

  2. ハードウェアセットアップ: ブザー、トランジスター、抵抗器、GPIOピンを正しく接続するための回路図に従います。

  3. プログラミング: ブザーを制御し、温度センサー機能を実装するPythonコードを探索します。

  4. モードトランジション: プログラムモードとモニターモードの間で切り替えるための押しボタンを実装します。

  5. コミュニティとのエンゲージメント: プロジェクトのソリューションをYouTubeで共有し、コミュニティと交流します。

  6. スキルの統合: 以前に学んだコンセプトを適用し、包括的なプロジェクトを開発します。

ビデオ

Video 29: プログラム可能な温度感知アラームを構築する

このビデオでは、Raspberry Piを使用してプログラム可能な温度監視システムとアラームを構築する方法をデモンストレーションします。ハードウェアのセットアップ、Pythonでのコーディング、デバッグ技術について説明します。このチュートリアルは、コードの組織と明瞭さを維持するための構造化されたプログラミングとトラブルシューティング方法を強調しています。

  1. ハードウェアセットアップ: 必要なハードウェアコンポーネントを説明します。これには、Raspberry Pi、ブレイクアウトボード、ADC0834、DHT11温度センサー、トグルボタン、アクティブブザー、トランジスターが含まれます。

  2. プロジェクトの概要: 完成したデバイスとそのコンポーネント、機能をデモンストレーションします。

  3. 回路図の概要: プロジェクトの回路図について議論し、コンポーネント間の接続を強調します。

  4. プログラミング: センサー値の読み取り、モード切り替え、温度閾値に基づくアラームのトリガリングを説明するPythonコードを通じて説明します。

  5. デバッグ: コードとハードウェア接続のエラーを特定し、修正するためのデバッグ技術をデモンストレーションします。

  6. 温度感知のためのアナログからデジタルへの変換。

  7. リアルタイムの温度表示のためのLCDディスプレイのインターフェース。

  8. プログラミングモードとモニタリングモードの間で切り替えるためのボタンによるユーザーインタラクション。

  9. 温度閾値に基づいてアラームをトリガーする。

  10. コードの組織と明瞭さを維持するための構造化プログラミングアプローチ。

ビデオ

Video 30: Raspberry Piで光を検出するフォトレジスターの使用

Raspberry Piプロジェクトにフォトレジスターを組み込んで光の強度を測定し、明るさに基づいてアクションを制御する方法を学びましょう。

  1. フォトレジスターの紹介: 光の強度に応じてフォトレジスターの抵抗がどのように変化するかを学びます。

  2. フォトレジスターの物理学: フォトレジスターの動作に基づく固体物理学の原理を理解します。

  3. 回路の構築: フォトレジスターと負荷抵抗器を使用して電圧分割回路を作成する方法を発見します。

  4. Raspberry Piのプログラミング: ADC0834モジュールを使用してフォトレジスターからアナログ値を読み取るPythonコードを書きます。

  5. 回路のテスト: 回路が照明条件の変化にどのように反応するかを見て、抵抗と電圧の変化を示します。

  6. 実用的な応用: 自動照明システムなどのプロジェクトでフォトレジスターを使用する潜在的な用途を探索します。

ビデオ

Video 31: 暗闇での動きを検出するアラーム

このビデオでは、Raspberry Pi、動作センサー、光センサー、ブザーを使用して侵入者アラームシステムを構築する方法をデモンストレーションし、ハードウェアセットアップとPythonコーディングの両方についてステップバイステップのガイダンスを提供します。

  1. プロジェクトへの紹介: Raspberry Piを使用して侵入者アラームシステムを構築する。

  2. 使用されるコンポーネントの概要: Raspberry Pi、PIR動作センサー、光センサー(ADC-0834)、アクティブブザー、トランジスター(S8550)。

  3. ハードウェアセットアップの説明: コンポーネントを配線し、ブザー、動作センサー、光センサーをRaspberry PiのGPIOピンに接続する方法。

  4. アラームシステムのコーディング: センサー入力を読み取り、動作と暗闇を検出し、それに応じてブザーアラームをトリガーするPythonコードの使用。

  5. システムのテスト: 異なる照明条件での侵入者検出をシミュレートすることにより、アラームシステムの機能性をデモンストレーション。

  6. 将来のプロジェクトの議論: 加速度計、ジャイロスコープ、RFID、カメラなどの追加コンポーネントに関する今後のチュートリアルをプレビューし、さらなるRaspberry Piプロジェクトについて議論。

ビデオ

Video 32: Raspberry Piでキーパッドを理解し、使用する

Raspberry Piプロジェクトにキーパッドを効率的に組み込む方法を学びましょう。入力読み取りに受動的な行列アドレッシングを使用します。

  1. 紹介: Raspberry Piプロジェクトにキーパッドを統合する方法を学びます。

  2. 受動的行列アドレッシング: 効率的なキーパッド入力読み取りのための受動的アドレッシングの概念を理解します。

  3. 配線セットアップ: キーパッドの行と列を使用した配線セットアップを発見します。

  4. GPIOピンの設定: 行のための出力として、列のための入力としてGPIOピンをセットアップします。

  5. キーのラベリング: キーパッド上のキーを簡単に参照するためにマトリックスを作成します。

  6. 実装: キーパッドをプロジェクトに組み込むためのコーディングプロセスに沿って進みます。

ビデオ

Video 33: Raspberry Piプロジェクトにキーパッドを取り入れる方法

このビデオでは、Raspberry Piを使用してキーパッド入力を読み取る方法をデモンストレーションし、回路セットアップ、Pythonコードの実装、そして「スティッキーボタン」問題に対処します。

  1. キーパッドスキャン方法: 行と列を使用したキーパッドスキャンの概念を理解する。

  2. 回路セットアップ: 行と列のためのGPIOピンを設定し、内部プルダウン抵抗の使用を含む。

  3. Pythonコードの実装: 行を活性化し、列を読み取ることによりキーパッド入力を読み取るためのPythonコードのステップバイステップのウォークスルー。

  4. 「スティッキーボタン」問題: 繰り返しボタンが押される問題の特定と解決。

ビデオ

Video 34: Raspberry Pi用キーパッド読取りPythonクラス作成

Raspberry Piに接続されたキーパッドから入力を読み取るPythonクラス作成について学びます。SunFounder提供のチュートリアルシリーズの一環で、キーパッド接続のハードウェアセットアップとPythonでのプログラミング方法に焦点を当てています。

  1. プロジェクト紹介: Raspberry Piを使用したキーパッド入力システム構築。

  2. ハードウェアセットアップ: GPIOを利用したキーパッドの配線説明。

  3. Pythonプログラミング: キーパッドからの入力を読み取るクラスのコード作成方法。

  4. 入力読取り実装: 行と列をスキャンして入力を読み取る機能の実装。

  5. 問題解決: 「粘着ボタン」問題の特定と対策。

  6. 応用: キーパッド機能を包含したPythonライブラリ作成、LCD表示器やカメラとの統合可能性探索。

ビデオ

Video 35: キーパッドとLCDを使ったモバイルRaspberry Piプロジェクトの作成

このチュートリアルでは、入力用のキーパッドと出力用のLCDディスプレイを使用してRaspberry Piアラームシステムを作成する方法、および効率的なプログラムフローのためのPythonコーディング技術について学びます。

  1. プロジェクト紹介: Raspberry Piアラームシステムの構築概要。

  2. コンポーネントセットアップ: キーパッドとLCDディスプレイコンポーネントの設定。

  3. Pythonコーディング: キーパッドとLCDと対話するPythonコードの記述。

  4. スレッディングコンセプト: プログラムフローを改善するためのスレッディングの使用についての議論。

  5. アラームシステムの状態: アラームシステムの異なる状態(アームド、ディスアームド、パスワード変更)の説明。

  6. 宿題: 異なる状態とパスワード検証のためのプログラムフローを実装する課題の割り当て。

ビデオ

Video 36: Raspberry Piでキーパッド入力を監視する方法

Raspberry Piを使ってキーパッドからの入力を読み取り、LCDで出力するアラームシステムを作る方法を学びます。配線方法、スレッディングによるマルチタスキング、コマンド処理、パスワード検証などについて説明します。実用化と展開の重要性も強調されています。

  1. 携帯性と展開: 実世界での応用に向けたプロジェクト。

  2. キーパッドとLCDセットアップ: GPIOピンを使った接続方法。

  3. Pythonコーディング: キーパッド入力の読み取りとLCDへの表示。

  4. スレッディングによる改善: プログラムフローを向上させるスレッディングの利用。

  5. アラームシステムの状態管理: 異なるアラームシステムの状態の説明。

  6. 宿題: 異なる状態のプログラムフローとパスワード検証の実装。

ビデオ

Video 37: キーパッドとLCDを使ったRaspberry Piアラームシステム

Raspberry Piを使用して、キーパッドとLCDディスプレイを組み込んだアラームシステムの構築方法を学びます。配線、Pythonコード、マルチタスキング、エラーハンドリングに重点を置き、実用化を目指します。

  1. 携帯性と展開: デスクトップ超えたアプリケーションへ。

  2. キーパッドとLCDの設定: GPIOピンを介した接続。

  3. スレッディング: タスク同時実行のため。

  4. プログラムフロー: アーム、ディスアーム、パスワード変更の実装。

  5. エラーハンドリング: 正しいプログラム終了の保証。

  6. 視聴者チャレンジ: システムの機能強化提案。

ビデオ

Video 38: Raspberry Piセキュリティシステム

Pythonコードとpygameライブラリを使用して、携帯可能なRaspberry Piアラームシステムに音響アラームを追加する方法を学びます。

  1. ポータブルプロジェクト開発: Raspberry Piを中心に展開可能なプロジェクトを構築する方法を教えるシリーズの一部です。

  2. 音響アラームの追加: pygameライブラリを使用してMP3アラーム音をインポートし再生することで、アラームシステムに音響警告を追加する方法をデモンストレーションします。

  3. 実装詳細: PIRセンサーによって侵入者が検出されたときにアラーム音をロードして再生する手順をステップバイステップで提供します。

  4. カスタマイズオプション: アラームシステムの多様性を高めるための異なるアラーム音を取得して保存する方法についてのガイダンスを提供します。

  5. 宿題: アラームシステムをさらに改善するために、複数のアラームオプションをプログラムする課題を視聴者に挑戦させます。

ビデオ

Video 39: Raspberry Piセキュリティシステム

このRaspberry Piチュートリアルでは、PIR動作センサー、キーパッド、LCDディスプレイを使用したホームセキュリティシステムのアラーム音をカスタマイズする方法を学びます。

  1. SunFounderが提供するRaspberry Piプロジェクトに焦点を当てたチュートリアルシリーズの紹介。

  2. Raspberry Piを使用してLCD、PIR動作センサー、キーパッドの統合を含むホームセキュリティシステムを構築する概要。

  3. アーミング、ディスアーミング、パスワード変更、アラーム音の選択のためのPythonコードの説明。

  4. キーパッド、LCD、PIRセンサーなどのハードウェアコンポーネントを接続して設定するステップバイステップガイド。

  5. ユーザー入力に基づいた複数のアラーム音をプログラミングするデモンストレーションと、一般的なエラーのトラブルシューティングのヒント。

ビデオ

Video 40: Raspberry PiセキュリティプロジェクトをPuttyで遠隔操作

SSHとPuttyを使用してRaspberry Piに遠隔からアクセスし、制御する方法を学びます。これにより、デスクトップ環境に縛られずにプロジェクトの開発が可能になります。

  1. Raspberry PiでのSSH有効化: 遠隔アクセスを可能にするため、raspi-configを通じてSSHを有効にします。

  2. Raspberry PiのIPアドレスの検出: ifconfigを使用してIPアドレスを見つけ、一貫した遠隔アクセスのために静的IPアドレスの割り当てを検討します。

  3. Puttyのダウンロードとインストール: PCにPuttyをダウンロードしインストールして、Raspberry PiへのSSH接続を確立します。

  4. Puttyを使用したRaspberry Piへの接続: Puttyを使用してSSH経由で遠隔からRaspberry Piに接続し、資格情報でログインしてコマンドを遠隔実行します。

  5. Raspberry Piの遠隔制御: Puttyを通じてRaspberry Pi上のプログラムを遠隔で実行し、遠隔アクセスの実用性を示します。

ビデオ

Video 41: Raspberry PiでVNCを使用したリモートデスクトップの設定方法

Windows PCから物理的な周辺機器を必要とせずにRaspberry Piを制御できるように、リモートデスクトップアクセスを設定する方法を学びます。

  1. SunFounder提供のRaspberry Piチュートリアルシリーズの紹介。

  2. 物理的な周辺機器を避けてRaspberry Piにリモートデスクトップアクセスする必要性の説明。

  3. リモート端末アクセス用のPuTTY経由のSSHの使用概要。

  4. フルデスクトップインターフェース用のVNC(Virtual Network Computing)の紹介。

  5. Raspberry PiでVNCを有効にし、表示オプションを設定する手順。

  6. リモート接続のためにRaspberry PiのIPアドレスを知ることの重要性。

ビデオ

Video 42: Raspberry PiとPC間のUDPを使ったデータ送信方法

PythonとUDP(User Datagram Protocol)を使用してRaspberry PiとPC間のクライアントサーバー通信を設定する方法をデモします。サーバーとクライアントのプログラム作成、ソケットの初期化とバインド、データ交換、基本機能の実装について説明します。

  1. クライアントサーバー通信の紹介: リモート接続のクリーンアップの必要性を理解する。

  2. サーバープログラムの作成: Raspberry PiでPythonのソケットライブラリを使用してサーバープログラムを作成する手順。

  3. データ交換: PCとRaspberry Pi間でのデータ送受信のプロセスを探る。

  4. クライアントプログラムの作成: Raspberry Piサーバーと通信するPC側のクライアントプログラムの作成。

  5. 基本機能の実装: カウンター操作の簡単な例で双方向通信をデモする。

ビデオ

Video 43: Raspberry Piを使ったシンプルなクライアントサーバーシステムの構築

Raspberry Piをサーバーとして、PCクライアントからのコマンド受信時に温度と湿度の測定を行うクライアントサーバー通信システムの確立方法を学びます。

  1. Raspberry Piサーバーの設定: GPIOピンの設定、UDPサーバーソケットの作成。

  2. クライアント要求の処理: コマンドを継続的にリスニングし、データのデコードとパース。

  3. センサー読み取り: DHT11センサーからの温度と湿度の読み取り。

  4. データ交換: センサーデータをクライアントに送り返し、表示させる。

  5. クライアント側の実装: クライアントソケットの確立、コマンドの送信、データの受信と処理。

ビデオ

Video 44: Raspberry Piで高度なクライアント・サーバー接続を構築

Raspberry Piを使い、PCからのコマンドに応じて温湿度データを送受信するクライアント・サーバーシステムの設定方法を解説します。エラーハンドリングやデータ伝送も扱います。

  1. Raspberry Piサーバー設定: UDPサーバーソケットの作成。

  2. クライアントリクエスト処理: コマンドのリスニングとデータ解析。

  3. センサー読取り: DHT11センサーからの温湿度データ取得。

  4. データ交換: クライアントへのセンサーデータ送信。

  5. クライアント側実装: コマンド送信とデータ受信処理。

ビデオ

ビデオ69: ラズベリーパイでMFRC522 RFIDモジュールとタグを使う方法

このチュートリアルでは、ラズベリーパイプロジェクトでのアクセス制御や出席追跡などにRFIDモジュールを統合する方法を学びます。Pythonでのコーディング実践を含むステップバイステップの指示に従ってください。

  1. RFIDモジュール入門: RFID技術がラズベリーパイプロジェクトをどう強化するか理解します。

  2. ハードウェアセットアップ: MFRC522 RFIDモジュールをラズベリーパイに接続する方法を学びます。

  3. ラズベリーパイでSPIセットアップ: SPIを有効化し、ラズベリーパイとRFIDモジュールの通信に必要なライブラリをインストールします。

  4. RFIDモジュール操作: PythonコードでRFIDリーダーオブジェクトを初期化し、カードIDを読み、IDにテキストデータを関連付ける方法を学びます。

  5. RFIDタグの読み書き: PythonでRFIDタグにデータを読み書きする実践的なデモを見ます。

  6. 宿題: 人の名前と好きな色を記録するシステムをRFIDタグで作成し、プロジェクトへのRFID統合に関する理解を深めます。

ビデオ

ビデオ70: ラズベリーパイでMFRC522 RFIDモジュールとタグを使う方法

このビデオでは、ラズベリーパイを使用してRFID/NFCカードをプログラミングするための上級技術について説明します。データバンドル、ユーザー入力の処理、ハードウェアとのインタラクション、エラーチェックなどのトピックをカバーしています。このチュートリアルは、RFID/NFCカードプログラミングプロジェクトにおける管理機能の実装に向けた、効率的なデータ管理、ユーザープロンプト、デバッグ技術に関する洞察を提供します。

  1. RC522 RFIDモジュールとRGB LEDのセットアップ。

  2. 効率的なデータ管理のための辞書の活用。

  3. ユーザープロンプトと応答の実装。

  4. 新しいRFID/NFCカードをプログラミングするための管理機能。

  5. データバンドル: コロン区切りを使用して効率的にデータをバンドルする。

  6. ユーザー入力の適切なフォーマットとアポストロフィの処理。

  7. NFCカードにパーソナライズされたデータを書き込む。

  8. NFCカードから読み取ったデータに基づいてLEDを制御する。

  9. エラーチェックの重要性とエラーハンドリングの技術。

  10. 宿題: プログラムの管理セクションで色入力のエラーチェックを実装し、辞書を動的に更新する。

ビデオ

Pythonで遊ぼう (すべてのPiモデル用)

「GPIO Zero」の確認

もし、Raspberry Pi 5を使用してPythonユーザーであれば、 「GPIO Zero」が提供するAPIを使用してGPIOをプログラムできます。

「GPIO Zero」は、Raspberry PiのGPIOピンを制御するためのモジュールです。 このパッケージは、Raspberry Pi上のGPIOを制御するための使いやすいクラスや関数の範囲を提供します。 詳細や例については、こちらを参照してください:https://gpiozero.readthedocs.io/en/latest/

GPIO Zeroがインストールされているかどうかをテストするには、Pythonで次のコマンドを入力してください:

python
_images/zero_01.png

Python CLIで、 import gpiozero と入力します。 エラーメッセージが表示されなければ、GPIO Zeroがインストールされていることを意味します。

import gpiozero
_images/zero_02.png

Python CLIを終了する場合は、次のコマンドを入力してください:

exit()
_images/zero_03.png

1 出力

1.1 ディスプレイ

1.1.1 点滅するLED
概要

このプロジェクトでは、プログラムによって点滅するLEDを作成する方法を学びます。 設定により、LEDはさまざまな興味深い現象を生成できます。さあ、始めましょう。

必要なコンポーネント

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

_images/1.1.1_blinking_led_list.png
回路図

この実験では、Raspberry PiのGPIOピン17をLEDの陽極(長いピン)に接続し、LEDの陰極(短いピン)を抵抗に接続し、抵抗のもう一方の端をRaspberry PiのGNDピンに接続します。LEDを点灯させるには、GPIO17を高電圧(3.3V)に設定する必要があります。これはプログラムによって実現できます。

注釈

Pin11 は、Raspberry Piの左から右への11番目のピンを指します。それに対応する BCM ピン番号は以下の表に示されています。

Python言語関連の内容の中で、BCM 17は以下の表のBCM列で17になります。 同時に、それはRaspberry Piの11番目のピンであり、Pin 11と同じです。

T-Board Name

physical

BCM

GPIO17

Pin 11

17

_images/1.1.1_blinking_led_schematic.png
実験手順

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

_images/1.1.1_blinking_led_circuit.png

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

  1. 画面を使用する場合、以下の手順をお勧めします。

「1.1.1_BlinkingLed_zero.py」を見つけてダブルクリックして開きます。これでファイルが開きます。

ウィンドウで Run -> Run Module をクリックすると、次のコンテンツが表示されます。

実行を停止するには、右上のXボタンをクリックして閉じ、コードに戻ります。コードを変更した場合は、Run Module (F5) をクリックする前に保存する必要があります。その後、結果を確認できます。

  1. Raspberry Piにリモートでログインする場合、次のコマンドを入力します:

cd ~/davinci-kit-for-raspberry-pi/python-pi5

注釈

この実験のコードのパスに cd を使用してディレクトリを変更します。

ステップ3: コードを実行します。

sudo python3 1.1.1_BlinkingLed_zero.py

注釈

ここで、sudo - superuser do、pythonはPythonでファイルを実行することを意味します。

コードを実行した後、LEDが点滅するのを見ることができます。

ステップ4: コードファイル「1.1.1_BlinkingLed_zero.py」を編集したい場合、「Ctrl + C」を押してコードの実行を停止します。その後、次のコマンドを入力して「1.1.1_BlinkingLed_zero.py」を開きます:

nano 1.1.1_BlinkingLed_zero.py

注釈

nanoはテキストエディタツールです。このツールを使用してコードファイル「1.1.1_BlinkingLed_zero.py」を開くためにこのコマンドが使用されます。

「Ctrl+X」を押して終了します。コードを変更した場合、変更を保存するかどうかを確認するプロンプトが表示されます。保存する場合は「Y」(保存)、保存しない場合は「N」(保存しない)を入力します。

その後、効果を確認するために再度「nano 1.1.1_BlinkingLed_zero.py」を入力します。

コード

以下はプログラムコードです:

注釈

以下のコードは 変更/リセット/コピー/実行/停止 することができます。ただし、それを行う前に「davinci-kit-for-raspberry-pi/python-pi5」というソースコードのパスに移動する必要があります。コードを変更した後、そのまま実行して効果を確認できます。

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

# GPIO Zeroライブラリを使用してGPIOピン17に接続されたLEDを初期化します。
led = LED(17)

try:
   # LEDの状態を切り替えるための無限ループを開始します。
   while True:
      # LEDをオンにしてコンソールにメッセージを表示します
      led.on()
      print('...LED ON')

      # LEDを0.5秒間オンにしたまま待機します。
      sleep(0.5)

      # LEDをオフにしてコンソールにメッセージを表示します
      led.off()
      print('LED OFF...')

      # LEDを0.5秒間オフにしたまま待機します。
      sleep(0.5)

except KeyboardInterrupt:
   # キーボードインタラプト(Ctrl+Cを押すなど)を優雅に処理してループを終了します。
   # GPIO Zeroは終了時にGPIO設定のクリーンアップを自動的に処理します。
   pass

コードの説明

  1. システムがこれを検出すると、env設定でpythonのインストールパスを検索し、対応するインタープリタを呼び出して操作を完了します。これは、ユーザーがpythonを /usr/bin のデフォルトパスにインストールしていない場合でも、操作を行うためのものです。

    #!/usr/bin/env python3
    
  2. これらの行は必要なクラスと関数をインポートします。 LEDはLED制御用の gpiozero から、 sleep は遅延用の time からです。

    from gpiozero import LED
    from time import sleep
    
  3. この行はGPIOピン17に接続されたLEDオブジェクトを作成します。

    # GPIO Zeroライブラリを使用してGPIOピン17に接続されたLEDを初期化します。
    led = LED(17)
    
  4. while True: を使用して無限ループを開始します。ループ内では、LEDがオンになり( led.on() )、メッセージが表示されます。プログラムは0.5秒間一時停止します( sleep(0.5) )。その後、LEDがオフになり( led.off() )、別のメッセージが表示され、プログラムは再び0.5秒間一時停止します。

    try:
        # LEDの状態を切り替える無限ループを開始します。
        while True:
            # LEDをオンにしてコンソールにメッセージを表示します。
            led.on()
            print('...LED ON')
    
            # LEDがオンの状態で0.5秒間待ちます。
            sleep(0.5)
    
            # LEDをオフにしてコンソールにメッセージを表示します。
            led.off()
            print('LED OFF...')
    
            # LEDがオフの状態で0.5秒間待ちます。
            sleep(0.5)
    
  5. except ブロックは KeyboardInterrupt (Ctrl+Cを押すなど)をキャッチし、ループを安全に終了します。ここで pass ステートメントは、割り込み時に特定のアクションを実行しないことを示すプレースホルダーとして使用されます。

    except KeyboardInterrupt:
        # キーボードの割り込み(Ctrl+C)を安全に処理し、ループを中断します。
        # 終了時にはGPIO Zeroが自動的にGPIOの設定をクリーンアップします。
        pass
    
1.1.2 RGB LED
概要

このプロジェクトでは、RGB LEDを制御してさまざまな色を点滅させます。

必要なコンポーネント

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

_images/1.1.2_rgb_led_list.png
回路図

R、G、およびBのピンを電流制限抵抗に接続した後、それぞれをGPIO17、GPIO18、GPIO27に接続します。LEDの最長のピン(GND)をRaspberry PiのGNDに接続します。これらの3つのピンに異なるPWM値を与えると、RGB LEDは異なる色を表示します。

T-Board Name

physical

BCM

GPIO17

Pin 11

17

GPIO18

Pin 12

18

GPIO27

Pin 13

27

_images/1.1.2_rgb_led_schematic.png
実験手順

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

_images/1.1.2_rgbLed_circuit.png

ステップ2: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.1.2_rgbLed_zero.py

コードを実行した後、RGB LEDが赤、緑、青、黄、ピンク、シアンを表示するのを確認できます。

コード

注釈

以下のコードは 変更/リセット/コピー/実行/停止 することができます。ただし、それを行う前に「davinci-kit-for-raspberry-pi/python-pi5」というソースコードのパスに移動する必要があります。コードを変更した後、そのまま実行して効果を確認できます。

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

# RGB形式(赤、緑、青)でRGB LEDの色のリストを定義します。
# 各色成分は0(オフ)から1(フル強度)までの範囲です。
COLORS = [(1, 0, 0), (0, 1, 0), (0.2, 0.1, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1)]

# RGB LEDを初期化します。赤の成分をGPIO 17に、緑をGPIO 18に、青をGPIO 27に接続します。
rgb_led = RGBLED(red=17, green=18, blue=27)

try:
    # 定義した色を連続してサイクルします。
    while True:
        for color in COLORS:
            # RGB LEDを現在の色に設定します。
            rgb_led.color = color
            # 現在の色をコンソールに出力します。
            print(f"Color set to: {color}")
            # 次の色に切り替える前に1秒待ちます。
            sleep(1)

except KeyboardInterrupt:
    # キーボードインタラプト(Ctrl+Cを押すなど)を優雅に処理してループを終了します。
    # GPIOのクリーンアップは、スクリプトの終了時にGPIO Zeroによって自動的に管理されます。
    pass

コードの説明

  1. これはRGB LEDを制御するための gpiozero ライブラリから RGBLED クラスをインポートし、コード内で遅延を実装するための time ライブラリをインポートしています。

    #!/usr/bin/env python3
    from gpiozero import RGBLED
    from time import sleep
    
    # RGB LEDのRGB形式で異なる色を表すタプルを含むCOLORSリストを定義します。
    # 各色成分は0から1までの範囲で、0はオフ、1は各色成分のフル強度を表します。
    
  2. COLORS リストにはRGB形式で異なる色を表すタプルが含まれています。R、G、Bピンに異なるパルス幅変調(PWM)値を rgb_led.color 属性を介して割り当てることにより、LEDはさまざまな色を生成できます。PWM値は0から1までの範囲で、0は無強度(オフ)を表し、各色成分のフル強度を表すのは1です。

  3. 例えば、 rgb_led.color = (1, 0, 0) を設定すると、LEDは赤に点灯します。これは赤成分にフル強度を設定し、緑と青をオフにしています。同様に、これらの値の異なる組み合わせによって異なる色が表示されます。PWMを介した色の混合は、RGB LEDで幅広い色の範囲を作成するための技術です。

    COLORS = [(1, 0, 0), (0, 1, 0), (0.2, 0.1, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1)]
    
  4. RGB LEDは、その赤、緑、青の成分をそれぞれGPIOピン17、18、27に接続して初期化されます。

    # RGB LEDを初期化します。赤の成分をGPIO 17に、緑をGPIO 18に、青をGPIO 27に接続します。
    rgb_led = RGBLED(red=17, green=18, blue=27)
    
  5. while True: ループは COLORS で定義された色を連続してサイクルします。各色に対して、rgb_led.color = color はLEDをその色に設定し、 sleep(1) は1秒間の一時停止を行います。

    try:
        # 定義した色を連続してサイクルします。
        while True:
            for color in COLORS:
                # RGB LEDを現在の色に設定します。
                rgb_led.color = color
                # 現在の色をコンソールに出力します。
                print(f"Color set to: {color}")
                # 次の色に切り替える前に1秒待ちます。
                sleep(1)
    
  6. このセクションは KeyboardInterrupt (Ctrl+Cを押すなど)を優雅に処理します。 pass ステートメントは、中断時に特定のアクションを指定しないことを示すプレースホルダとして使用され、GPIO ZeroはGPIOのクリーンアップを自動的に処理します。

    except KeyboardInterrupt:
        # キーボードインタラプト(Ctrl+Cを押すなど)を優雅に処理してループを終了します。
        # GPIOのクリーンアップは、スクリプトの終了時にGPIO Zeroによって自動的に管理されます。
        pass
    
1.1.3 LED バーグラフ
概要

このプロジェクトでは、LEDバーグラフ上のライトを順番に点灯させます。

必要なコンポーネント

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

_images/1.1.3_led_bar_list.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

SPICE0

Pin 24

10

8

SPICE1

Pin 26

11

7

GPIO12

Pin 32

26

12

GPIO16

Pin 36

27

16

GPIO20

Pin 38

28

22

GPIO21

Pin 40

29

21

_images/1.1.3_LedBarGraph_schematic.png
実験手順

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

注釈

接続する際に方向に注意してください。逆に接続すると点灯しません。

_images/1.1.3_LedBarGraph_circuit.png

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ3: 実行可能ファイルを実行します。

sudo python3 1.1.3_LedBarGraph_zero.py

コードを実行した後、LEDバーグラフ上のLEDが定期的に点灯および消灯するのを確認できます。

コード

注釈

以下のコードは 変更/リセット/コピー/実行/停止 することができます。ただし、それを行う前に「davinci-kit-for-raspberry-pi/python-pi5」というソースコードのパスに移動する必要があります。コードを変更した後、そのまま実行して効果を確認できます。

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

# LEDが接続されているGPIOピンを定義します
led_pins = [18, 23, 24, 25, 8, 7, 12, 16, 20, 21]

# 各ピンに対応するLEDオブジェクトを作成します
leds = [LED(pin) for pin in led_pins]

def odd_led_bar_graph():
    # 奇数番目のLED(インデックス0, 2, 4など)を順番に点灯させます。
    for i in range(5):
        j = i * 2  # 奇数のインデックスを計算
        leds[j].on()  # 奇数番目のLEDを点灯
        sleep(0.3)    # 視覚効果のための遅延
        leds[j].off() # LEDを消灯

def even_led_bar_graph():
    # 偶数番目のLED(インデックス1, 3, 5など)を順番に点灯させます。
    for i in range(5):
        j = i * 2 + 1  # 偶数のインデックスを計算
        leds[j].on()   # 偶数番目のLEDを点灯
        sleep(0.3)     # 視覚効果のための遅延
        leds[j].off()  # LEDを消灯

def all_led_bar_graph():
    # すべてのLEDを順番に点灯させます
    for led in leds:
        led.on()       # LEDを点灯
        sleep(0.3)     # 視覚効果のための遅延
        led.off()      # LEDを消灯

def turn_off_all_leds():
    # すべてのLEDを一斉に消灯させます
    for led in leds:
        led.off()

try:
    # LEDパターンをサイクルするためのメインループ
    while True:
        odd_led_bar_graph()   # 奇数番目のLEDをアクティブに
        sleep(0.3)            # パターン間の一時停止
        even_led_bar_graph()  # 偶数番目のLEDをアクティブに
        sleep(0.3)            # パターン間の一時停止
        all_led_bar_graph()   # すべてのLEDをアクティブに
        sleep(0.3)            # 再起動前の一時停止

except KeyboardInterrupt:
    # 中断(Ctrl+C)を処理する
    turn_off_all_leds()      # 終了時にすべてのLEDが消灯するようにします
    pass

コードの説明

  1. これらの行は必要なクラスと関数をインポートします。LED制御のための gpiozeroLED および遅延のための timesleep です。

    #!/usr/bin/env python3
    from gpiozero import LED
    from time import sleep
    
  2. led_pins リストにはGPIOピン番号が含まれており、 ledsled_pins の各ピンに対応する LED オブジェクトのリストです。

    # LEDが接続されているGPIOピンを定義します
    led_pins = [18, 23, 24, 25, 8, 7, 12, 16, 20, 21]
    
    # 各ピンに対応するLEDオブジェクトを作成します
    leds = [LED(pin) for pin in led_pins]
    
  3. LEDバーグラフの奇数番号のLEDを順番に点灯させます。

    def odd_led_bar_graph():
        # 奇数番号のLED(インデックス0, 2, 4など)を順番に点灯させます
        for i in range(5):
            j = i * 2  # 奇数のインデックスを計算します
            leds[j].on()  # 奇数番号のLEDを点灯させます
            sleep(0.3)    # 視覚的な効果のための遅延
            leds[j].off() # LEDを消灯させます
    
  4. LEDバーグラフの偶数番号のLEDを順番に点灯させます。

    def even_led_bar_graph():
        # 偶数番号のLED(インデックス1, 3, 5など)を順番に点灯させます
        for i in range(5):
            j = i * 2 + 1  # 偶数のインデックスを計算します
            leds[j].on()   # 偶数番号のLEDを点灯させます
            sleep(0.3)     # 視覚的な効果のための遅延
            leds[j].off()  # LEDを消灯させます
    
  5. LEDバーグラフのLEDを1つずつ順番に点灯させます。

    def all_led_bar_graph():
        # すべてのLEDを順番に点灯させます
        for led in leds:
            led.on()       # LEDを点灯させます
            sleep(0.3)     # 視覚的な効果のための遅延
            led.off()      # LEDを消灯させます
    
  6. while True ループはLEDパターンを連続してサイクルします。 except ブロックはKeyboardInterrupt(Ctrl+C)を処理し、終了時にすべてのLEDが消灯することを確認します。

try:
    # LEDパターンをサイクルするメインループ
    while True:
        odd_led_bar_graph()   # 奇数番号のLEDをアクティブにする
        sleep(0.3)            # パターン間の一時停止
        even_led_bar_graph()  # 偶数番号のLEDをアクティブにする
        sleep(0.3)            # パターン間の一時停止
        all_led_bar_graph()   # すべてのLEDをアクティブにする
        sleep(0.3)            # 再開前の一時停止

except KeyboardInterrupt:
    # インタラプト(Ctrl+C)を処理します
    turn_off_all_leds()      # 終了時にすべてのLEDが消灯していることを確認します
    pass
1.1.4 7セグメントディスプレイ
概要

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

必要なコンポーネント

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

_images/1.1.4_7_segment_list.png
回路図

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

_images/1.1.4_7_segment_schematic.png
実験手順

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

_images/1.1.4_7-Segment_circuit.png

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.1.4_7-Segment_zero.py

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

コード

注釈

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

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

# 74HC595シフトレジスタに接続されたGPIOピン
SDI = OutputDevice(17)   # シリアルデータ入力
RCLK = OutputDevice(18)  # メモリクロック入力(レジスタクロック)
SRCLK = OutputDevice(27) # シフトレジスタクロック

# 7セグメントディスプレイの共通陰極の16進数デジットコード
segCode = [
    0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,
    0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
]

def hc595_shift(data):
    # 74HC595に8ビットのデータをシフト
    for bit in range(8):
        # データビットに基づいてSDIを高または低に設定
        SDI.value = 0x80 & (data << bit)
        # シフトレジスタクロックをトリガ
        SRCLK.on()
        sleep(0.001)
        SRCLK.off()
    # メモリクロックをトリガしてデータを出力にラッチ
    RCLK.on()
    sleep(0.001)
    RCLK.off()

def display_all_on():
    # すべてのセグメントをオンにする関数(共通陰極の7セグメントディスプレイ用)
    all_on_code = 0x3f
    hc595_shift(all_on_code)
    print("Displaying all segments on")

try:
    while True:
        # 7セグメントディスプレイに各16進数デジットを表示
        for code in segCode:
            hc595_shift(code)  # コードを74HC595にシフト
            # 表示されたセグメントコードを表示
            print(f"segCode[{segCode.index(code)}]: 0x{code:02X}")
            sleep(0.5)  # 各デジットを表示する間の一時停止

except KeyboardInterrupt:
    # スクリプトの中断(例:Ctrl+C)を優雅に処理
    pass

コードの説明

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

    #!/usr/bin/env python3
    from gpiozero import OutputDevice
    from time import sleep
    
  2. SDI、RCLK、SRCLKは、74HC595のシリアルデータ入力、メモリクロック入力(レジスタクロック)、シフトレジスタクロックピンに対応しています。

    # 74HC595シフトレジスタに接続されたGPIOピン
    SDI = OutputDevice(17)   # シリアルデータ入力
    RCLK = OutputDevice(18)  # メモリクロック入力(レジスタクロック)
    SRCLK = OutputDevice(27) # シフトレジスタクロック
    
  3. segCode は、7セグメントディスプレイに表示する各デジットの16進数コードを含む配列です。

    # 一般陰極型7セグメントディスプレイ用の16進数のデジットコード
    segCode = [
        0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,
        0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
    ]
    
  4. この関数は、データを74HC595に8ビットシフトします。それは各ビットを SDI に連続的に入力し、ビットをシフトするために SRCLK をトグルし、データを出力にラッチするために RCLK を使用します。

    def hc595_shift(data):
        # 74HC595に8ビットのデータをシフトします
        for bit in range(8):
            # データビットに基づいてSDIを高または低に設定します
            SDI.value = 0x80 & (data << bit)
            # シフトレジスタクロックをトリガします
            SRCLK.on()
            sleep(0.001)
            SRCLK.off()
        # データをアウトプットにラッチするためにメモリクロックをトリガします
        RCLK.on()
        sleep(0.001)
        RCLK.off()
    
  5. この関数は、ディスプレイのすべてのセグメントをオンにします。これは、共通カソードの7セグメントディスプレイ用です。

    def display_all_on():
        # すべてのセグメントをオンにするための関数(一般陰極型7セグメントディスプレイ用)
        all_on_code = 0x3f
        hc595_shift(all_on_code)
        print("Displaying all segments on")
    
  6. メインループでは、 segCode の各コードが順番にディスプレイに送られ、各コードの間に遅延があります。

    try:
        while True:
            # 7セグメントディスプレイに各16進数のデジットを表示します
            for code in segCode:
                hc595_shift(code)  # コードを74HC595にシフト
                # 表示されているセグメントコードを表示
                print(f"segCode[{segCode.index(code)}]: 0x{code:02X}")
                sleep(0.5)  # 各デジットの表示間に一時停止
    
  7. この部分のコードは、スクリプトの中断(Ctrl+Cなど)を優雅に処理します。

    except KeyboardInterrupt:
        # スクリプトの中断を優雅に処理します(例:Ctrl+C)
        pass
    
1.1.5 4桁 7セグメントディスプレイ
概要

次に、4桁の7セグメントディスプレイを制御してみましょう。

必要なコンポーネント

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

_images/1.1.5_4_digit_list.png
回路図

T-Board Name

physical

BCM

GPIO17

Pin 11

17

GPIO27

Pin 13

27

GPIO22

Pin 15

22

SPIMOSI

Pin 19

10

GPIO18

Pin 12

18

GPIO23

Pin 16

23

GPIO24

Pin 18

24

_images/1.1.5_4_digit_schmatic.png
実験手順

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

_images/1.1.5_4-Digit_circuit.png

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.1.5_4-Digit_zero.py

コードを実行した後、プログラムはカウントを1秒ごとに増やし、4桁のディスプレイにカウントを表示します。

コード

注釈

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

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

# 74HC595シフトレジスタ用のGPIOピンを定義
SDI = OutputDevice(24)   # シリアルデータ入力
RCLK = OutputDevice(23)  # レジスタクロック
SRCLK = OutputDevice(18) # シフトレジスタクロック

# 7セグメントディスプレイの数字を選択するためのGPIOピンを定義
placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]

# 7セグメントディスプレイに表示する0から9までの数字のセグメントコードを定義
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

counter = 0  # 表示用のカウンターを初期化
timer1 = 0   # カウンターの増分用のタイマーを初期化

def clearDisplay():
    """ 7セグメントディスプレイをクリアします。 """
    for _ in range(8):
        SDI.on()
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def hc595_shift(data):
    """ 1バイトのデータを74HC595シフトレジスタにシフトします。 """
    for i in range(8):
        SDI.value = 0x80 & (data << i)  # データビットに基づいてSDIを高/低に設定
        SRCLK.on()  # シフトレジスタクロックをパルス
        SRCLK.off()
    RCLK.on()  # レジスタクロックをパルスしてデータを出力にラッチ
    RCLK.off()

def pickDigit(digit):
    """ 7セグメントディスプレイに表示する数字を選択します。 """
    for pin in placePin:
        pin.off()  # すべての数字選択ピンをオフにする
    placePin[digit].on()  # 選択された数字をオンにする

def timer():
    """ カウンターを1秒ごとに増分するタイマー関数です。 """
    global counter, timer1
    timer1 = threading.Timer(1.0, timer)  # 次の増分のためにタイマーをリセット
    timer1.start()
    counter += 1  # カウンターを増分
    print("%d" % counter)  # 現在のカウンターの値を表示

def setup():
    """ 初期状態を設定し、タイマーを開始します。 """
    global timer1
    timer1 = threading.Timer(1.0, timer)  # タイマーの初期化と開始
    timer1.start()

def loop():
    """ カウンターの値で7セグメントディスプレイを更新するメインループです。 """
    global counter
    while True:
        for i in range(4):  # 各数字をループ
            clearDisplay()  # 新しい数字を設定する前にディスプレイをクリア
            pickDigit(i)    # 表示する数字を選択
            digit = (counter // (10 ** i)) % 10
            hc595_shift(number[digit])  # 数字の値を74HC595にシフト
            time.sleep(0.001)  # ディスプレイの安定性のための短い遅延

def destroy():
    """ 終了時にGPIOリソースをクリーンアップし、タイマーを停止します。 """
    global timer1
    timer1.cancel()  # タイマーを停止
    for device in [SDI, RCLK, SRCLK] + placePin:
        device.close()  # GPIOデバイスをクローズ

try:
    setup()  # 初期セットアップを実行
    while True:
        loop()  # メインループを開始

except KeyboardInterrupt:
    # スクリプトの中断(例:Ctrl+C)
    destroy()  # 終了時にリソースをクリーンアップ

コードの説明

  1. placePin リストは、4桁の7セグメントディスプレイの各桁を制御するための共通アノードピンを制御します。

  2. 16進数で0から9までのセグメントコード(共通アノード)を含む number 配列を定義します。

  3. setup 関数は、カウンタ増加用のタイマーを1秒ごとにトリガするためのセットアップを行います。

  4. タイマーが1.0秒に達すると、タイマー関数が呼び出され、カウンタに1を追加し、次にタイマー自体が1秒ごとに繰り返し実行されます。

  5. hc595_shift 関数は、74HC595シフトレジスタに1バイトのデータをシフトし、ディスプレイセグメントを制御します。

  6. メインループ loop では、現在のカウンタ値を表示し、各桁を順番に表示します。各桁を表示する前にディスプレイをクリアします。

  7. clearDisplay 関数は、次の桁を表示する前にすべてのセグメントをオフに設定してディスプレイをクリアします。

  8. pickDigit 関数は、アクティブ化する7セグメントディスプレイの桁を選択します。各桁は個別のGPIOピンで制御されます。

  9. プログラムが中断された場合、GPIOリソースを適切に解放し、タイマーを停止します。

1.1.6 LEDドットマトリックス
はじめに

その名前からも分かるように、LEDドットマトリックスはLEDで構成されたマトリックスです。 LEDの点灯と消灯によって、異なる文字やパターンを形成します。

必要なコンポーネント

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

_images/1.1.6_led_dot_matrix_list.png
原理

LEDドットマトリックス

一般的に、LEDドットマトリックスは2つのタイプに分類されます:共通陰極(CC)と共通陽極(CA)。外観は似ていますが、内部に違いがあります。テストで区別できます。このキットではCAタイプが使用されています。サイドにラベル「788BS」と表示されています。

以下の図をご覧ください。ピンは背面の2つの端に配置されています。ラベル側を参照してください:この端のピンはピン1から8で、もう一方はピン9から16です。

外部ビュー:

_images/1.1.6_led_dot_matrix_1.png

以下の図は内部構造を示しています。CA LEDドットマトリックスでは、ROWはLEDの陽極を表し、COLは陰極です。CCの場合は逆です。共通点は、両方のタイプともに、ピン13、3、4、10、6、11、15、16がすべてCOLであり、ピン9、14、8、12、1、7、2、5がすべてROWであることです。左上隅の最初のLEDを点灯させたい場合、CA LEDドットマトリックスの場合、ピン9をHighに設定してピン13をLowに、CCの場合はピン13をHighに設定してピン9をLowにします。最初の列全体を点灯させたい場合、CAの場合、ピン13をLowにし、ROW 9、14、8、12、1、7、2、5をHighに設定し、CCの場合、ピン13をHighにし、ROW 9、14、8、12、1、7、2、5をLowに設定します。理解を深めるために、以下の図を参考にしてください。

内部ビュー:

_images/1.1.6_led_dot_matrix_2.png

上記の行と列に対応するピン番号:

COL

1

2

3

4

5

6

7

8

Pin No.

13

3

4

10

6

11

15

16

ROW

1

2

3

4

5

6

7

8

Pin No.

9

14

8

12

1

7

2

5

さらに、ここでは2つの74HC595チップを使用しています。1つはLEDドットマトリックスの行を制御し、もう1つは列を制御します。

回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

_images/1.1.6_led_dot_matrix_schematic.png
実験手順

ステップ1: 回路を組み立てます。配線が複雑なので、ステップバイステップで進めましょう。まず、T-Cobbler、LEDドットマトリックス、および2つの74HC595チップをブレッドボードに挿入します。T-Cobblerの3.3VとGNDをボードの両側の穴に接続し、次に2つの74HC595チップのピン16と10をVCCに、ピン13とピン8をGNDに接続します。

注釈

上記のFritzingイメージでは、ラベルが下にある側です。

_images/1.1.6_LedMatrix_circuit_1.png

ステップ2: 2つの74HC595のピン11を一緒に接続し、次にGPIO27に接続します。次に、2つのチップのピン12を接続し、GPIO18に接続します。その後、左側の74HC595のピン14をGPIO17に、ピン9を2番目の74HC595のピン14に接続します。

_images/1.1.6_LedMatrix_circuit_2.png

ステップ3: 右側の74HC595はLEDドットマトリックスの列を制御します。以下のテーブルを参照してマッピングを確認してください。したがって、74HC595のQ0-Q7ピンは、ピン13、3、4、10、6、11、15、16とそれぞれマッピングされています。

74HC595

Q0

Q1

Q2

Q3

Q4

Q5

Q6

Q7

LED Dot Matrix

13

3

4

10

6

11

15

16

_images/1.1.6_LedMatrix_circuit_3.png

ステップ4: さて、LEDドットマトリックスのROWを接続します。左側の74HC595がLEDドットマトリックスのROWを制御します。以下のテーブルを参照してマッピングを確認してください。左側の74HC595のQ0-Q7は、ピン9、14、8、12、1、7、2、5とそれぞれマッピングされています。

74HC595

Q0

Q1

Q2

Q3

Q4

Q5

Q6

Q7

LED Dot Matrix

9

14

8

12

1

7

2

5

_images/1.1.6_LedMatrix_circuit_4.png

ステップ5: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ6: 実行します。

sudo python3 1.1.6_led_dot_matrix_zero.py

コードを実行すると、LEDドットマトリックスが一列ずつ点灯し、列ごとに消灯します。

コード

注釈

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

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

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

# Define patterns for matrix display; ROWs are anodes (+), COLs are cathodes (-)
# Pattern for ROWs (anode signals)
code_H = [0x01, 0xff, 0x80, 0xff, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
# Pattern for COLs (cathode signals)
code_L = [0x00, 0x7f, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f]

# Shift data to 74HC595
def hc595_shift(dat):
   """ Shift data to the 74HC595 shift register for displaying on the matrix. """
   for i in range(8):
      # Set SDI value and trigger shift register clock
      SDI.value = 0x80 & (dat << i)
      SRCLK.on()
      SRCLK.off()
   # Trigger register clock to update display
   RCLK.on()
   sleep(0.001)
   RCLK.off()

def main():
   """ Main loop for cycling through display patterns. """
   while True:
      # Cycle through patterns in ascending order
      for i in range(len(code_H)):
            hc595_shift(code_L[i])
            hc595_shift(code_H[i])
            sleep(0.1)

      # Cycle through patterns in descending order
      for i in range(len(code_H)-1, -1, -1):
            hc595_shift(code_L[i])
            hc595_shift(code_H[i])
            sleep(0.1)

# Run main loop, handle keyboard interrupt gracefully
try:
   main()
except KeyboardInterrupt:
   pass

コードの説明

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

    #!/usr/bin/env python3
    from gpiozero import OutputDevice
    from time import sleep
    
  2. このセクションでは、74HC595シフトレジスタに接続されたGPIOピンを初期化します。 SDI はシリアルデータ入力、 RCLK はレジスタクロック、 SRCLK はシフトレジスタクロックです。これらのピンはデータをレジスタにシフトし、LEDマトリクスの表示を制御するために使用されます。

    # 74HC595シフトレジスタに接続されたGPIOピンを定義
    SDI = OutputDevice(17)   # シリアルデータ入力
    RCLK = OutputDevice(18)  # レジスタクロック
    SRCLK = OutputDevice(27) # シフトレジスタクロック
    
  3. code_Hcode_L は、LEDマトリクスの行(陽極)と列(陰極)を制御するための2進パターンを定義します。これらの配列の各要素は、マトリクス内のどのLEDがオンまたはオフになるかを制御する2進パターンを表します。

    # マトリクス表示のためのパターンを定義します。行は陽極(+)、列は陰極(-)です。
    # 行のパターン(陽極信号)
    code_H = [0x01, 0xff, 0x80, 0xff, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
    # 列のパターン(陰極信号)
    code_L = [0x00, 0x7f, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f]
    
  4. この関数は、バイトデータ( dat )を74HC595シフトレジスタにシフトします。バイト内の各ビットに対して、ビット値に基づいて SDI ピンを高または低に設定し、ビットをレジスタにシフトするために SRCLK ピンをトグルさせます。すべてのビットがシフトされた後、LEDマトリクスの表示を更新するために RCLK ピンをトグルさせます。

    # データを74HC595にシフト
    def hc595_shift(dat):
       """ マトリクスに表示するためのデータを74HC595シフトレジスタにシフトします。 """
       for i in range(8):
          # SDIの値を設定してシフトレジスタクロックをトリガー
          SDI.value = 0x80 & (dat << i)
          SRCLK.on()
          SRCLK.off()
       # レジスタクロックをトリガーして表示を更新
       RCLK.on()
       sleep(0.001)
       RCLK.off()
    
  5. メイン関数には、LEDマトリクスの事前定義されたパターンを無限ループで循環させるコードが含まれています。 hc595_shift 関数を使用してシフトレジスタに行と列のパターン( code_Hcode_L )を送信し、昇順で最初に、次に降順で表示を作成します。

    def main():
       """ 表示パターンを循環させるためのメインループ。 """
       while True:
          # 昇順でパターンを循環させます
          for i in range(len(code_H)):
                hc595_shift(code_L[i])
                hc595_shift(code_H[i])
                sleep(0.1)
    
          # 降順でパターンを循環させます
          for i in range(len(code_H)-1, -1, -1):
                hc595_shift(code_L[i])
                hc595_shift(code_H[i])
                sleep(0.1)
    
  6. このセグメントは、プログラムがキーボード割り込み(Ctrl+C)を使用して中断できるようにします。メインループを中断する際に急激な停止やリソースの漏洩が発生しないようにします。

    # メインループを実行し、キーボード割り込みを丁寧に処理します
    try:
       main()
    except KeyboardInterrupt:
       pass
    
1.1.7 I2C LCD1602
はじめに

LCD1602は文字型液晶ディスプレイで、同時に32(16*2)文字を表示できます。

必要なコンポーネント

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

_images/1.1.7_i2c_lcd_list.png
回路図

T-Board Name

physical

SDA1

Pin 3

SCL1

Pin 5

_images/1.1.7_i2c_lcd_schematic.png
実験手順

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

_images/1.1.7_i2c_lcd1602_circuit.png

ステップ2: I2Cをセットアップします( I2C構成 を参照してください。I2Cを設定済みの場合は、このステップをスキップしてください。)

ステップ3: ディレクトリを変更します。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ4: 実行します。

sudo python3 1.1.7_Lcd1602_zero.py

コードの実行後、LCDに「Greetings!、From SunFounder」と表示されます。

注釈

  • 「FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'」というエラーが表示された場合、I2Cを有効にするには I2C構成 を参照してください。

  • 「ModuleNotFoundError: No module named 'smbus2'」エラーが表示された場合、 sudo pip3 install smbus2 を実行してください。

  • エラー「OSError: [Errno 121] Remote I/O error」が表示された場合、モジュールの配線が誤っているか、モジュールが壊れていることを意味します。

  • コードと配線が正常であるが、LCDにコンテンツが表示されない場合、背面のポテンショメータを回してコントラストを上げることができます。

コード

注釈

以下のコードは変更/リセット/コピー/実行/停止ができます。ただし、コードを変更する前に davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、直接実行して効果を確認できます。

#!/usr/bin/env python3
import LCD1602  # LCD1602とのインターフェースを行うモジュールをインポート
import time     # タイミング関数のモジュールをインポート

def setup():
    # I2Cアドレス0x27およびバックライトを有効にしてLCDを初期化
    LCD1602.init(0x27, 1)
    # メッセージ 'Greetings!' を左上隅(行0、列0)に表示
    LCD1602.write(0, 0, 'Greetings!')
    # メッセージ 'From SunFounder' を2行目(行1、列1)に表示
    LCD1602.write(1, 1, 'From SunFounder')
    time.sleep(2)  # メッセージを2秒間表示

try:
    setup()  # LCDの初期化およびメッセージの表示のためのセットアップ関数を実行します

except KeyboardInterrupt:
    # キーボードの割り込み(例:Ctrl+C)が発生した場合、LCDディスプレイをクリアします
    LCD1602.clear()
    pass  # それ以上のアクションは不要です

コードの説明

  1. このファイルはI2C LCD1602を制御するためのオープンソースファイルです。これを使用すると、I2C LCD1602を簡単に使用できます。

    import LCD1602  # LCD1602とのインターフェースを行うモジュールをインポート
    
  2. この関数は指定されたデバイスシンボルを使用してI2Cシステムを初期化します。最初のパラメータはI2Cデバイスのアドレスで、i2cdetectコマンドを使用して検出できます(詳細は付録を参照)。I2C LCD1602のアドレスは通常0x27です。

    # I2Cアドレス0x27およびバックライトを有効にしてLCDを初期化
    LCD1602.init(0x27, 1)
    
  3. LCD1602.write はLCDにメッセージを表示するために使用されます。最初の2つのパラメータは行と列の位置で、3番目はメッセージです。これでLCDに "Greetings!! From SunFounder" と表示されるようになります。

    # メッセージ 'Greetings!' を左上隅(行0、列0)に表示
    LCD1602.write(0, 0, 'Greetings!')
    # メッセージ 'From SunFounder' を2行目(行1、列1)に表示
    LCD1602.write(1, 1, 'From SunFounder')
    

1.2 音声

1.2.1 アクティブブザー
はじめに

このプロジェクトでは、PNPトランジスタを使用してアクティブブザーを鳴らす方法を学びます。

必要なコンポーネント

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

_images/1.2.1_active_buzzer_list.png
回路図

この実験では、アクティブブザー、PNPトランジスタ、および1kΩの抵抗器が、トランジスタのベースとGPIOの間に使用されてトランジスタを保護します。 Raspberry PiのGPIO17の出力に高い電圧(3.3V)が供給されると、トランジスタは電流飽和のために導通し、ブザーは音を鳴らします。しかし、Raspberry PiのIOに低い電圧が供給されると、トランジスタは遮断され、ブザーは音を鳴らしません。

T-Board Name

physical

BCM

GPIO17

Pin 11

17

_images/1.2.1_active_buzzer_schematic.png
実験手順

ステップ1: 回路を組み立てます(アクティブブザーには表面に白いテーブルステッカーがあり、裏面は黒です)。

_images/1.2.1_ActiveBuzzer_circuit.png

ステップ2: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.2.1_ActiveBuzzer_zero.py

コードを実行すると、ブザーが鳴ります。

コード

注釈

以下のコードは変更/リセット/コピー/実行/停止ができます。ただし、コードを変更する前に davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、直接実行して効果を確認できます。

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

# GPIOピン17に接続されたBuzzerオブジェクトを初期化します
buzzer = Buzzer(17)

try:
    while True:
        # ブザーをオンにする
        print('ブザーオン')
        buzzer.on()
        sleep(0.1)  # ブザーを0.1秒間オンにします

        # ブザーをオフにする
        print('ブザーオフ')
        buzzer.off()
        sleep(0.1)  # ブザーを0.1秒間オフにします

except KeyboardInterrupt:
    # キーボードの割り込み(Ctrl+C)を処理してスクリプトをきれいに終了します
    pass

コードの説明

  1. これらのステートメントは gpiozero ライブラリから Buzzer クラスと time モジュールから sleep 関数をインポートします。

    #!/usr/bin/env python3
    from gpiozero import Buzzer
    from time import sleep
    
  2. この行は、Raspberry PiのGPIOピン17に接続された Buzzer オブジェクトを作成します。

    # GPIOピン17に接続されたBuzzerオブジェクトを初期化します
    buzzer = Buzzer(17)
    
  3. 無限ループ( while True )内で、ブザーは0.1秒ごとにオンとオフになります。 print ステートメントは各アクションに対するコンソール出力を提供します。

    try:
        while True:
            # ブザーをオンにする
            print('ブザーオン')
            buzzer.on()
            sleep(0.1)  # ブザーを0.1秒間オンにします
    
            # ブザーをオフにする
            print('ブザーオフ')
            buzzer.off()
            sleep(0.1)  # ブザーを0.1秒間オフにします
    
  4. このセグメントは、キーボード割り込み(Ctrl+C)を使用してプログラムを安全に終了できるようにします。

    except KeyboardInterrupt:
    # キーボードの割り込み(Ctrl+C)を処理してスクリプトをきれいに終了します
    pass
    
1.2.2 パッシブブザー
はじめに

このプロジェクトでは、パッシブブザーを使用して音楽を演奏する方法を学びます。

必要なコンポーネント

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

_images/1.2.2_passive_buzzer_list.png
回路図

この実験では、パッシブブザー、PNPトランジスタ、および1kΩの抵抗器が、トランジスタのベースとGPIOの間に使用されてトランジスタを保護します。

GPIO17に異なる周波数が供給されると、パッシブブザーは異なる音を鳴らします。これにより、ブザーは音楽を演奏します。

T-Board Name

physical

BCM

GPIO17

Pin 11

17

_images/1.2.2_passive_buzzer_schematic.png
実験手順

ステップ1: 回路を組み立てます(パッシブブザーは裏面に緑の回路基板があります)。

_images/1.2.2_PassiveBuzzer_circuit.png

ステップ2: ディレクトリを変更します。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.2.2_PassiveBuzzer_zero.py

コードを実行すると、ブザーが音楽を演奏します。

コード

注釈

以下のコードは変更/リセット/コピー/実行/停止ができます。ただし、コードを変更する前に davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、直接実行して効果を確認できます。

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

# GPIOピン17に接続されたTonalBuzzerオブジェクトを初期化します
tb = TonalBuzzer(17)  # ご使用のセットアップに基づいてこのピン番号を更新します

def play(tune):
    """
    ブザーを使用して音楽を演奏します。
    :param tune: ノートとその持続時間を表すタプル(ノート、持続時間)のリスト
    """
    for note, duration in tune:
        print(note)  # 現在再生中の音符を出力
        tb.play(note)  # ブザーで音符を演奏
        sleep(float(duration))  # 音符の持続時間待ち
    tb.stop()  # 曲が終わった後に演奏を停止します

# 音楽チューンをノートと持続時間のシーケンスとして定義します
tune = [('C#4', 0.2), ('D4', 0.2), (None, 0.2),
    ('Eb4', 0.2), ('E4', 0.2), (None, 0.6),
    ('F#4', 0.2), ('G4', 0.2), (None, 0.6),
    ('Eb4', 0.2), ('E4', 0.2), (None, 0.2),
    ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
    ('C4', 0.2), ('B4', 0.2), (None, 0.2),
    ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
    ('B4', 0.2), ('Bb4', 0.5), (None, 0.6),
    ('A4', 0.2), ('G4', 0.2), ('E4', 0.2),
    ('D4', 0.2), ('E4', 0.2)]

try:
    play(tune)  # 演奏を開始するためにplay関数を実行します

except KeyboardInterrupt:
    # キーボード割り込みをスムーズに処理
    pass

コードの説明

  1. これらの行はブザーの制御のために gpiozero ライブラリから TonalBuzzer クラス、待機を作成するために time モジュールから sleep 関数をインポートします。

    #!/usr/bin/env python3
    from gpiozero import TonalBuzzer
    from time import sleep
    
  2. この行はGPIOピン17に接続された TonalBuzzer オブジェクトを初期化します。

    # GPIOピン17に接続されたTonalBuzzerオブジェクトを初期化します
    tb = TonalBuzzer(17)  # お使いのセットアップに基づいてこのピン番号を更新してください
    
  3. play 関数は、音楽のノートとその持続時間を表すタプルのリストを繰り返し処理します。各ノートは指定された持続時間だけ演奏され、曲が終了するとブザーが停止します。

    def play(tune):
        """
        ブザーを使って音楽を演奏します。
        :param tune: ノートとその持続時間を表すタプル(ノート、持続時間)のリスト。
        """
        for note, duration in tune:
            print(note)  # 現在演奏されているノートを出力
            tb.play(note)  # ブザーでノートを演奏
            sleep(float(duration))  # ノートの持続時間分遅延
        tb.stop()  # 曲が完了した後に演奏を停止
    
  4. メロディは音符(周波数)と持続時間(秒)のシーケンスとして定義されています。

    # ノートと持続時間(秒)のシーケンスとして音楽のメロディを定義します
    tune = [('C#4', 0.2), ('D4', 0.2), (None, 0.2),
        ('Eb4', 0.2), ('E4', 0.2), (None, 0.6),
        ('F#4', 0.2), ('G4', 0.2), (None, 0.6),
        ('Eb4', 0.2), ('E4', 0.2), (None, 0.2),
        ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
        ('C4', 0.2), ('B4', 0.2), (None, 0.2),
        ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
        ('B4', 0.2), ('Bb4', 0.5), (None, 0.6),
        ('A4', 0.2), ('G4', 0.2), ('E4', 0.2),
        ('D4', 0.2), ('E4', 0.2)]
    
  5. play(tune) 関数は try ブロック内で呼び出されます。 KeyboardInterrupt (Ctrl+Cのような)はプログラムを正常に停止します。

    try:
        play(tune)  # 曲を演奏を開始するためにplay関数を実行します
    
    except KeyboardInterrupt:
        # Ctrl+Cのようなキーボード割り込みを処理してプログラムをきれいに終了します
        pass
    

1.3 ドライバー

1.3.1 モーター
はじめに

このプロジェクトでは、L293Dを使用してDCモーターを制御し、時計回りと反時計回りに回転させる方法を学びます。 DCモーターはより大きな電流が必要ですので、安全のためにここでは電源供給モジュールを使用してモーターに電力を供給します。

必要なコンポーネント

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

_images/1.3.1_motor_list.png
回路図
_images/1.3.1_motor_schematic.png
実験手順

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

_images/1.3.1_motor_circuit.png

注釈

電源モジュールには、キットに含まれている9Vバッテリーと9Vバッテリーバックルを使用できます。 電源モジュールのジャンパーキャップをブレッドボードの5Vバスストリップに挿入してください。

_images/1.3.1_motor_battery.jpeg

ステップ2: コードのフォルダに入ります。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.3.1_Motor_zero.py

コードが実行されると、モーターは最初に時計回りに5秒間回転し、5秒間停止し、その後、反時計回りに5秒間回転し、その後、モーターは5秒間停止します。この一連の動作は繰り返し実行されます。

コード

注釈

以下のコードは変更/リセット/コピー/実行/停止ができます。ただし、コードを変更する前に davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、直接実行して効果を確認できます。

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

# GPIO Zeroを使用してモーターを初期化し、前進(17)、後退(27)、および有効(22)制御のためのGPIOピンを指定します。
motor = Motor(forward=17, backward=27, enable=22)

try:
    # モーターの方向と動きを制御するためのメイン関数です。
    # モーターの回転を時計回りと反時計回りに交互に切り替えます。
    actions = {'CW': motor.forward, 'CCW': motor.backward, 'STOP': motor.stop}  # 読みやすさのためにモーターアクションを定義

    while True:
        # モーターの方向を制御するために定義されたアクションをループします
        for action in ['CW', 'STOP', 'CCW', 'STOP']:
            actions[action]()  # 現在のアクション(前進、停止、後退、停止)を実行
            print(f"{action}")  # コンソールに現在のアクションを表示
            sleep(5)  # 次のアクションに進む前に5秒間停止

except KeyboardInterrupt:
    # プログラムを停止するためのキーボード割り込み(Ctrl+Cなど)を正常に処理します
    pass

コードの説明

  1. これらのインポートステートメントは、 gpiozero ライブラリから Motor クラスと、 time モジュールから sleep 関数を取り込みます。

    #!/usr/bin/env python3
    from gpiozero import Motor
    from time import sleep
    
  2. この行は、前進(17)、後退(27)、および有効(22)制御のためのGPIOピンを指定して Motor オブジェクトを初期化します。

    # Initialize the Motor with GPIO Zero, specifying GPIO pins for forward (17), backward (27), and enable (22) control
    motor = Motor(forward=17, backward=27, enable=22)
    
  3. モーター制御のアクションは、可読性のために辞書で定義されています。無限ループ( while True )がこれらのアクションを繰り返し、各アクションを5秒間実行します。

    try:
        # モーターの方向と動きを制御するメイン関数。
        # 時計回りと反時計回りのモーターの回転を交互に行い、間に停止します。
        actions = {'CW': motor.forward, 'CCW': motor.backward, 'STOP': motor.stop}  # 可読性のためにモーターアクションを定義
    
        while True:
            # ループを使用して定義されたアクションを制御してモーターの方向を切り替えます
            for action in ['CW', 'STOP', 'CCW', 'STOP']:
                actions[action]()  # 現在のアクション(前進、停止、後退、停止)を実行します
                print(f"{action}")  # 現在のアクションをコンソールに表示します
                sleep(5)  # 次のアクションに進む前に5秒間一時停止します
    
  4. このセグメントは、キーボード割り込み(Ctrl+Cなど)を使用してプログラムを安全に終了できるようにします。

    except KeyboardInterrupt:
    # キーボード割り込み(e.g., Ctrl+C)をスムーズに処理してプログラムを停止します
    pass
    
1.3.2 サーボ
はじめに

このプロジェクトでは、サーボを回転させる方法を学びます。

必要なコンポーネント

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

_images/1.3.2_servo_list.png
回路図
_images/1.3.2_servo_schematic.png
実験手順

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

_images/1.3.2_Servo_circuit.png

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ3: 実行可能ファイルを実行します。

sudo python3 1.3.2_Servo_zero.py

プログラムが実行されると、サーボは0度から90度、180度まで回転し、次に180度から90度、0度まで回転します。これが繰り返されます。

コード

注釈

以下のコードは変更/リセット/コピー/実行/停止ができます。ただし、コードを変更する前に davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、直接実行して効果を確認できます。

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

# サーボモーターを接続するGPIOピン番号を設定
myGPIO = 18

# サーボのパルス幅を微調整するための補正係数を定義し、それを使用して最大および最小パルス幅を計算します
myCorrection = 0.45
maxPW = (2.0 + myCorrection) / 1000  # 最大パルス幅を計算
minPW = (1.0 - myCorrection) / 1000  # 最小パルス幅を計算

# カスタムパルス幅でサーボオブジェクトを初期化
servo = Servo(myGPIO, min_pulse_width=minPW, max_pulse_width=maxPW)

try:
    while True:
        # サーボを中央に位置させて待機
        servo.mid()
        print("mid")  # 現在の位置を表示
        sleep(0.5)    # 0.5秒の一時停止

        # サーボを最小位置に移動させて待機
        servo.min()
        print("min")  # 現在の位置を表示
        sleep(1)      # 1秒間位置を保持

        # サーボを中央の位置に戻して待機
        servo.mid()
        print("mid")  # 現在の位置を表示
        sleep(0.5)    # 0.5秒の一時停止

        # サーボを最大位置に移動させて待機
        servo.max()
        print("max")  # 現在の位置を表示
        sleep(1)      # 1秒間位置を保持

except KeyboardInterrupt:
    # キーボード割り込み(Ctrl+C)でスクリプトを正常に終了する
    pass

コードの説明

  1. これらのインポート文は、サーボ制御のための Servo クラスとタイミングのための sleep 関数を取り込みます。

    #!/usr/bin/env python3
    from gpiozero import Servo
    from time import sleep
    
  2. サーボモーターを接続するためのGPIOピン番号を18に設定します。

    # サーボモーターが接続されているGPIOピン番号を設定します
    myGPIO = 18
    
  3. これらの行は、補正係数を定義し、それを使用してサーボの最大および最小パルス幅を計算します。これにより、サーボの動きの範囲を微調整できます。

    # サーボのパルス幅を微調整するための補正係数を定義し、最大パルス幅と最小パルス幅を計算します
    myCorrection = 0.45
    maxPW = (2.0 + myCorrection) / 1000  # 最大パルス幅を計算
    minPW = (1.0 - myCorrection) / 1000  # 最小パルス幅を計算
    
  4. カスタムパルス幅でサーボオブジェクトを初期化します。

    # カスタムパルス幅でサーボオブジェクトを初期化します
    servo = Servo(myGPIO, min_pulse_width=minPW, max_pulse_width=maxPW)
    
  5. try ブロックには、サーボを連続的に動かすための while True ループが含まれています。サーボは中間位置、最小位置、最大位置に配置され、各位置が表示され、指定された期間保持されます。

    try:
        while True:
            # サーボを中間位置に配置し、待機
            servo.mid()
            print("mid")  # 現在の位置を表示
            sleep(0.5)    # 0.5秒の短い休憩
    
            # サーボを最小位置に移動し、待機
            servo.min()
            print("min")  # 現在の位置を表示
            sleep(1)      # 1秒間位置を保持
    
            # サーボを中間位置に戻し、待機
            servo.mid()
            print("mid")  # 現在の位置を表示
            sleep(0.5)    # 0.5秒の短い休憩
    
            # サーボを最大位置に移動し、待機
            servo.max()
            print("max")  # 現在の位置を表示
            sleep(1)      # 1秒間位置を保持
    
    except KeyboardInterrupt:
        # キーボード割り込み(Ctrl+Cなど)でスクリプトを正常に終了します
        pass
    
1.3.3 ステッパーモーター
はじめに

ステッパーモーターは、その独自の設計により、フィードバックメカニズムなしで高い精度で制御できます。ステッパーモーターのシャフトは、一連の磁石で取り付けられ、正および負に充電される一連の電磁コイルによって制御され、特定の順序で正確に前方または後方に小さな「ステップ」で移動します。

必要な部品

このプロジェクトでは、次の部品が必要です。

_images/1.3.3_stepper_motor_list.png
回路図
_images/1.3.3_stepper_motor_schematic.png
実験手順

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

_images/1.3.3_stepper_motor_circuit.png

ステップ2: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.3.3_StepperMotor_zero.py

コードが実行されると、ステッパーモーターは、 'a' または 'c' の入力に応じて時計回りまたは反時計回りに回転します。

コード

注釈

以下のコードを変更、リセット、コピー、実行、停止することができます。ただし、それを行う前に、ソースコードのパスである davinci-kit-for-raspberry-pi/python-pi5 に移動する必要があります。コードを変更した後、その効果を確認するために直接実行できます。

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

# ステッパーモーターを制御するためにGPIOピン18、23、24、25を初期化します
motorPin = [OutputDevice(pin) for pin in (18, 23, 24, 25)]

# モーターの回転速度パラメーターを設定し、スムーズなモーター動作のための各ステップ間の待ち時間を計算します
rotationPerMinute = 15
stepsPerRevolution = 2048
stepSpeed = (60 / rotationPerMinute) / stepsPerRevolution

def rotary(direction):
    """
    指定された方向に基づいてモーターの回転を制御します。

    :param direction: 時計回りの場合は 'c'、反時計回りの場合は 'a'
    """
    if direction == 'c':
        # 時計回りの回転のステップシーケンスを実行します
        for j in range(4):
            for i in range(4):
                if 0x99 << j & (0x08 >> i):
                    motorPin[i].on()
                else:
                    motorPin[i].off()
                sleep(stepSpeed)
    elif direction == 'a':
        # 反時計回りの回転のステップシーケンスを実行します
        for j in range(4):
            for i in range(4):
                if 0x99 >> j & (0x08 >> i):
                    motorPin[i].on()
                else:
                    motorPin[i].off()
                sleep(stepSpeed)

def loop():
    """
    ユーザーにモーターの回転方向を選択させ続け、この入力に基づいてモーターを制御します。
    """
    while True:
        direction = input('モーターの回転方向を選択してください a=反時計回り、c=時計回り: ')
        if direction == 'c':
            print('モーターは時計回りに動作します\n')
            break
        elif direction == 'a':
            print('モーターは反時計回りに動作します\n')
            break
        else:
            print('入力エラー、もう一度やり直してください!')

    # 選択した方向でモーターを連続的に回転させます
    while True:
        rotary(direction)

def destroy():
    """
    安全にすべてのモーターピンをオフにし、クリーンなシャットダウンに使用します。
    """
    for pin in motorPin:
        pin.off()

# メインプログラムの実行
try:
    loop()
except KeyboardInterrupt:
    destroy()  # キーボード割り込みを処理してモーターを安全にシャットダウン
コードの説明
  1. このセクションでは、必要なライブラリをインポートしています。GPIOピンの制御には「gpiozero」、タイミング制御には「time」を使用しています。

    #!/usr/bin/env python3
    from gpiozero import OutputDevice
    from time import sleep
    
  2. ステッパーモータを制御するためにGPIOピン18、23、24、25を初期化します。

    # ステッパーモータのモーターピンを初期化します
    motorPin = [OutputDevice(pin) for pin in (18, 23, 24, 25)]
    
  3. モーターの回転速度を設定し、スムーズな動作のために各ステップ間の時間間隔を計算します。

    # モーターの回転速度パラメータを設定します
    rotationPerMinute = 15
    stepsPerRevolution = 2048
    # スムーズなモーター動作のための各ステップの間隔を計算します
    stepSpeed = (60 / rotationPerMinute) / stepsPerRevolution
    
  4. 「rotary」関数は、モーターの回転を制御します。ビット操作とステッピングシーケンスを使用して、時計回りまたは反時計回りの回転に適した順序でモーターピンをアクティブにします。

    def rotary(direction):
        """
        指定された方向に基づいてモーターの回転を制御します。
    
        :param direction: 'c' は時計回り、'a' は反時計回り
        """
        if direction == 'c':
            # 時計回りの回転用のステッピングシーケンスを実行します
            for j in range(4):
                for i in range(4):
                    if 0x99 << j & (0x08 >> i):
                        motorPin[i].on()
                    else:
                        motorPin[i].off()
                    sleep(stepSpeed)
        elif direction == 'a':
            # 反時計回りの回転用のステッピングシーケンスを実行します
            for j in range(4):
                for i in range(4):
                    if 0x99 >> j & (0x08 >> i):
                        motorPin[i].on()
                    else:
                        motorPin[i].off()
                    sleep(stepSpeed)
    
  5. 「loop」関数はユーザーにモーターの回転方向を選択するように継続的にプロンプトを表示し、入力に基づいてモーターを制御します。

    def loop():
        """
        ユーザーにモーターの回転方向を選択するように継続的にプロンプトを表示し、この入力に基づいてモーターを制御します。
        """
        while True:
            direction = input('モーターの方向を選択してください。a=反時計回り、c=時計回り:')
            if direction == 'c':
                print('モーターが時計回りに動作中\n')
                break
            elif direction == 'a':
                print('モーターが反時計回りに動作中\n')
                break
            else:
                print('入力エラー、もう一度やり直してください!')
    
        # 選択した方向にモーターを継続的に回転させます
        while True:
            rotary(direction)
    
  6. 「destroy」関数はすべてのモーターピンをオフにします。これはクリーンなシャットダウンのために使用され、プログラムが終了したときにモーターが安全に停止することを保証します。

    def destroy():
        """
        クリーンなシャットダウンに使用される、すべてのモーターピンを安全にオフにします。
        """
        for pin in motorPin:
            pin.off()
    
  7. メインプログラムは「loop」を呼び出し、キーボード割り込み(Ctrl+Cなど)を処理して「destroy」を使用してモーターを安全にシャットダウンします。

    # メインプログラムの実行
    try:
        loop()
    except KeyboardInterrupt:
        destroy()  # キーボード割り込みを処理してモーターを安全にシャットダウンします
    
1.3.4 リレー
はじめに

このプロジェクトでは、リレーの使用方法を学びます。リレーは、自動制御システムで一般的に使用されるコンポーネントの1つです。電圧、電流、温度、圧力などが予め設定された値に達したり、超えたり、低下したりした場合、リレーは回路を接続または切断して、機器を制御および保護します。

必要な部品

このプロジェクトでは、次の部品が必要です。

_images/1.3.4_relay_list.png
回路図
_images/1.3.4_relay_schematic.png
実験手順

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

_images/1.3.4_relay_circuit.png

ステップ2: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 1.3.4_Relay_zero.py

コードが実行されている間、LEDが点灯します。さらに、通常閉じている接点が切断され、通常開いている接点が閉じることによるチクタク音が聞こえます。

コード

注釈

以下のコードを変更、リセット、コピー、実行、停止することができます。ただし、それを行う前に、ソースコードのパスである davinci-kit-for-raspberry-pi/python-pi5 に移動する必要があります。コードを変更した後、その効果を確認するために直接実行できます。

#!/usr/bin/env python3
from gpiozero import OutputDevice  # GPIOピンを制御するためのクラスをインポート
from time import sleep  # 遅延用にsleep関数をインポート

# GPIOピン17に接続されたリレーを初期化します
relay = OutputDevice(17)

try:
    # リレーの状態を1秒ごとに切り替え続けるループ
    while True:
        print('リレーをオープンにします...')  # リレーがアクティブ化されていることを通知
        relay.on()  # リレーをオンにします(アクティブロー構成を想定)
        sleep(1)   # リレーを1秒間オンの状態に保持

        print('...リレーをクローズにします')  # リレーが非アクティブ化されていることを通知
        relay.off()  # リレーをオフにします
        sleep(1)   # リレーを1秒間オフの状態に保持

except KeyboardInterrupt:
    # キーボード割り込み(Ctrl+Cなど)を処理してループを終了
    relay.off()  # スクリプトを終了する前にリレーをオフにする
    pass

コードの説明

  1. このセクションでは、必要なライブラリをインポートしています。GPIOピンを制御するために gpiozero から OutputDevice を、時間制御のために time から sleep をインポートしています。

    #!/usr/bin/env python3
    from gpiozero import OutputDevice  # GPIOピンを制御するためのクラスをインポート
    from time import sleep  # 遅延用にsleep関数をインポート
    
  2. GPIOピン17に接続されたリレーを制御するための OutputDevice オブジェクトを初期化しています。

    # GPIOピン17に接続されたリレーを初期化します
    relay = OutputDevice(17)
    
  3. try ブロック内で、無限ループ while True がリレーの状態を繰り返し切り替えます。リレーは、各状態の間に1秒の遅延があり、コンソールにプリントされたステートメントが表示されます。

    try:
        # リレーの状態を1秒ごとに切り替え続けるループ
        while True:
            print('リレーをオープンにします...')  # リレーがアクティブ化されていることを通知
            relay.on()  # リレーをオンにします(アクティブロー構成を想定)
            sleep(1)   # リレーを1秒間オンの状態に保持
    
            print('...リレーをクローズにします')  # リレーが非アクティブ化されていることを通知
            relay.off()  # リレーをオフにします
            sleep(1)   # リレーを1秒間オフの状態に保持
    
  4. KeyboardInterrupt(Ctrl+Cなど)をキャッチして、スクリプトを正常に終了する前にリレーをオフにします。

    except KeyboardInterrupt:
      # キーボード割り込み(Ctrl+Cなど)を処理してループを終了
      relay.off()  # スクリプトを終了する前にリレーをオフにする
      pass
    

2 入力

2.1 コントローラー

2.1.1 ボタン
はじめに

このプロジェクトでは、ボタンを使用してLEDをオンまたはオフにする方法を学びます。

必要な部品

このプロジェクトには、以下の部品が必要です。

_images/2.1.1_Button_list.png
回路図

Raspberry Piの入力として通常開放ボタンを使用し、接続は以下の回路図に示す通りです。ボタンが押されると、GPIO18は高レベル(3.3V)になります。プログラムを介してGPIO18の状態を検出できます。つまり、GPIO18が高レベルになると、ボタンが押されたことを意味します。ボタンが押されたときに対応するコードを実行し、LEDが点灯します。

注釈

LEDの長いピンが陽極であり、短いピンが陰極です。

_images/2.1.1_Button_schematic_1.png _images/2.1.1_Button_schematic_2.png
実験手順

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

_images/2.1.1_Button_circuit.png

ステップ2: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ3: コードを実行します。

sudo python3 2.1.1_Button_zero.py

ボタンを押すとLEDが点灯し、ボタンを離すとLEDが消灯します。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。ただし、それに先立ち、 davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を直接確認するために実行できます。

#!/usr/bin/env python3
from gpiozero import LED, Button  # gpiozeroからLEDとButtonクラスをインポート
from signal import pause  # signalモジュールからpause関数をインポート

# GPIOピン17に接続されたLEDオブジェクトを初期化
led = LED(17)
# GPIOピン18に接続されたButtonオブジェクトを初期化
button = Button(18)

# ボタンの「when_pressed」イベントをLEDの「on()」メソッドにリンク
button.when_pressed = led.on
# ボタンの「when_released」イベントをLEDの「off()」メソッドにリンク
button.when_released = led.off

# ボタンのイベントを待ち続け、スクリプトを実行し続けるイベントループを実行
pause()

コードの説明

  1. このスクリプトはPython3で書かれており、 gpiozero ライブラリから LED および Button クラス、 signal モジュールから pause をインポートしています。

    #!/usr/bin/env python3
    from gpiozero import LED, Button  # gpiozeroからLEDとButtonクラスをインポート
    from signal import pause  # signalモジュールからpause関数をインポート
    
  2. GPIOピン17に接続されたLEDオブジェクトとGPIOピン18に接続されたボタンオブジェクトを初期化します。

    # GPIOピン17に接続されたLEDオブジェクトを初期化
    led = LED(17)
    # GPIOピン18に接続されたButtonオブジェクトを初期化
    button = Button(18)
    
  3. ボタンが押されたときにLEDが点灯し、ボタンが離されたときにLEDが消灯するようにイベントハンドラを設定します。

    # ボタンの「when_pressed」イベントをLEDの「on()」メソッドにリンク
    button.when_pressed = led.on
    # ボタンの「when_released」イベントをLEDの「off()」メソッドにリンク
    button.when_released = led.off
    
  4. ボタンの押下およびリリースイベントを待ち続けるために、スクリプトをイベントループ内で実行し続けます。

    # ボタンのイベントを待ち続け、スクリプトを実行し続けるイベントループを実行
    pause()
    
2.1.2 スライドスイッチ
はじめに

このプロジェクトでは、スライドスイッチの使用方法を学びます。通常、スライドスイッチは基板上にはんだ付けされて電源スイッチとして使用されますが、ここではそれをブレッドボードに挿入して使用し、しっかり固定されない場合があります。また、スライドスイッチをブレッドボードに取り付けてその機能を示します。

必要な部品

このプロジェクトには、以下の部品が必要です。

_images/2.1.2_slide_switch_list.png
回路図

スライドスイッチの中央のピンをGPIO17に接続し、2つのLEDをそれぞれGPIO22とGPIO27のピンに接続します。そして、スライドを引くと2つのLEDが交互に点灯するのを確認できます。

_images/2.1.2_slide_switch_schematic_1.png _images/2.1.2_slide_switch_schematic_2.png
実験手順

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

_images/2.1.2_slide_switch_circuit.png

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 2.1.2_Slider_zero.py

コードが実行されている間、スイッチを左に接続すると黄色のLEDが点灯し、右に接続すると赤いLEDが点灯します。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。ただし、それに先立ち、 davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を直接確認するために実行できます。

#!/usr/bin/env python3
from gpiozero import LED, Button  # GPIOデバイスを制御するためにLEDとButtonクラスをインポート
from time import sleep  # 遅延を追加するためにsleep関数をインポート

# プルアップ抵抗を無効にしてGPIOピン17に接続されたマイクロスイッチを初期化
micro_switch = Button(17, pull_up=False)
# GPIOピン22に接続されたLED1を初期化
led1 = LED(22)
# GPIOピン27に接続されたLED2を初期化
led2 = LED(27)

try:
    # マイクロスイッチの状態に基づいてLEDの状態を制御するメインループ
    while True:
        if micro_switch.is_pressed:  # マイクロスイッチが押されているかどうかを確認
            print('    LED1 ON    ')  # ステータスメッセージを表示
            led1.on()   # LED1を点灯
            led2.off()  # LED2を消灯
        else:  # マイクロスイッチが押されていない場合
            print('    LED2 ON    ')  # ステータスメッセージを表示
            led1.off()  # LED1を消灯
            led2.on()   # LED2を点灯

        sleep(0.5)  # スイッチの状態を再確認する前に0.5秒待機

except KeyboardInterrupt:
    # キーボード割り込み(Ctrl+Cなど)を処理してループからきれいに終了する
    pass

コードの説明

  1. この行はスクリプトをPython 3で実行するように設定します。 gpiozero からGPIOデバイスを制御するために LED および Button をインポートし、遅延のために time から sleep をインポートします。

    #!/usr/bin/env python3
    from gpiozero import LED, Button  # GPIOデバイスを制御するためにLEDとButtonクラスをインポート
    from time import sleep  # 遅延を追加するためにsleep関数をインポート
    
  2. プルアップ抵抗を無効にしてGPIOピン17に接続されたマイクロスイッチ、GPIOピン22と27に接続された2つのLEDを初期化します。

    # プルアップ抵抗を無効にしてGPIOピン17に接続されたマイクロスイッチを初期化
    micro_switch = Button(17, pull_up=False)
    # GPIOピン22に接続されたLED1を初期化
    led1 = LED(22)
    # GPIOピン27に接続されたLED2を初期化
    led2 = LED(27)
    
  3. メインループはマイクロスイッチの状態を確認します。押されている場合、LED1が点灯し、LED2が消灯します。押されていない場合、LED1が消灯し、LED2が点灯します。ループは0.5秒ごとに繰り返されます。キーボード割り込み(Ctrl+Cなど)をキャッチしてスクリプトのきれいな終了を許可します。

    try:
    # マイクロスイッチの状態に基づいてLEDの状態を制御するメインループ
    while True:
        if micro_switch.is_pressed:  # マイクロスイッチが押されているかどうかを確認
            print('    LED1 ON    ')  # ステータスメッセージを表示
            led1.on()   # LED1を点灯
            led2.off()  # LED2を消灯
        else:  # マイクロスイッチが押されていない場合
            print('    LED2 ON    ')  # ステータスメッセージを表示
            led1.off()  # LED1を消灯
            led2.on()   # LED2を点灯
    
        sleep(0.5)  # スイッチの状態を再確認する前に0.5秒待機
    
    except KeyboardInterrupt:
        # キーボード割り込み(Ctrl+Cなど)を処理してループからきれいに終了する
        pass
    
2.1.3 傾斜スイッチ
はじめに

これは内部に金属のボールが入ったボール傾斜スイッチです。小さな角度の傾斜を検出するために使用されます。

必要な部品

このプロジェクトには、以下の部品が必要です。

_images/2.1.3_tilt_switch_list.png
回路図
_images/2.1.3_tilt_switch_schematic_1.png _images/2.1.3_tilt_switch_schematic_2.png
実験手順

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

_images/2.1.3_tilt_switch_circuit.png

ステップ2: ディレクトリを変更します。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 2.1.3_Tilt_zero.py

傾けて垂直に置くと、緑のLEDが点灯します。傾けると、画面に「傾けました!」と表示され、赤いLEDが点灯します。再び垂直に置くと、緑のLEDが点灯します。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。ただし、それに先立ち、 davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を直接確認するために実行できます。

#!/usr/bin/env python3
from gpiozero import LED, Button

# GPIO Zeroを使用して傾斜センサーとLEDを初期化します
TiltPin = Button(17, pull_up=False)  # プルアップ抵抗が無効化されたGPIOピン17に接続された傾斜センサーを初期化
green_led = LED(27)  # GPIOピン27に接続された緑色のLEDを初期化
red_led = LED(22)   # GPIOピン22に接続された赤色のLEDを初期化

def detect():
    """
    傾斜センサーの状態を検出し、LEDを制御します。
    傾けた場合、赤いLEDを点灯し、緑のLEDを消灯します。
    傾けていない場合、その逆を行います。
    """
    if TiltPin.is_pressed:  # センサーが傾いているかどうかを確認
        print('    *************')
        print('    *   傾けました!   *')
        print('    *************')
        red_led.on()   # 赤いLEDを点灯
        green_led.off()  # 緑のLEDを消灯
    else:  # センサーが傾いていない場合
        red_led.off()  # 赤いLEDを消灯
        green_led.on()  # 緑のLEDを点灯

try:
    while True:
        # 傾斜センサーの状態を継続的に確認し、LEDを更新します
        TiltPin.when_pressed = detect
        TiltPin.when_released = detect

except KeyboardInterrupt:
    # キーボード割り込み(Ctrl+C)を処理してループをきれいに終了します
    pass

コードの説明

  1. この行はスクリプトをPython 3で実行するように設定し、 gpiozero からGPIOデバイスを制御するために LEDButton をインポートします。

    #!/usr/bin/env python3
    from gpiozero import LED, Button
    
  2. プルアップ抵抗が無効化されたGPIOピン17に接続された傾斜センサーと、GPIOピン27および22に接続された2つのLEDを初期化します。

    # GPIO Zeroを使用して傾斜センサーとLEDを初期化します
    TiltPin = Button(17, pull_up=False)  # プルアップ抵抗が無効化されたGPIOピン17に接続された傾斜センサーを初期化
    green_led = LED(27)  # GPIOピン27に接続された緑色のLEDを初期化
    red_led = LED(22)   # GPIOピン22に接続された赤色のLEDを初期化
    
  3. detect 関数を定義し、傾斜センサーの状態をチェックします。傾けた場合、赤いLEDを点灯し、緑のLEDを消灯します。傾けていない場合、その逆を行います。

    def detect():
        """
        傾斜センサーの状態を検出し、LEDを制御します。
        傾けた場合、赤いLEDを点灯し、緑のLEDを消灯します。
        傾けていない場合、その逆を行います。
        """
        if TiltPin.is_pressed:  # センサーが傾いているかどうかを確認
            print('    *************')
            print('    *   傾けました!   *')
            print('    *************')
            red_led.on()   # 赤いLEDを点灯
            green_led.off()  # 緑のLEDを消灯
        else:  # センサーが傾いていない場合
            red_led.off()  # 赤いLEDを消灯
            green_led.on()  # 緑のLEDを点灯
    
  4. メインループは傾斜センサーの when_pressedwhen_released イベントに detect 関数を割り当てます。 try-except ブロックは優雅な終了のためにキーボード割り込みを処理します。

    try:
        while True:
            # 傾斜センサーの状態を継続的に確認し、LEDを更新します
            TiltPin.when_pressed = detect
            TiltPin.when_released = detect
    
    except KeyboardInterrupt:
        # キーボード割り込み(Ctrl+C)を処理してループをきれいに終了します
        pass
    
2.1.4 ポテンショメータ
はじめに

ADC(アナログデジタルコンバータ)機能は、アナログ信号をデジタル信号に変換するために使用できます。この実験では、ADC0834を使用してADCに関連する機能を取得します。ここでは、ポテンショメータを使用してこのプロセスを実装します。ポテンショメータは物理的な量である電圧を変化させ、ADC機能によって変換されます。

必要な部品

このプロジェクトには、以下の部品が必要です。

_images/2.1.7_potentiometer_list.png
回路図
_images/2.1.7_potentiometer_second_1.png _images/2.1.7_potentiometer_second_2.png
実験手順

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

_images/2.1.7_Potentiometer_circuit.png

注釈

画像に示されている対応する位置を参照して、チップを配置してください。チップの溝は左側にある必要があります。

ステップ2: コードファイルを開きます。

cd ~/raphael-kit/python-pi5

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

sudo python3 2.1.4_Potentiometer_zero.py

コードが実行されたら、ポテンショメータのつまみを回すと、LEDの輝度がそれに応じて変化します。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 できます。ただし、それに先立ち、 raphael-kit/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を直接確認するために実行できます。

#!/usr/bin/env python3

from gpiozero import PWMLED
import ADC0834
import time

# Initialize a PWM LED on GPIO pin 22
led = PWMLED(22)

# Set up the ADC0834 module
ADC0834.setup()

def MAP(x, in_min, in_max, out_min, out_max):
    """
    Map a value from one range to another.
    :param x: The value to be mapped.
    :param in_min: The lower bound of the value's current range.
    :param in_max: The upper bound of the value's current range.
    :param out_min: The lower bound of the value's target range.
    :param out_max: The upper bound of the value's target range.
    :return: The mapped value.
    """
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

try:
    while True:
        # Get the current reading from the ADC0834 module
        res = ADC0834.getResult()
        print('res = %d' % res)

        # Map the ADC value to a range suitable for setting LED brightness
        R_val = MAP(res, 0, 255, 0, 100)

        # Set the LED brightness
        led.value = float(R_val / 100)

        # Wait for 0.2 seconds before reading again
        time.sleep(0.2)

# Graceful exit when 'Ctrl+C' is pressed
except KeyboardInterrupt:
    led.value = 0  # Turn off the LED

コードの説明

  1. PWM LEDの制御には「gpiozero」、アナログからデジタルへの変換には「ADC0834」、遅延の実装には「time」が使用されています。

    #!/usr/bin/env python3
    
    from gpiozero import PWMLED
    import ADC0834
    import time
    
  2. GPIOピン22に接続されたPWMLEDオブジェクトを初期化し、ADC0834コンバータをセットアップします。

    # GPIOピン22にPWM LEDを初期化します
    led = PWMLED(22)
    
    # ADC0834モジュールをセットアップします
    ADC0834.setup()
    
  3. 1つの範囲の値を別の範囲に変換するための「MAP」という名前の関数を定義し、ADCの値を適切なLEDの明るさにマッピングするのに役立ちます。

    def MAP(x, in_min, in_max, out_min, out_max):
        return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
    
  4. ループ内でADC値を連続して読み取り、ADCの読み取り値(0-255)をLEDの明るさ(0-100)にマッピングします。このマップされた値に基づいてLEDの明るさを調整します。視認性と安定性を向上させるために0.2秒の遅延を実装します。

    try:
        while True:
            # ADC0834モジュールから現在の読み取り値を取得します
            res = ADC0834.getResult()
            print('res = %d' % res)
    
            # ADCの値をLEDの明るさを設定するための適切な範囲にマップします
            R_val = MAP(res, 0, 255, 0, 100)
    
            # LEDの明るさを設定します
            led.value = float(R_val / 100)
    
            # 再度読み取る前に0.2秒待機します
            time.sleep(0.2)
    
    # 'Ctrl+C'が押されたときの優雅な終了
    except KeyboardInterrupt:
        led.value = 0  # LEDをオフにする
    
2.1.5 キーパッド
はじめに

キーパッドはボタンの長方形の配列です。このプロジェクトでは、 キーパッドを文字の入力に使用します。

必要なコンポーネント

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

_images/2.1.5_keypad_list.png
回路図
_images/2.1.5_keypad_chematic_1.png _images/2.1.5_keypad_chematic_2.png
実験手順

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

_images/2.1.5_keypad_circuit.png

ステップ 2: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 2.1.5_Keypad_zero.py

コードを実行すると、キーパッドのボタンの押下値(ボタンの値)が画面に表示されます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に davinci-kit-for-raspberry-pi/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
from gpiozero import DigitalOutputDevice, Button
from time import sleep

class Keypad:
    def __init__(self, rows_pins, cols_pins, keys):
        """
        指定された行と列のピン、およびキーパッドのレイアウトでキーパッドを初期化します。
        :param rows_pins: 行のGPIOピンのリスト。
        :param cols_pins: 列のGPIOピンのリスト。
        :param keys: キーパッドのレイアウトのキーリスト。
        """
        # 行のピンをDigitalOutputDeviceとして初期化
        self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]
        # 列のピンをButtonとして初期化
        self.cols = [Button(pin, pull_up=False) for pin in cols_pins]
        self.keys = keys  # キーパッドのレイアウトを設定

    def read(self):
        """
        キーパッドで現在押されているキーを読み取ります。
        :return: 押されたキーのリスト。
        """
        pressed_keys = []
        # 押されたキーを識別するために各行と列をスキャン
        for i, row in enumerate(self.rows):
            row.on()  # 現在の行を有効にする
            for j, col in enumerate(self.cols):
                if col.is_pressed:  # 列のボタンが押されているか確認
                    # 行と列に基づいてキーのインデックスを計算
                    index = i * len(self.cols) + j
                    pressed_keys.append(self.keys[index])
            row.off()  # 現在の行を無効にする
        return pressed_keys

try:
    # 行、列、およびキーパッドのレイアウトを設定
    rows_pins = [18, 23, 24, 25]
    cols_pins = [10, 22, 27, 17]
    keys = ["1", "2", "3", "A",
            "4", "5", "6", "B",
            "7", "8", "9", "C",
            "*", "0", "#", "D"]

    # Keypadクラスのインスタンスを作成
    keypad = Keypad(rows_pins, cols_pins, keys)
    last_key_pressed = []

    # キーパッドを連続的に読み取り、新たに押されたキーを表示
    while True:
        pressed_keys = keypad.read()
        if pressed_keys and pressed_keys != last_key_pressed:
            print(pressed_keys)  # 押されたキーのリストを表示
            last_key_pressed = pressed_keys
        sleep(0.1)  # CPU負荷を軽減するための短い遅延

except KeyboardInterrupt:
    # キーボード割り込み(Ctrl+Cなど)を処理してスクリプトを正常に終了
    pass

コードの説明

  1. gpiozero ライブラリから DigitalOutputDevice および Button クラス、遅延のための sleep 関数をインポートします。

    #!/usr/bin/env python3
    from gpiozero import DigitalOutputDevice, Button
    from time import sleep
    
  2. Keypad クラスを定義します。 __init__ メソッドは、指定された行と列のピンとキーパッドのキーレイアウトでキーパッドを初期化します。 read メソッドはキーパッドをスキャンし、押されたキーのリストを返します。

    class Keypad:
        def __init__(self, rows_pins, cols_pins, keys):
            """
            指定された行と列のピン、およびキーパッドのレイアウトでキーパッドを初期化します。
            :param rows_pins: 行のGPIOピンのリスト。
            :param cols_pins: 列のGPIOピンのリスト。
            :param keys: キーパッドのレイアウトのキーリスト。
            """
            # 行のピンをDigitalOutputDeviceとして初期化
            self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]
            # 列のピンをButtonとして初期化
            self.cols = [Button(pin, pull_up=False) for pin in cols_pins]
            self.keys = keys  # キーパッドのレイアウトを設定
    
        def read(self):
            """
            キーパッドで現在押されているキーを読み取ります。
            :return: 押されたキーのリスト。
            """
            pressed_keys = []
            # 押されたキーを識別するために各行と列をスキャン
            for i, row in enumerate(self.rows):
                row.on()  # 現在の行を有効にする
                for j, col in enumerate(self.cols):
                    if col.is_pressed:  # 列のボタンが押されているか確認
                        # 行と列に基づいてキーのインデックスを計算
                        index = i * len(self.cols) + j
                        pressed_keys.append(self.keys[index])
                row.off()  # 現在の行を無効にする
            return pressed_keys
    
  3. GPIOピンの行と列を設定し、キーパッドのレイアウトを定義します。

    try:
        # 行、列、およびキーパッドのレイアウトを設定
        rows_pins = [18, 23, 24, 25]
        cols_pins = [10, 22, 27, 17]
        keys = ["1", "2", "3", "A",
                "4", "5", "6", "B",
                "7", "8", "9", "C",
                "*", "0", "#", "D"]
    
  4. 指定された設定で Keypad クラスのインスタンスを作成します。

    try:
        ...
    
        # Keypadクラスのインスタンスを作成
        keypad = Keypad(rows_pins, cols_pins, keys)
        last_key_pressed = []
    
  5. キーパッドを連続的に読み取り、キーの状態に変更があればそれを表示し、CPU負荷を軽減するために短い遅延を導入します。キーボード割り込み(Ctrl+Cなど)が発生した場合、スクリプトをきれいに終了するために処理します。

    try:
        ...
    
        # キーパッドを連続的に読み取り、新たに押されたキーを表示
        while True:
            pressed_keys = keypad.read()
            if pressed_keys and pressed_keys != last_key_pressed:
                print(pressed_keys)  # 押されたキーのリストを表示
                last_key_pressed = pressed_keys
            sleep(0.1)  # CPU負荷を軽減するための短い遅延
    
    except KeyboardInterrupt:
        # キーボード割り込み(Ctrl+Cなど)を処理してスクリプトを正常に終了
        pass
    
2.1.6 ジョイスティック
はじめに

このプロジェクトでは、ジョイスティックの動作を学びます。ジョイスティックを操作し、その結果を画面に表示します。

必要なコンポーネント

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

_images/2.1.9_joystick_list.png
回路図

ジョイスティックのデータを読み取る際、軸ごとにいくつかの違いがあります。X軸およびY軸のデータはアナログで、アナログ値をデジタル値に変換するにはADC0834を使用する必要があります。Z軸のデータはデジタルですので、GPIOを直接読み取ることもできますし、ADCを使用しても読み取ることができます。

_images/2.1.9_joystick_schematic_1.png _images/2.1.9_joystick_schematic_2.png
実験手順

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

_images/2.1.9_Joystick_circuit.png

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

cd ~/raphael-kit/python-pi5

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

sudo python3 2.1.6_Joystick_zero.py

コードを実行した後、ジョイスティックを動かし、対応するx、y、Btnの値が画面に表示されます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に raphael-kit/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
from gpiozero import Button
import ADC0834
import time

# GPIOピン22に接続されたボタンを初期化
BtnPin = Button(22)

# ADC0834 ADCのセットアップ
ADC0834.setup()

try:
    # ADC値とボタンの状態を読み取り、表示するメインループ
    while True:
        # ADCチャンネル0と1からXとYの値を読み取ります
        x_val = ADC0834.getResult(0)
        y_val = ADC0834.getResult(1)

        # ボタンの状態(押されているかどうか)を読み取ります
        Btn_val = BtnPin.value

        # X、Y、およびボタンの値を表示します
        print('X: %d  Y: %d  Btn: %d' % (x_val, y_val, Btn_val))

        # 次の読み取り前に0.2秒の遅延
        time.sleep(0.2)

# スクリプトの正常な終了を確実に処理します(たとえば、キーボード割り込みを介して)
except KeyboardInterrupt:
    pass

コードの説明

  1. このセクションでは、 gpiozero ライブラリから Button クラスをインポートして、GPIOピンに接続されたボタンを管理します。また、ADC0834 ADC(アナログ-デジタルコンバータ)モジュールとのインタフェースのために ADC0834 ライブラリもインポートします。

    #!/usr/bin/env python3
    from gpiozero import Button
    import ADC0834
    import time
    
  2. GPIOピン22に接続されたボタンを初期化し、ADC0834モジュールを使用するためのセットアップを行います。

    # GPIOピン22に接続されたボタンを初期化
    BtnPin = Button(22)
    
    # ADC0834 ADCのセットアップ
    ADC0834.setup()
    
  3. ジョイスティックのVRXおよびVRY接続はそれぞれADC0834のCH0およびCH1に接続されています。これにより、CH0およびCH1から値を読み取ることが容易になり、それらの値は x_val および y_val 変数に保存されます。さらに、ジョイスティックのSW値が読み取られ、 Btn_val 変数に割り当てられます。取得した x_valy_val、および Btn_val の値は、 print() 関数を使用して表示されます。

    try:
        # ADC値とボタンの状態を読み取り、表示するメインループ
        while True:
            # ADCチャンネル0と1からXとYの値を読み取ります
            x_val = ADC0834.getResult(0)
            y_val = ADC0834.getResult(1)
    
            # ボタンの状態(押されているかどうか)を読み取ります
            Btn_val = BtnPin.value
    
            # X、Y、およびボタンの値を表示します
            print('X: %d  Y: %d  Btn: %d' % (x_val, y_val, Btn_val))
    
            # 次の読み取り前に0.2秒の遅延
            time.sleep(0.2)
    
    # スクリプトの正常な終了を確実に処理します(たとえば、キーボード割り込みを介して)
    except KeyboardInterrupt:
        pass
    

2.2 センサー

2.2.1 フォトレジスタ
はじめに

フォトレジスタは、日常生活で環境光の強度を測定するためによく使用されるコンポーネントです。これにより、コントローラは昼と夜を認識し、ナイトランプなどの光制御機能を実現します。このプロジェクトはポテンショメーターに非常に似ており、電圧を変化させて光を検出します。

必要なコンポーネント

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

_images/2.2.1_photoresistor_list.png
回路図
_images/2.2.1_photoresistor_schematic_1.png _images/2.2.1_photoresistor_schematic_2.png
実験手順

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

_images/2.2.1_photoresistor_circuit.png

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

cd ~/raphael-kit/python-pi5

ステップ 3: 実行可能ファイルを実行します。

sudo python3 2.2.1_Photoresistor_zero.py

コードが実行されていると、フォトレジスタで検出された光の強度に応じてLEDの明るさが変化します。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に raphael-kit/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
from gpiozero import PWMLED
import ADC0834
import time

# GPIOピン22に接続されたPWM LEDを初期化
led = PWMLED(22)

# ADC0834モジュールをセットアップ
ADC0834.setup()

# 値を別の範囲にマップするための関数を定義
def MAP(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

# ADC値を読み取り、LEDの明るさを制御するメインループ
def loop():
    while True:
        # ADCからアナログ値を読み取る
        analogVal = ADC0834.getResult()
        print('value = %d' % analogVal)

        # ADCの値をPWM値にマップしてLEDの明るさを設定
        led.value = float(analogVal/255)

        # 0.2秒待つ
        time.sleep(0.2)

# メインループを実行し、KeyboardInterruptに対応して正常なシャットダウンを処理
try:
    loop()
except KeyboardInterrupt:
    # プログラムが停止したときにLEDをオフにする
    led.value = 0

コードの説明

  1. このセクションでは、 gpiozero ライブラリから PWMLED クラスをインポートして、PWM LED の制御に必要です。また、アナログ-デジタルコンバータとのインタフェースのために ADC0834 モジュールを含み、sleep などの時間ベースの関数を実行するために time モジュールもインポートしています。

    #!/usr/bin/env python3
    from gpiozero import PWMLED
    import ADC0834
    import time
    
  2. GPIOピン22に接続されたPWM LEDを初期化し、ADC0834モジュールをセットアップしてプロジェクトで使用する準備を行います。

    # GPIOピン22に接続されたPWM LEDを初期化
    led = PWMLED(22)
    
    # ADC0834モジュールをセットアップ
    ADC0834.setup()
    
  3. 1つの範囲から別の範囲への値をマップするための関数を定義します。この関数は、ADCの読み取りをPWM制御に適した範囲に変換するために重要です。

    # 値を別の範囲にマップするための関数を定義
    def MAP(x, in_min, in_max, out_min, out_max):
        return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
    
  4. このセクションには、アナログ値をADC0834から連続して読み取り、対応するPWM値にマップし、LEDの明るさを調整するループが含まれています。変更を可視化し、CPUへの負荷を軽減するために短い遅延(time.sleep(0.2))が含まれています。

    # ADC値を読み取り、LEDの明るさを制御するメインループ
    def loop():
        while True:
            # ADCからアナログ値を読み取る
            analogVal = ADC0834.getResult()
            print('value = %d' % analogVal)
    
            # ADCの値をPWM値にマップしてLEDの明るさを設定
            led.value = float(analogVal/255)
    
            # 0.2秒待つ
            time.sleep(0.2)
    
  5. loop 関数を実行し、KeyboardInterrupt に対応して正常なシャットダウンを行います。プログラムが停止すると、LEDがオフになるようにします。

    # メインループを実行し、KeyboardInterruptに対応して正常なシャットダウンを処理
    try:
        loop()
    except KeyboardInterrupt:
        # プログラムが停止したときにLEDをオフにする
        led.value = 0
    
2.2.2 サーミスタ
はじめに

フォトレジスタが光を感知するように、サーミスタは温度に感応する電子デバイスで、温度制御などの機能を実現するために使用できます。たとえば、ヒートアラームを作成することができます。

必要なコンポーネント

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

_images/2.2.2_thermistor_list.png
回路図
_images/2.2.2_thermistor_schematic_1.png _images/2.2.2_thermistor_schematic_2.png
実験手順

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

_images/2.2.2_thermistor_circuit.png

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

cd ~/raphael-kit/python-pi5

ステップ 3: 実行可能ファイルを実行します。

sudo python3 2.2.2_Thermistor_zero.py

コードを実行すると、サーミスタが周囲の温度を検出し、プログラムの計算が終了すると温度が画面に表示されます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に raphael-kit/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import ADC0834
import time
import math

# ADC0834モジュールを初期化
ADC0834.setup()

# try-exceptブロック内でプロセスを実行
try:
    while True:
        # センサーからアナログ値を読み取る
        analogVal = ADC0834.getResult()

        # アナログ値を電圧に変換
        Vr = 5 * float(analogVal) / 255

        # サーミスタの抵抗を計算
        Rt = 10000 * Vr / (5 - Vr)

        # ケルビンで温度を計算
        temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))

        # ケルビンを摂氏に変換
        Cel = temp - 273.15

        # 摂氏を華氏に変換
        Fah = Cel * 1.8 + 32

        # 摂氏と華氏の両方で温度を表示
        print('Celsius: %.2f C  Fahrenheit: %.2f F' % (Cel, Fah))

        # 次の読み取り前に0.2秒待つ
        time.sleep(0.2)

# graceful terminationのためにKeyboardInterruptを処理
except KeyboardInterrupt:
    # ADC0834のリソースをクリーンアップ
    ADC0834.destroy()

コードの説明

  1. このセクションでは、アナログ-デジタル変換用のADC0834ライブラリ、遅延を実装するためのtimeライブラリ、数学的操作を行うためのmathライブラリをインポートしています。

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import ADC0834
    import time
    import math
    
  2. アナログ値の読み取りを可能にするためにADC0834モジュールを初期化します。

    # ADC0834モジュールを初期化
    ADC0834.setup()
    
  3. 無限ループを実装してデータの連続読み取りを行います。ループはサーミスタからアナログ値を読み取り、この値を電圧に変換し、サーミスタの抵抗を計算し、その抵抗をケルビン、摂氏、華氏の温度測定に変換します。温度の読み取りを摂氏と華氏の両方で出力し、各読み取りの間に0.2秒の待機を挿入します。

    # try-exceptブロック内でプロセスを実行
    try:
        while True:
            # センサーからアナログ値を読み取る
            analogVal = ADC0834.getResult()
    
            # アナログ値を電圧に変換
            Vr = 5 * float(analogVal) / 255
    
            # サーミスタの抵抗を計算
            Rt = 10000 * Vr / (5 - Vr)
    
            # ケルビンで温度を計算
            temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
    
            # ケルビンを摂氏に変換
            Cel = temp - 273.15
    
            # 摂氏を華氏に変換
            Fah = Cel * 1.8 + 32
    
            # 摂氏と華氏の両方で温度を表示
            print('Celsius: %.2f C  Fahrenheit: %.2f F' % (Cel, Fah))
    
            # 次の読み取り前に0.2秒待つ
            time.sleep(0.2)
    
  4. プログラムを正常に終了するためのKeyboardInterrupt例外をキャッチし、終了時にADC0834のリソースをクリーンアップする命令を含めています。

    # graceful terminationのためにKeyboardInterruptを処理
    except KeyboardInterrupt:
        # ADC0834のリソースをクリーンアップ
        ADC0834.destroy()
    
2.2.3 PIR(人体赤外線センサー)
はじめに

このプロジェクトでは、人体赤外線センサーを使用してデバイスを作成します。誰かがLEDに近づくと、LEDが自動で点灯します。そうでない場合、光は消えます。この赤外線モーションセンサーは、人間や動物から放射される赤外線を検出できるセンサーの一種です。

必要なコンポーネント

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

_images/2.2.4_pir_list.png
回路図
_images/2.2.4_pir_schematic.png
実験手順

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

_images/2.2.4_pir_circuit.png

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ 3: 実行可能ファイルを実行します。

sudo python3 2.2.4_PIR_zero.py

コードを実行すると、PIRが周囲を検出し、誰かが通り過ぎるのを感知するとRGB LEDが黄色に光ります。

PIRモジュールには2つのポテンショメーターがあります:感度を調整するためのものと検出距離を調整するためのものです。 PIRモジュールをより良く動作させるには、両方を反時計回りに回して最後まで回す必要があります。

_images/2.2.4_PIR_TTE.png

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に davinci-kit-for-raspberry-pi/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
from gpiozero import RGBLED, MotionSensor
from time import sleep

# GPIO Zeroライブラリを使用してRGB LEDとPIRモーションセンサーを初期化
led = RGBLED(red=18, green=27, blue=22)  # RGB LEDはGPIOピン18(赤)、27(緑)、22(青)に接続されています
pir = MotionSensor(17)  # PIRセンサーはGPIOピン17に接続されています

try:
    # モーションを監視し、LEDの色を更新し続けます
    while True:
        if pir.motion_detected:  # PIRセンサーによるモーションの検出を確認
            led.color = (1, 1, 0)  # LEDの色を黄色に設定します(赤 + 緑)
        else:
            led.color = (0, 0, 1)  # LEDの色を青に設定します(青のみ)
        sleep(0.1)  # CPU負荷を軽減するための短い遅延

except KeyboardInterrupt:
    # KeyboardInterrupt(Ctrl+C)を処理してループを gracefully に終了します
    pass

コードの説明

  1. GPIO ZeroライブラリからRGB LEDを制御するための RGBLED クラスと、モーション検出用の MotionSensor クラスをインポートします。また、遅延を作成するために sleep 関数をインポートします。

    #!/usr/bin/env python3
    from gpiozero import RGBLED, MotionSensor
    from time import sleep
    
  2. 赤、緑、青のコンポーネントを持つRGB LEDを初期化し、それぞれのコンポーネントをGPIOピン18、27、22に接続します。また、GPIOピン17にPIRセンサーを初期化します。

    # GPIO Zeroライブラリを使用してRGB LEDとPIRモーションセンサーを初期化
    led = RGBLED(red=18, green=27, blue=22)  # RGB LEDはGPIOピン18(赤)、27(緑)、22(青)に接続されています
    pir = MotionSensor(17)  # PIRセンサーはGPIOピン17に接続されています
    
  3. プログラムは無限ループに入り、PIRセンサーを使用してモーションを連続的に確認します。モーションが検出された場合、LEDは黄色に設定されます(赤と緑の組み合わせ)。モーションが検出されない場合、LEDは青に変わります。短い0.1秒の遅延がCPU負荷を軽減します。

    try:
        # モーションを監視し、LEDの色を更新し続けます
        while True:
            if pir.motion_detected:  # PIRセンサーによるモーションの検出を確認
                led.color = (1, 1, 0)  # LEDの色を黄色に設定します(赤 + 緑)
            else:
                led.color = (0, 0, 1)  # LEDの色を青に設定します(青のみ)
            sleep(0.1)  # CPU負荷を軽減するための短い遅延
    
    except KeyboardInterrupt:
        # KeyboardInterrupt(Ctrl+C)を処理してループを gracefully に終了します
        pass
    
2.2.4 超音波センサーモジュール
はじめに

超音波センサーは、物体を正確に検出し、距離を測定するために超音波を使用します。それは超音波を発信し、それらを電子信号に変換します。

必要なコンポーネント

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

_images/2.2.5_ultrasonic_list.png
回路図
_images/2.2.5_ultrasonic_schematic.png
実験手順

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

_images/2.2.5_ultrasonic_circuit.png

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ 3: 実行可能ファイルを実行します。

sudo python3 2.2.5_Ultrasonic_zero.py

コードを実行すると、超音波センサーモジュールが前方の障害物とモジュール自体の距離を検出し、その距離値が画面に表示されます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に davinci-kit-for-raspberry-pi/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

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

# GPIO Zeroライブラリを使用してDistanceSensorを初期化
# トリガーピンはGPIO 23に接続、エコーピンはGPIO 24に接続
sensor = DistanceSensor(echo=24, trigger=23)

try:
    # 距離を連続的に測定および報告するためのメインループ
    while True:
        dis = sensor.distance * 100  # 距離を測定し、メートルからセンチメートルに変換
        print('Distance: {:.2f} cm'.format(dis)) # 距離を小数点以下2桁の精度で表示
        sleep(0.3)  # 次の測定前に0.3秒待機

except KeyboardInterrupt:
    # KeyboardInterrupt(Ctrl+C)を処理してループを gracefully に終了します
    pass

コードの説明

  1. 遅延用に time モジュールから sleep 関数を含む、距離測定用の gpiozero ライブラリから DistanceSensor クラスをインポートします。

    #!/usr/bin/env python3
    from gpiozero import DistanceSensor
    from time import sleep
    
  2. エコーピンをGPIO 24に、トリガーピンをGPIO 23に接続した超音波距離センサーを初期化します。

    # GPIO Zeroライブラリを使用してDistanceSensorを初期化
    # トリガーピンはGPIO 23に接続、エコーピンはGPIO 24に接続
    sensor = DistanceSensor(echo=24, trigger=23)
    
  3. メインループは距離を連続して測定し、メートルからセンチメートルに変換し、小数点以下2桁の精度で表示します。その後、0.3秒待ってから距離を再測定します。 KeyboardInterrupt (Ctrl+Cのような)をキャッチしてスクリプトから gracefully に終了できるようにします。

    try:
        # 距離を連続的に測定および報告するためのメインループ
        while True:
            dis = sensor.distance * 100  # 距離を測定し、メートルからセンチメートルに変換
            print('Distance: {:.2f} cm'.format(dis))   # 距離を小数点以下2桁の精度で表示
            sleep(0.3)  # 次の測定前に0.3秒待機
    
    except KeyboardInterrupt:
        # KeyboardInterrupt(Ctrl+C)を処理してループを gracefully に終了します
        pass
    
2.2.5 MPU6050モジュール
はじめに

MPU-6050は、スマートフォン、タブレット、およびウェアラブルセンサー向けに設計された、世界初かつ唯一の6軸モーショントラッキングデバイス(3軸ジャイロスコープと3軸アクセラ​​​​メーター)です。低消費電力、低コスト、高性能の要件を持つこれらの機能を備えています。

この実験では、MPU6050の3軸加速度センサーと3軸ジャイロスコープの値をI2Cを使用して取得し、それらを画面に表示します。

必要なコンポーネント

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

_images/2.2.6_mpu6050_list.png
回路図

MPU6050はI2Cバスインターフェースを介してマイクロコントローラと通信します。SDA1とSCL1は対応するピンに接続する必要があります。

_images/2.2.6_mpu6050_schematic.png
実験手順

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

_images/2.2.6_mpu6050_circuit.png

ステップ 2: I2Cのセットアップを行います(Appendix I2C構成 を参照してください。I2Cを設定済みの場合は、このステップをスキップします。)

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

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ 4: 実行可能ファイルを実行します。

sudo python3 2.2.6_mpu6050_zero.py

コードを実行すると、MPU6050によって読み取られたx軸およびy軸の偏角、および加速度、各軸の角速度が計算された後、画面に表示されます。

注釈

  • エラーが発生した場合、 FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1' と表示される場合、I2Cを有効にするために I2C構成 を参照してください。

  • ModuleNotFoundError: No module named 'smbus2' エラーが表示された場合、 sudo pip3 install smbus2 を実行してください。

  • エラー OSError: [Errno 121] Remote I/O error が表示される場合、モジュールの接続が誤っているか、モジュールが壊れていることを示します。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に davinci-kit-for-raspberry-pi/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

import smbus
import math
import time

# 電源管理レジスタ
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

def read_byte(adr):
    return bus.read_byte_data(address, adr)

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val

def dist(a,b):
    return math.sqrt((a*a)+(b*b))

def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)

def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)


bus = smbus.SMBus(1) # or bus = smbus.SMBus(1) for Revision 2 boards
address = 0x68       # これはi2cdetectコマンドで読み取られるアドレス値です

# 6050をスリープモードから起こします
bus.write_byte_data(address, power_mgmt_1, 0)

while True:
    time.sleep(0.1)
    gyro_xout = read_word_2c(0x43)
    gyro_yout = read_word_2c(0x45)
    gyro_zout = read_word_2c(0x47)

    print ("gyro_xout : ", gyro_xout, " scaled: ", (gyro_xout / 131))
    print ("gyro_yout : ", gyro_yout, " scaled: ", (gyro_yout / 131))
    print ("gyro_zout : ", gyro_zout, " scaled: ", (gyro_zout / 131))

    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)

    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0

    print ("accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled)
    print ("accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled)
    print ("accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled)

    print ("x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
    print ("y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))

    time.sleep(1)

コードの説明

  1. MPU6050から送信されたセンサーデータを読み取ります。

    def read_word(adr):
        high = bus.read_byte_data(address, adr)
        low = bus.read_byte_data(address, adr+1)
        val = (high << 8) + low
        return val
    
    def read_word_2c(adr):
        val = read_word(adr)
        if (val >= 0x8000):
            return -((65535 - val) + 1)
        else:
            return val
    
  2. y軸の偏角を計算します。

    def get_y_rotation(x,y,z):
        radians = math.atan2(x, dist(y,z))
        return -math.degrees(radians)
    
  3. x軸の偏角を計算します。

    def get_x_rotation(x,y,z):
        radians = math.atan2(y, dist(x,z))
        return math.degrees(radians)
    
  4. ジャイロスコープセンサーのx軸、y軸、z軸の値を読み取り、メタデータを角速度の値に変換し、それらを表示します。

    gyro_xout = read_word_2c(0x43)
    gyro_yout = read_word_2c(0x45)
    gyro_zout = read_word_2c(0x47)
    
    print ("gyro_xout : ", gyro_xout, " scaled: ", (gyro_xout / 131))
    print ("gyro_yout : ", gyro_yout, " scaled: ", (gyro_yout / 131))
    print ("gyro_zout : ", gyro_zout, " scaled: ", (gyro_zout / 131))
    
  5. 加速度センサーのx軸、y軸、z軸の値を読み取り、その値を加速度(重力単位)に変換し、それらを表示します。

    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)
    
    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0
    
    print ("accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled)
    print ("accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled)
    print ("accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled)
    
  6. x軸およびy軸の偏角を表示します。

    print ("x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
    print ("y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
    

3 拡張

3.1.1 カウンティングデバイス
はじめに

ここでは、PIRセンサーと4桁のセグメントディスプレイからなる、数値表示カウンターシステムを作成します。PIRが通行人を検出すると、4桁のセグメントディスプレイに表示される数値が1つ増えます。このカウンターを使用して、通路を通過する人数をカウントできます。

必要なコンポーネント

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

_images/4.1.7_counting_device_list_1.png _images/4.1.7_counting_device_list_2.png
回路図
_images/4.1.7_counting_device_schematic.png
実験手順

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

_images/4.1.7_counting_device_circuit.png

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

cd ~/raphael-kit/python-pi5

ステップ 3: 実行可能ファイルを実行します。

sudo python3 3.1.1_CountingDevice_zero.py

コードを実行すると、PIRが通行人を検出すると、4桁のセグメントディスプレイに表示される数値が1つ増えます。

PIRモジュールには2つのポテンショメータがあります。1つは感度を調整するためのもので、もう1つは検出距離を調整するためのものです。PIRモジュールをより良く動作させるには、これらのポテンショメータを両方とも反時計回りにまわす必要があります。

_images/4.1.7_PIR_TTE.png

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に raphael-kit/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
from gpiozero import OutputDevice, MotionSensor

# GPIO 26に接続されたPIRモーションセンサーを初期化
pir = MotionSensor(26)

# シフトレジスタのピンを初期化
SDI = OutputDevice(24)    # シリアルデータ入力
RCLK = OutputDevice(23)   # レジスタクロック入力
SRCLK = OutputDevice(18)  # シフトレジスタクロック入力

# 7セグメントディスプレイのピンを初期化
placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]

# 7セグメントディスプレイに表示する数字のコードを定義
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# 表示される数値のカウンター
counter = 0

def clearDisplay():
    # すべてのセグメントをオフにしてディスプレイをクリア
    for _ in range(8):
        SDI.on()
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def hc595_shift(data):
    # データを74HC595シフトレジスタにシフト
    for i in range(8):
        SDI.value = 0x80 & (data << i)
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def pickDigit(digit):
    # 7セグメントディスプレイの特定の桁をアクティブ化
    for pin in placePin:
        pin.off()
    placePin[digit].on()

def display():
    # 現在のカウンター値でディスプレイを更新
    global counter
    clearDisplay()
    pickDigit(0)
    hc595_shift(number[counter % 10])

    clearDisplay()
    pickDigit(1)
    hc595_shift(number[counter % 100//10])

    clearDisplay()
    pickDigit(2)
    hc595_shift(number[counter % 1000//100])

    clearDisplay()
    pickDigit(3)
    hc595_shift(number[counter % 10000//1000])

def loop():
    # ディスプレイを連続的に更新し、モーションを確認するメインループ
    global counter
    currentState = 0
    lastState = 0
    while True:
        display()
        currentState = 1 if pir.motion_detected else 0
        if currentState == 1 and lastState == 0:
            counter += 1
        lastState = currentState

try:
    loop()
except KeyboardInterrupt:
    # スクリプトが中断されたときにすべてのピンをオフにする
    SDI.off()
    SRCLK.off()
    RCLK.off()
    pass

コードの説明

  1. この行では、 gpiozero ライブラリから OutputDeviceMotionSensor クラスをインポートします。 OutputDevice はLED、モーター、または出力として制御したい任意のデバイスを指します。 MotionSensor は通常、動きを検出するために使用されるPIR(受動赤外線)センサーです。

    #!/usr/bin/env python3
    from gpiozero import OutputDevice, MotionSensor
    
  2. GPIOピン26に接続されたPIRモーションセンサーを初期化します。

    # GPIO 26にPIRモーションセンサーを初期化
    pir = MotionSensor(26)
    
  3. シフトレジスタのシリアルデータ入力(SDI)、レジスタクロック入力(RCLK)、シフトレジスタクロック入力(SRCLK)に接続されたGPIOピンを初期化します。

    # シフトレジスタピンを初期化
    SDI = OutputDevice(24)    # シリアルデータ入力
    RCLK = OutputDevice(23)   # レジスタクロック入力
    SRCLK = OutputDevice(18)  # シフトレジスタクロック入力
    
  4. 7セグメント表示の各桁用のピンを初期化し、0-9の数字を表示するためのバイナリコードを定義します。

    # 7セグメント表示用ピンを初期化
    placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]
    
    # 7セグメント表示の数字コードを定義
    number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
    
  5. 次の数字を表示する前にすべてのセグメントをオフに設定して、7セグメント表示をクリアします。

    def clearDisplay():
        # すべてのセグメントをオフに設定して表示をクリアする
        for _ in range(8):
            SDI.on()
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
  6. 74HC595シフトレジスタに1バイトのデータをシフトし、表示セグメントを制御します。

    def hc595_shift(data):
        # 74HC595シフトレジスタにデータをシフトする
        for i in range(8):
            SDI.value = 0x80 & (data << i)
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
  7. 7セグメント表示のどの桁をアクティブにするかを選択します。各桁は別々のGPIOピンによって制御されます。

    def pickDigit(digit):
        # 7セグメント表示の特定の桁をアクティブにする
        for pin in placePin:
            pin.off()
        placePin[digit].on()
    
  8. 最初に単位の桁の表示を開始し、次に十の桁の表示をアクティブにします。その後、百と千の桁の表示を順に行います。この高速なアクティベーションの連続は、連続した4桁の表示の錯覚を作り出します。

    def display():
        # 現在のカウンター値で表示を更新する
        global counter
        clearDisplay()
        pickDigit(0)
        hc595_shift(number[counter % 10])
    
        clearDisplay()
        pickDigit(1)
        hc595_shift(number[counter % 100//10])
    
        clearDisplay()
        pickDigit(2)
        hc595_shift(number[counter % 1000//100])
    
        clearDisplay()
        pickDigit(3)
        hc595_shift(number[counter % 10000//1000])
    
  9. メインループを定義し、表示を継続的に更新し、PIRセンサーの状態をチェックします。動きが検出されると、カウンターが増加します。

    def loop():
        # 表示を更新し、動きをチェックするメインループ
        global counter
        currentState = 0
        lastState = 0
        while True:
            display()
            currentState = 1 if pir.motion_detected else 0
            if currentState == 1 and lastState == 0:
                counter += 1
            lastState = currentState
    
  10. メインループを実行し、キーボードコマンド(Ctrl+C)で中断できるようにします。クリーンな終了のためにすべてのピンをオフにします。

    try:
        loop()
    except KeyboardInterrupt:
        # スクリプトが中断されたときにすべてのピンをオフにする
        SDI.off()
        SRCLK.off()
        RCLK.off()
        pass
    
3.1.2 ようこそ
はじめに

このプロジェクトでは、歩行者の動きを検出するためにPIRを使用し、 センサー付きコンビニエンスストアの扉の動作を模倣するためにサーボ、LED、ブザーを使用します。歩行者がPIRの感知範囲内に現れると、インジケーターライトが点灯し、扉が開き、ブザーが開店ベルを演奏します。

必要なコンポーネント

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

_images/4.1.8_welcome_list.png
回路図
_images/4.1.8_welcome_schematic.png
実験手順

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

_images/4.1.8_welcome_circuit.png

ステップ 2: ディレクトリを変更します。

cd ~/raphael-kit/python-pi5

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

sudo python3 3.1.2_Welcome_zero.py

コードが実行されると、PIRセンサーが通行人を検出した場合、扉は自動的に開き(サーボで模倣)、インジケーターライトが点灯し、開店ベルの音楽が再生されます。ドアベルの音楽が再生された後、システムは自動的に扉を閉じ、インジケーターライトを消灯し、次回の通行人を待機します。

PIRモジュールには2つのポテンショメータがあります。1つは感度を調整するためのもので、もう1つは検出距離を調整するためのものです。PIRモジュールをより良く動作させるには、これらのポテンショメータを両方とも反時計回りにまわす必要があります。

_images/4.1.8_PIR_TTE.png

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、その前に raphael-kit/python-pi5 のソースコードパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3

from gpiozero import LED, MotionSensor, Servo, TonalBuzzer
import time

# LED、モーションセンサー(PIR)、ブザーのためのGPIOピン設定
ledPin = LED(6)
pirPin = MotionSensor(21)
buzPin = TonalBuzzer(27)

# サーボモーターパルス幅補正ファクターと計算
myCorrection = 0.45
maxPW = (2.0 + myCorrection) / 1000  # 最大パルス幅
minPW = (1.0 - myCorrection) / 1000  # 最小パルス幅

# サーボをカスタムパルス幅で初期化
servoPin = Servo(25, min_pulse_width=minPW, max_pulse_width=maxPW)

# ブザーの音楽のチューン、音符と持続時間が含まれています
tune = [('C#4', 0.2), ('D4', 0.2), (None, 0.2),
        ('Eb4', 0.2), ('E4', 0.2), (None, 0.6),
        ('F#4', 0.2), ('G4', 0.2), (None, 0.6),
        ('Eb4', 0.2), ('E4', 0.2), (None, 0.2),
        ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
        ('C4', 0.2), ('B4', 0.2), (None, 0.2),
        ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
        ('B4', 0.2), ('Bb4', 0.5), (None, 0.6),
        ('A4', 0.2), ('G4', 0.2), ('E4', 0.2),
        ('D4', 0.2), ('E4', 0.2)]

def setAngle(angle):
    """
    サーボを指定した角度に移動します。
    :param angle: 角度(0-180)。
    """
    value = float(angle / 180)  # 角度をサーボの値に変換
    servoPin.value = value      # サーボの位置を設定
    time.sleep(0.001)           # サーボの動作のための短い遅延

def doorbell():
    """
    ブザーを使用して音楽を演奏します。
    """
    for note, duration in tune:
        buzPin.play(note)       # 音符を演奏
        time.sleep(float(duration))  # 音符の持続時間
    buzPin.stop()               # チューン再生後にブザーを停止

def closedoor():
    # LEDをオフにし、サーボを使ってドアを閉めます
    ledPin.off()
    for i in range(180, -1, -1):
        setAngle(i)             # サーボを180度から0度まで移動
        time.sleep(0.001)       # スムーズな動作のための短い遅延
    time.sleep(1)               # ドアを閉めた後の待機

def opendoor():
    # LEDをオンにし、ドアを開ける(サーボを移動)、チューンを演奏し、ドアを閉じる
    ledPin.on()
    for i in range(0, 181):
        setAngle(i)             # サーボを0から180度まで移動
        time.sleep(0.001)       # スムーズな動作のための短い遅延
    time.sleep(1)               # チューンを演奏する前の待機
    doorbell()                  # ドアベルのチューンを演奏
    closedoor()                 # チューン演奏後にドアを閉じる

def loop():
    # モーションを確認し、ドアを操作するためのメインループ
    while True:
        if pirPin.motion_detected:
            opendoor()               # モーションが検出された場合はドアを開く
        time.sleep(0.1)              # ループ内の短い遅延

try:
    loop()
except KeyboardInterrupt:
    # ユーザーの割り込み(たとえば、Ctrl+C)でGPIOをクリーンアップ
    buzPin.stop()
    ledPin.off()

代码解释

  1. 脚本は必要なモジュールをインポートすることから始まります。 gpiozero ライブラリは、LED、モーションセンサー、サーボモーター、音楽ブザーとのインターフェースを提供するために使用されます。 time モジュールはタイミング関連の機能を処理するために使用されます。

    #!/usr/bin/env python3
    from gpiozero import LED, MotionSensor, Servo, TonalBuzzer
    import time
    
  2. LED、PIRモーションセンサー、音楽ブザーをそれぞれのGPIOピンに初期化します。

    # LED、モーションセンサー(PIR)、ブザーのためのGPIOピン設定
    ledPin = LED(6)
    pirPin = MotionSensor(21)
    buzPin = TonalBuzzer(27)
    
  3. サーボモーターの最大および最小パルス幅を計算し、微調整のための補正ファクターを組み込みます。

    # サーボモーターパルス幅補正ファクターと計算
    myCorrection = 0.45
    maxPW = (2.0 + myCorrection) / 1000  # 最大パルス幅
    minPW = (1.0 - myCorrection) / 1000  # 最小パルス幅
    
  4. サーボモーターを正確な位置に配置するためにカスタムパルス幅を使用してGPIOピン25上で初期化します。

    # サーボをカスタムパルス幅で初期化
    servoPin = Servo(25, min_pulse_width=minPW, max_pulse_width=maxPW)
    
  5. ブザーで演奏するための音楽チューンを、音符(周波数)と持続時間(秒)のシーケンスとして定義します。

    # ブザーの音楽のチューン、音符と持続時間が含まれています
    tune = [('C#4', 0.2), ('D4', 0.2), (None, 0.2),
            ('Eb4', 0.2), ('E4', 0.2), (None, 0.6),
            ('F#4', 0.2), ('G4', 0.2), (None, 0.6),
            ('Eb4', 0.2), ('E4', 0.2), (None, 0.2),
            ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
            ('C4', 0.2), ('B4', 0.2), (None, 0.2),
            ('F#4', 0.2), ('G4', 0.2), (None, 0.2),
            ('B4', 0.2), ('Bb4', 0.5), (None, 0.6),
            ('A4', 0.2), ('G4', 0.2), ('E4', 0.2),
            ('D4', 0.2), ('E4', 0.2)]
    
  6. 指定された角度にサーボを移動するための関数。角度をサーボの値に変換します。

    def setAngle(angle):
        """
        サーボを指定した角度に移動します。
        :param angle: 角度(0-180)。
        """
        value = float(angle / 180)  # 角度をサーボの値に変換
        servoPin.value = value      # サーボの位置を設定
        time.sleep(0.001)           # サーボの動作のための短い遅延
    
  7. ブザーを使用して音楽を演奏するための関数。 tune リスト内を繰り返し、各音符を指定された持続時間で演奏します。

    def doorbell():
        """
        ブザーを使用して音楽を演奏します。
        """
        for note, duration in tune:
            buzPin.play(note)       # 音符を演奏
            time.sleep(float(duration))  # 音符の持続時間
        buzPin.stop()               # チューン再生後にブザーを停止
    
  8. サーボモーターを使用してドアを開閉するための関数。 opendoor 関数はLEDを点灯させ、ドアを開け、音楽を演奏し、その後ドアを閉じます。

    def closedoor():
        # LEDをオフにし、サーボを使ってドアを閉めます
        ledPin.off()
        for i in range(180, -1, -1):
            setAngle(i)             # サーボを180度から0度まで移動
            time.sleep(0.001)       # スムーズな動作のための短い遅延
        time.sleep(1)               # ドアを閉めた後の待機
    
    def opendoor():
        # LEDをオンにし、ドアを開ける(サーボを移動)、チューンを演奏し、ドアを閉じる
        ledPin.on()
        for i in range(0, 181):
            setAngle(i)             # サーボを0から180度まで移動
            time.sleep(0.001)       # スムーズな動作のための短い遅延
        time.sleep(1)               # チューンを演奏する前の待機
        doorbell()                  # ドアベルのチューンを演奏
        closedoor()                 # チューン演奏後にドアを閉じる
    
  9. モーション検出を常にチェックするメインループ。モーションが検出された場合、 opendoor 関数がトリガーされます。

    def loop():
        # モーションを確認し、ドアを操作するためのメインループ
        while True:
            if pirPin.motion_detected:
                opendoor()               # モーションが検出された場合はドアを開く
            time.sleep(0.1)              # ループ内の短い遅延
    
  10. メインループを実行し、スクリプトをキーボードコマンド(Ctrl+C)で停止できるようにし、クリーンな終了のためにブザーとLEDをオフにします。

    try:
        loop()
    except KeyboardInterrupt:
        # ユーザーの割り込み(たとえば、Ctrl+C)でGPIOをクリーンアップ
        buzPin.stop()
        ledPin.off()
    
3.1.3 リバースアラーム
はじめに

このプロジェクトでは、LCD、ブザー、超音波センサーを使用して、リバースアシストシステムを作成します。これをリモートコントロール車に取り付けて、車をガレージにバックさせる実際のプロセスをシミュレートできます。

必要な部品

このプロジェクトには、以下の部品が必要です。

_images/4.1.9_reversing_alarm_list.png
回路図

超音波センサーは、障害物との距離をコードの形でLCDに表示します。同時に、超音波センサーは異なる距離値に応じてブザーから警告音を出力します。

_images/4.1.9_reversing_alarm_schematic.png
実験手順

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

_images/4.1.9_reversing_alarm_circuit.png

ステップ2: ディレクトリを変更します。

cd ~/raphael-kit/python-pi5

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

sudo python3 3.1.3_ReversingAlarm_zero.py

このコードを実行すると、超音波センサーモジュールが障害物までの距離を検出し、その距離情報をLCD1602に表示し、同時にブザーから距離に応じて周波数が変化する警告音が鳴ります。

注釈

  • FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1' エラーが発生した場合は、I2Cを有効にするために I2C構成 を参照してください。

  • ModuleNotFoundError: No module named 'smbus2' エラーが表示された場合は、sudo pip3 install smbus2 を実行してください。

  • エラー OSError: [Errno 121] Remote I/O error が表示された場合、モジュールの接続が誤っているか、モジュールが壊れていることを意味します。

  • コードと配線は正常ですが、LCDにコンテンツが表示されない場合は、バックのポテンショメーターを回してコントラストを増加させることができます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、変更する前に raphael-kit/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
import LCD1602
import time
from gpiozero import DistanceSensor, Buzzer

# GPIOピンとともに超音波センサーを初期化します
sensor = DistanceSensor(echo=24, trigger=23)  # EchoピンはGPIO 24、TriggerピンはGPIO 23です

# GPIOピン17に接続されたブザーを初期化します
buzzer = Buzzer(17)

def lcdsetup():
    # I2Cアドレスとバックライトを有効にしてLCDを初期化します
    LCD1602.init(0x27, 1)  # 0x27はLCDのI2Cアドレスです
    LCD1602.clear()  # LCDディスプレイをクリアします
    # LCDに起動メッセージを表示します
    LCD1602.write(0, 0, '超音波センサー起動中')
    LCD1602.write(1, 1, 'SunFounder製')
    time.sleep(2)  # 2秒待機します

def distance():
    # センサーによって測定された距離を計算して返します
    dis = sensor.distance * 100  # 距離をセンチメートルに変換します
    print('距離: {:.2f} cm'.format(dis))  # 小数点以下2桁の距離を表示します
    time.sleep(0.3)  # 次の測定まで0.3秒待機します
    return dis

def loop():
    # 距離を連続して測定し、LCDとブザーを更新します
    while True:
        dis = distance()  # 現在の距離を取得します
        # 距離に基づいて距離を表示し、アラートを処理します
        if dis > 400:  # 距離が範囲外かどうかをチェックします
            LCD1602.clear()
            LCD1602.write(0, 0, 'エラー')
            LCD1602.write(3, 1, '範囲外')
            time.sleep(0.5)
        else:
            # LCDに現在の距離を表示します
            LCD1602.clear()
            LCD1602.write(0, 0, '距離:')
            LCD1602.write(5, 1, str(round(dis, 2)) + ' cm')
            # 距離に基づいてブザーの周波数を調整します
            if dis >= 50:
                time.sleep(0.5)
            elif 20 < dis < 50:
                # 中距離:中程度のブザー周波数
                for _ in range(2):
                    buzzer.on()
                    time.sleep(0.05)
                    buzzer.off()
                    time.sleep(0.2)
            elif dis <= 20:
                # 近距離:高いブザー周波数
                for _ in range(5):
                    buzzer.on()
                    time.sleep(0.05)
                    buzzer.off()
                    time.sleep(0.05)

try:
    lcdsetup()  # LCDディスプレイをセットアップ
    loop()      # 測定ループを開始
except KeyboardInterrupt:
    # ユーザーによる割り込み(例:Ctrl+C)でブザーをオフにしてLCDをクリアします
    buzzer.off()
    LCD1602.clear()

コードの説明

  1. このスクリプトでは、さまざまなライブラリを機能に活用しています。 LCD1602 ライブラリはLCDディスプレイを管理し、 time は時間に関連する機能を提供します。 gpiozero ライブラリは、Raspberry PiのGPIOピン操作に必要であり、特にDistanceSensorとBuzzerの操作に使用されます。

    #!/usr/bin/env python3
    import LCD1602
    import time
    from gpiozero import DistanceSensor, Buzzer
    
  2. 超音波センサーは、エコーとトリガーピンがそれぞれGPIOピン24と23に接続されてセットアップされています。さらに、ブザーはGPIOピン17に接続されています。

    # GPIOピンで超音波センサーを初期化
    sensor = DistanceSensor(echo=24, trigger=23)  # エコーピンはGPIO 24、トリガーピンはGPIO 23です
    
    # GPIOピン17に接続されたブザーを初期化
    buzzer = Buzzer(17)
    
  3. LCDディスプレイの初期化では、クリアしてから起動メッセージを表示する手順が含まれています。

    def lcdsetup():
        # I2Cアドレスとバックライトを有効にしてLCDを初期化
        LCD1602.init(0x27, 1)  # 0x27はLCDのI2Cアドレスです
        LCD1602.clear()  # LCDディスプレイをクリア
        # LCD上に起動メッセージを表示
        LCD1602.write(0, 0, 'Ultrasonic Starting')
        LCD1602.write(1, 1, 'By SunFounder')
        time.sleep(2)  # 2秒待機
    
  4. distance 関数は超音波センサーによって測定された距離を計算し、センチメートル単位で値を返します。

    def distance():
        # センサーによって測定された距離を計算して返す
        dis = sensor.distance * 100  # 距離をセンチメートルに変換
        print('Distance: {:.2f} cm'.format(dis))  # 距離を小数点以下2桁で表示
        time.sleep(0.3)  # 次の測定前に0.3秒待機
        return dis
    
  5. メインループは距離を連続的に測定し、LCDとブザーの両方を更新します。測定された距離に基づいて異なる距離範囲を処理し、エラーメッセージを表示したり、測定された距離に基づいてブザーの周波数を変更したりします。

    def loop():
        # 距離を連続的に測定し、LCDとブザーを更新
        while True:
            dis = distance()  # 現在の距離を取得
            # 距離に基づいてアラートを表示し、処理
            if dis > 400:  # 距離が範囲外かどうかをチェック
                LCD1602.clear()
                LCD1602.write(0, 0, 'Error')
                LCD1602.write(3, 1, 'Out of range')
                time.sleep(0.5)
            else:
                # LCD上に現在の距離を表示
                LCD1602.clear()
                LCD1602.write(0, 0, 'Distance is')
                LCD1602.write(5, 1, str(round(dis, 2)) + ' cm')
                # 距離に基づいてブザーの周波数を調整
                if dis >= 50:
                    time.sleep(0.5)
                elif 20 < dis < 50:
                    # 中距離:中程度のブザーの周波数
                    for _ in range(2):
                        buzzer.on()
                        time.sleep(0.05)
                        buzzer.off()
                        time.sleep(0.2)
                elif dis <= 20:
                    # 近距離:高いブザーの周波数
                    for _ in range(5):
                        buzzer.on()
                        time.sleep(0.05)
                        buzzer.off()
                        time.sleep(0.05)
    
  6. 実行時、スクリプトはLCDをセットアップし、メインループに入ります。キーボードコマンド(Ctrl+C)で割り込みが発生すると、ブザーがオフになり、LCDがクリアされます。

    try:
        lcdsetup()  # LCDディスプレイのセットアップ
        loop()      # 測定ループの開始
    except KeyboardInterrupt:
        # ユーザー割り込み(Ctrl+Cなど)でブザーをオフにし、LCDをクリア
        buzzer.off()
        LCD1602.clear()
    
3.1.4 スマートファン
はじめに

このプロジェクトでは、モーター、ボタン、サーミスタを使用して、風速調節可能なマニュアル+自動スマートファンを作成します。

必要な部品

このプロジェクトで必要な部品は次のとおりです。

_images/4.1.10_smart_fan_list.png
回路図
_images/4.1.10_smart_fan_schematic.png
実験手順

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

_images/4.1.10_smart_fan_circuit.png

注釈

電源モジュールにはキット内の9Vバッテリーと9Vバッテリーバックルを使用できます。電源モジュールのジャンパーキャップを、ブレッドボードの5Vバスストリップに挿入します。

_images/4.1.10_smart_fan_battery.jpeg

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

cd ~/raphael-kit/python-pi5

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

sudo python3 3.1.4_SmartFan_zero.py

コードが実行されると、ボタンを押してファンを起動します。ボタンを押すたびに、風速が1段階上下に調節されます。風速は 0〜45つ の段階があります。4番目の風速に設定されており、ボタンを押すと風速 0 でファンが停止します。

温度が2℃以上上昇または下降すると、速度は自動的に1段階高くまたは低くなります。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、変更する前に raphael-kit/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3

from gpiozero import Motor, Button
from time import sleep
import ADC0834
import math

# ボタンとモーター制御のためのGPIOピンを初期化します
BtnPin = Button(22)
motor = Motor(forward=5, backward=6, enable=13)

# 温度センシング用にADC0834モジュールを初期化します
ADC0834.setup()

# モーター速度レベルと温度を追跡するための変数を初期化します
level = 0
currentTemp = 0
markTemp = 0

def temperature():
    """
    センサーから現在の温度を読み取り、計算します。
    戻り値:
        float: 摂氏での現在の温度。
    """
    # ADC0834モジュールからアナログ値を読み取ります
    analogVal = ADC0834.getResult()
    # アナログ値を電圧に変換し、抵抗に変換します
    Vr = 5 * float(analogVal) / 255
    Rt = 10000 * Vr / (5 - Vr)
    # 摂氏での温度を計算します
    temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
    Cel = temp - 273.15
    return Cel

def motor_run(level):
    """
    指定されたレベルに基づいてモーターの速度を調整します。
    引数:
        level (int): 望ましいモーター速度レベル。
    戻り値:
        int: 調整されたモーター速度レベル。
    """
    # レベルが0の場合、モーターを停止します
    if level == 0:
        motor.stop()
        return 0
    # 最大速度のためにレベルを4で制限します
    if level >= 4:
        level = 4
    # モーターの速度を設定します
    motor.forward(speed=float(level / 4))
    return level

def changeLevel():
    """
    ボタンが押されたときにモーターの速度レベルを手動で変更し、参照温度を更新します。
    """
    global level, currentTemp, markTemp
    print("ボタンが押されました")
    # レベルを0から4までサイクルさせます
    level = (level + 1) % 5
    # 参照温度を更新します
    markTemp = currentTemp

# ボタンの押下イベントをchangeLevel関数にバインドします
BtnPin.when_pressed = changeLevel

def main():
    """
    温度変化に連続的に監視し、応答するためのメイン関数。
    """
    global level, currentTemp, markTemp
    # 初期参照温度を設定します
    markTemp = temperature()
    while True:
        # 現在の温度を連続して読み取ります
        currentTemp = temperature()
        # 温度差に基づいてモーターのレベルを調整します
        if level != 0:
            if currentTemp - markTemp <= -2:
                level -= 1
                markTemp = currentTemp
            elif currentTemp - markTemp >= 2:
                if level < 4:
                    level += 1
                markTemp = currentTemp
        # 調整されたレベルでモーターを実行します
        level = motor_run(level)

# メイン関数を実行し、キーボード割り込みを処理します
try:
    main()
except KeyboardInterrupt:
    # スクリプトが中断された場合、モーターを停止します
    motor.stop()
コードの説明
  1. モーターやボタンの管理用クラス、一時停止を導入するための sleep 関数、温度センシングのための ADC0834 ライブラリ、数学的な計算のための math ライブラリをインポートします。

    #!/usr/bin/env python3
    
    from gpiozero import Motor, Button
    from time import sleep
    import ADC0834
    import math
    
  2. ボタンを GPIO ピン 22 に設定し、モーターの制御に特定の GPIO ピンを設定します。温度測定用に ADC0834 モジュールを初期化します。また、モーター速度レベルと温度を監視するための変数を初期化します。

    # ボタンとモーター制御のための GPIO ピンを初期化
    BtnPin = Button(22)
    motor = Motor(forward=5, backward=6, enable=13)
    
    # 温度センシングのために ADC0834 モジュールを初期化
    ADC0834.setup()
    
    # モーター速度レベルと温度を追跡するための変数を初期化
    level = 0
    currentTemp = 0
    markTemp = 0
    
  3. センサーから温度を読み取り、摂氏に変換するための関数を定義します。

    def temperature():
        """
        センサーから現在の温度を読み取り、計算します。
        戻り値:
            float: 摂氏での現在の温度。
        """
        # ADC0834 モジュールからアナログ値を取得
        analogVal = ADC0834.getResult()
        # アナログ値を電圧に変換し、抵抗に変換
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        # 摂氏での温度を計算
        temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
        Cel = temp - 273.15
        return Cel
    
  4. 指定したレベルに基づいてモーターの速度を調整する関数を実装します。

    def motor_run(level):
        """
        指定されたレベルに基づいてモーターの速度を調整します。
        引数:
            level (int): 望ましいモーター速度レベル。
        戻り値:
            int: 調整されたモーター速度レベル。
        """
        # レベルが0の場合、モーターを停止
        if level == 0:
            motor.stop()
            return 0
        # レベルを最大4に制限
        if level >= 4:
            level = 4
        # モーター速度を設定
        motor.forward(speed=float(level / 4))
        return level
    
  5. ボタンを使用してモーターの速度レベルを手動で変更し、この関数をボタンのプレスイベントにバインドします。

    def changeLevel():
        """
        ボタンが押されたときにモーターの速度レベルを手動で変更し、参照温度を更新します。
        """
        global level, currentTemp, markTemp
        print("ボタンが押されました")
        # レベルを0から4までサイクル
        level = (level + 1) % 5
        # 参照温度を更新
        markTemp = currentTemp
    
    # ボタンのプレスイベントを changeLevel 関数にバインド
    BtnPin.when_pressed = changeLevel
    
  6. 温度変化に応じてモーターの速度を連続的に調整するメイン関数を実装することが残っています。

    def main():
        """
        温度変化に連続的に監視し、応答するためのメイン関数。
        """
        global level, currentTemp, markTemp
        # 初期参照温度を設定
        markTemp = temperature()
        while True:
            # 現在の温度を連続して読み取ります
            currentTemp = temperature()
            # レベルが0でない場合、温度差に基づいてモーターレベルを調整します
            if level != 0:
                if currentTemp - markTemp <= -2:
                    level -= 1
                    markTemp = currentTemp
                elif currentTemp - markTemp >= 2:
                    if level < 4:
                        level += 1
                    markTemp = currentTemp
            # 調整されたレベルでモーターを実行します
            level = motor_run(level)
    
    # メイン関数を実行し、キーボード割り込みを処理します
    try:
        main()
    except KeyboardInterrupt:
        # スクリプトが中断された場合、モーターを停止します
        motor.stop()
    
3.1.5 バッテリーインジケータ
はじめに

このプロジェクトでは、LED バーグラフ上にバッテリーの電力レベルを視覚的に表示できるバッテリーインジケータデバイスを作成します。

必要なコンポーネント

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

_images/4.1.11_battery_indicator_list.png
回路図
_images/4.1.11_battery_indicator_schematic.png
実験手順

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

_images/4.1.11_battery_indicator_circuit.png

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

cd ~/raphael-kit/python-pi5

ステップ 3: 実行可能ファイルを実行します。

sudo python3 3.1.5_BatteryIndicator_zero.py

プログラムが実行されたら、ADC0834の3番ピンとGNDにそれぞれリードアウトワイヤーを接続し、それらを別々のバッテリーの2極にリードアウトしてください。対応するLEDバーグラフのLEDが点灯し、電力レベルが表示されます(測定範囲:0-5V)。

コード

注釈

以下のコードは、 変更/リセット/コピー/実行/停止 ができます。ただし、それに先立ち、 raphael-kit/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3
from gpiozero import LED
import ADC0834
import time

# LEDが接続されたGPIOピンのリスト
ledPins = [25, 12, 16, 20, 21, 5, 6, 13, 19, 26]
# リスト内の各ピンに対してLEDオブジェクトを初期化
leds = [LED(pin) for pin in ledPins]

# ADC0834モジュールのセットアップ
ADC0834.setup()

def LedBarGraph(value):
    # すべてのLEDをオフにする
    for i in range(10):
        leds[i].off()
    # 指定された値までLEDを点灯させる
    for i in range(value):
        leds[i].on()

try:
    # LEDバーグラフを連続的に更新するためのメインループ
    while True:
        # ADC0834からアナログ値を読み取る
        analogVal = ADC0834.getResult()
        # アナログ値をLEDバーグラフのレベルに変換
        LedBarGraph(int(analogVal/25))
except KeyboardInterrupt:
    # プログラムが中断されたときにすべてのLEDをオフにする
    for i in range(10):
        leds[i].off()

コードの説明

  1. このセクションは必要なライブラリをインポートしています。 gpiozero はLEDを制御するため、 ADC0834 はADCモジュールとのインターフェース、 time は時間に関連する操作に使用されます。

    #!/usr/bin/env python3
    from gpiozero import LED
    import ADC0834
    import time
    
  2. LEDが接続されたGPIOピンを定義し、各ピンに対してLEDオブジェクトの配列を初期化します。これにより、配列内の各LEDを簡単に制御できます。

    # LEDが接続されたGPIOピンのリスト
    ledPins = [25, 12, 16, 20, 21, 5, 6, 13, 19, 26]
    # リスト内の各ピンに対してLEDオブジェクトを初期化
    leds = [LED(pin) for pin in ledPins]
    
  3. アナログからデジタルへの変換のためにADC0834モジュールを初期化します。

    # ADC0834モジュールのセットアップ
    ADC0834.setup()
    
  4. この関数はすべてのLEDをオフにし、指定された値に基づいてLEDをオンにして、バーグラフの表現を作成します。

    def LedBarGraph(value):
        # すべてのLEDをオフにする
        for i in range(10):
            leds[i].off()
        # 指定された値までLEDを点灯させる
        for i in range(value):
            leds[i].on()
    
  5. ADC0834からアナログ値を連続的に読み取り、この値に基づいてLEDバーグラフを更新します。アナログ値は0から10の範囲にスケールダウンされます。

    try:
        # LEDバーグラフを連続的に更新するためのメインループ
        while True:
            # ADC0834からアナログ値を読み取る
            analogVal = ADC0834.getResult()
            # アナログ値をLEDバーグラフのレベルに変換
            LedBarGraph(int(analogVal/25))
    
  6. プログラムが中断された場合(たとえば、Ctrl+Cを押した場合)、すべてのLEDがオフになるようにします。

    except KeyboardInterrupt:
        # プログラムが中断されたときにすべてのLEDをオフにする
        for i in range(10):
            leds[i].off()
    
3.1.6 モーションコントロール
はじめに

このレッスンでは、シンプルなモーションセンシングおよびコントロールデバイスを作成します。センサーとしてMPU6050を使用し、制御デバイスとしてステッパーモータを使用します。MPU6050を手袋に取り付けることで、手首を回転させることでステッパーモータを制御できます。

必要なコンポーネント

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

_images/3.1.6_motion_list.png
回路図
_images/3.1.6_motion_schematic.png
実験手順

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

_images/3.1.6_motion_control_circuit.png

ステップ 2: コードファイルを開きます。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

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

sudo python3 3.1.6_MotionControl_zero.py

コードが実行されると、 mpu6050Y軸 の傾斜角が 45 ℃ より大きい場合、ステッパーモータは反時計回りに回転し、 -45 ℃ より小さい場合、ステッパーモータは時計回りに回転します。

コード

注釈

以下のコードは、 変更/リセット/コピー/実行/停止 ができます。ただし、それに先立ち、 davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

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

# MPU6050の電源管理レジスタを初期化
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

# MPU6050とのI2C通信の設定
bus = smbus.SMBus(1)  # SMBusの初期化
address = 0x68        # MPU6050のI2Cアドレス
bus.write_byte_data(address, power_mgmt_1, 0)  # MPU6050を起動

# ステッパーモータのピンをGPIOピン18, 23, 24, 25に初期化
motorPin = [OutputDevice(pin) for pin in (18, 23, 24, 25)]

# モーターの回転速度パラメータを設定
rolePerMinute = 15
stepsPerRevolution = 2048
# 希望のRPMを達成するためのステップ間の遅延を計算
stepSpeed = (60 / rolePerMinute) / stepsPerRevolution

# 指定されたI2Cアドレスから1バイトを読み取る
def read_byte(adr):
    return bus.read_byte_data(address, adr)

# 指定されたI2Cアドレスからワード(2バイト)を読み取る
def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr + 1)
    val = (high << 8) + low
    return val

# 2の補数形式でワードを読み取る
def read_word_2c(adr):
    val = read_word(adr)
    if val >= 0x8000:
        return -((65535 - val) + 1)
    else:
        return val

# 2点間のユークリッド距離を計算
def dist(a, b):
    return math.sqrt((a * a) + (b * b))

# Y軸回転を計算
def get_y_rotation(x, y, z):
    radians = math.atan2(x, dist(y, z))
    return -math.degrees(radians)

# X軸回転を計算
def get_x_rotation(x, y, z):
    radians = math.atan2(y, dist(x, z))
    return math.degrees(radians)

# MPU6050からの傾斜角を取得
def mpu6050():
    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)
    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0
    angle = get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)
    return angle

# ステッパーモータの回転を制御
def rotary(direction):
    if direction == 'c':
        # 時計回りの回転シーケンス
        for j in range(4):
            for i in range(4):
                if 0x99 >> j & (0x08 >> i):
                    motorPin[i].on()
                else:
                    motorPin[i].off()
                time.sleep(stepSpeed)
    elif direction == 'a':
        # 反時計回りの回転シーケンス
        for j in range(4):
            for i in range(4):
                if 0x99 << j & (0x08 >> i):
                    motorPin[i].on()
                else:
                    motorPin[i].off()
                time.sleep(stepSpeed)

# 傾斜角を連続的に読み取り、モーターを制御するためのメインループ
try:
    while True:
        angle = mpu6050()
        if angle >= 45:
            rotary('a')  # 正の傾斜の場合、反時計回りに回転
        elif angle <= -45:
            rotary('c')  # 負の傾斜の場合、時計回りに回転
except KeyboardInterrupt:
    # キーボード割り込み時にすべてのモーターピンをオフにする
    for pin in motorPin:
        pin.off()

コードの説明

  1. スクリプトは、必要なライブラリをインポートすることから始まります。GPIOピンを制御するための「gpiozero」、I2C通信用の「smbus」、数学的な操作に「math」、遅延を制御するための「time」をインポートします。

    #!/usr/bin/env python3
    from gpiozero import OutputDevice
    import smbus
    import math
    import time
    
  2. MPU6050センサーとのI2C通信をセットアップします。「power_mgmt_1」と「power_mgmt_2」はセンサーの電源を管理するためのレジスタです。「power_mgmt_1」に書き込むことで、センサーは「起動」状態になります。

    # MPU6050の電源管理レジスタを初期化
    power_mgmt_1 = 0x6b
    power_mgmt_2 = 0x6c
    
    # MPU6050とのI2C通信のセットアップ
    bus = smbus.SMBus(1)  # SMBusの初期化
    address = 0x68        # MPU6050のI2Cアドレス
    bus.write_byte_data(address, power_mgmt_1, 0)  # MPU6050を起動
    
  3. Raspberry Pi上のGPIOピンを初期化して、ステッパーモータを制御します。各ピンはモーターのコイルに関連付けられています。

    # ステッパーモータのピンをGPIOピン18, 23, 24, 25に初期化
    motorPin = [OutputDevice(pin) for pin in (18, 23, 24, 25)]
    
  4. モーターの回転数(RPM)と1回転あたりのステップ数を設定します。「stepSpeed」は、希望のRPMを達成するためのステップ間の遅延を計算し、スムーズなモーターの動作を確保します。

    # モーターの回転速度パラメータを設定
    rolePerMinute = 15
    stepsPerRevolution = 2048
    # 希望のRPMを達成するためのステップ間の遅延を計算
    stepSpeed = (60 / rolePerMinute) / stepsPerRevolution
    
  5. これらの関数はI2C通信に使用されます。「read_byte」は指定されたアドレスから1バイトを読み取り、「read_word」は2バイト(ワード)を読み取り、ビット演算( << および + )を使用してそれらを単一の値に結合します。

    # 指定されたI2Cアドレスから1バイトを読み取る
    def read_byte(adr):
        return bus.read_byte_data(address, adr)
    
    # 指定されたI2Cアドレスからワード(2バイト)を読み取る
    def read_word(adr):
        high = bus.read_byte_data(address, adr)
        low = bus.read_byte_data(address, adr + 1)
        val = (high << 8) + low
        return val
    
  6. この関数は、読み取ったワードを2の補数形式に変換し、センサーデータから符号付きの値を解釈するために使用されます。この変換は、負のセンサー値を処理するために必要です。

    # 2の補数形式でワードを読み取る
    def read_word_2c(adr):
        val = read_word(adr)
        if val >= 0x8000:
            return -((65535 - val) + 1)
        else:
            return val
    
  7. 「dist」は2つのポイント間のユークリッド距離を計算し、回転計算に使用されます。「get_y_rotation」と「get_x_rotation」は「math」ライブラリの「atan2」関数を使用してY軸とX軸の回転角度を計算し、結果を度に変換します。

    # 2点間のユークリッド距離を計算
    def dist(a, b):
        return math.sqrt((a * a) + (b * b))
    
    # Y軸回転を計算
    def get_y_rotation(x, y, z):
        radians = math.atan2(x, dist(y, z))
        return -math.degrees(radians)
    
    # X軸回転を計算
    def get_x_rotation(x, y, z):
        radians = math.atan2(y, dist(x, z))
        return math.degrees(radians)
    
  8. この関数はMPU6050センサーから加速度計データを読み取り、読み取り値をスケーリングし、 get_y_rotation 関数を使用して傾斜角を計算します。「read_word_2c」関数は2の補数形式でセンサーデータを読み取り、負の値を処理するために必要です。

    # MPU6050からの傾斜角を取得
    def mpu6050():
        accel_xout = read_word_2c(0x3b)
        accel_yout = read_word_2c(0x3d)
        accel_zout = read_word_2c(0x3f)
        accel_xout_scaled = accel_xout / 16384.0
        accel_yout_scaled = accel_yout / 16384.0
        accel_zout_scaled = accel_zout / 16384.0
        angle = get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)
        return angle
    
  9. 「rotary」関数はステッパーモーターの回転を制御します。指定された「direction」に基づいて時計回りまたは反時計回りの回転を実行し、特定のモーターピンをパターンに従ってオンまたはオフにします。

    # ステッパーモーターの回転を制御
    def rotary(direction):
        if direction == 'c':
            # 時計回りの回転シーケンス
            for j in range(4):
                for i in range(4):
                    if 0x99 >> j & (0x08 >> i):
                        motorPin[i].on()
                    else:
                        motorPin[i].off()
                    time.sleep(stepSpeed)
        elif direction == 'a':
            # 反時計回りの回転シーケンス
            for j in range(4):
                for i in range(4):
                    if 0x99 << j & (0x08 >> i):
                        motorPin[i].on()
                    else:
                        motorPin[i].off()
                    time.sleep(stepSpeed)
    
  10. メインループはMPU6050センサーから傾斜角を連続して読み取り、角度に基づいてモーターの回転方向を制御します。プログラムが中断された場合(キーボード割り込みなど)、安全のためにすべてのモーターピンをオフにします。

    # 傾斜角を連続的に読み取り、モーターを制御するためのメインループ
    try:
        while True:
            angle = mpu6050()
            if angle >= 45:
                rotary('a')  # 正の傾斜の場合、反時計回りに回転
            elif angle <= -45:
                rotary('c')  # 負の傾斜の場合、時計回りに回転
    except KeyboardInterrupt:
        # キーボード割り込み時にすべてのモーターピンをオフにする
        for pin in motorPin:
            pin.off()
    
3.1.7 交通信号灯
概要

このプロジェクトでは、3つの色のLEDライトを使用して交通信号の変更を実現し、 4桁の7セグメントディスプレイを使用して各交通状態のタイミングを表示します。

必要な部品

このプロジェクトでは、以下の部品が必要です。

_images/4.1.12_traffic_light_list.png
配線図

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

GPIO25

Pin 22

6

25

SPICE0

Pin 24

10

8

SPICE1

Pin 26

11

7

_images/4.1.12_traffic_light_schematic.png
実験手順

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

_images/4.1.12_traffic_light_circuit.png

ステップ 2: ディレクトリを変更します。

cd ~/raphael-kit/python-pi5

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

sudo python3 3.1.7_TrafficLight_zero.py

コードを実行すると、LEDが交通信号の色変更をシミュレートします。最初に赤いLEDが60秒点灯し、次に緑のLEDが30秒点灯します。その後、黄色のLEDが5秒点灯します。その後、再び赤いLEDが60秒点灯します。このように、この一連のアクションが繰り返し実行されます。同時に、4桁の7セグメントディスプレイにはカウントダウン時間が連続して表示されます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、それを行う前に、ソースコードのパス( raphael-kit/python-pi5 のような)に移動する必要があります。コードを変更した後、それを直接実行して効果を確認できます。

#!/usr/bin/env python3

from gpiozero import OutputDevice, LED
import threading

# 74HC595シフトレジスタ用のGPIOピンのセットアップ
SDI = OutputDevice(24)   # シリアルデータ入力
RCLK = OutputDevice(23)  # レジスタクロック
SRCLK = OutputDevice(18) # シフトレジスタクロック

# 7セグメントディスプレイのデジット選択用のGPIOピンのセットアップ
placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]

# 7セグメントディスプレイに表示する0〜9の数字のセグメントコード
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# 交通信号のLED用のGPIOピンのセットアップ
ledPinR = LED(25) # 赤いLED
ledPinG = LED(8)  # 緑のLED
ledPinY = LED(7)  # 黄色のLED

# 交通信号の持続時間設定
greenLight = 30
yellowLight = 5
redLight = 60

# 交通信号の色の名前
lightColor = ("赤", "緑", "黄色")

# ステート変数の初期化
colorState = 0
counter = 60
timer1 = None

def setup():
    """ 交通信号システムを初期化し、タイマーを開始します。 """
    global timer1
    timer1 = threading.Timer(1.0, timer)
    timer1.start()

def clearDisplay():
    """ 7セグメントディスプレイをクリアします。 """
    for _ in range(8):
        SDI.on()
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def hc595_shift(data):
    """ データを74HC595シフトレジスタにシフトしてディスプレイします。 """
    for i in range(8):
        SDI.value = 0x80 & (data << i)
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def pickDigit(digit):
    """ 7セグメントディスプレイ上に表示する特定のディジットを選択します。 """
    for pin in placePin:
        pin.off()
    placePin[digit].on()

def timer():
    """ 交通信号の変更のタイミングを処理します。 """
    global counter, colorState, timer1
    timer1 = threading.Timer(1.0, timer)
    timer1.start()
    counter -= 1
    if counter == 0:
        counter = [greenLight, yellowLight, redLight][colorState]
        colorState = (colorState + 1) % 3
    print(f"カウンタ : {counter}    色: {lightColor[colorState]}")

def lightup():
    """ 現在の状態に基づいて交通信号LEDを更新します。 """
    global colorState
    ledPinR.off()
    ledPinG.off()
    ledPinY.off()
    [ledPinR, ledPinG, ledPinY][colorState].on()

def display():
    """ 7セグメントディスプレイ上に現在のカウンタ値を表示します。 """
    global counter

    for i in range(4):
        digit = counter // (10 ** (3 - i)) % 10
        if i == 0 and digit == 0:
            continue
        clearDisplay()
        pickDigit(3 - i)
        hc595_shift(number[digit])

def loop():
    """ ディスプレイとライトを連続的に更新するメインループ。 """
    while True:
        display()
        lightup()

def destroy():
    """ スクリプトが終了した際にリソースをクリーンアップします。 """
    global timer1
    timer1.cancel()
    ledPinR.off()
    ledPinG.off()
    ledPinY.off()

try:
    setup()
    loop()
except KeyboardInterrupt:
    destroy()
コードの説明
  1. gpiozeroライブラリから OutputDevice および LED クラスをインポートし、一般的な出力デバイスと特にLEDを制御するための機能を有効にします。Pythonのスレッディングモジュールもインポートされており、スレッドを作成して処理するために使用されます。

    #!/usr/bin/env python3
    from gpiozero import OutputDevice, LED
    import threading
    
  2. シフトレジスタのシリアルデータ入力(SDI)、レジスタクロック入力(RCLK)、およびシフトレジスタクロック入力(SRCLK)に接続されたGPIOピンを初期化します。

    # 74HC595シフトレジスタ用のGPIOピンのセットアップ
    SDI = OutputDevice(24)   # シリアルデータ入力
    RCLK = OutputDevice(23)  # レジスタクロック
    SRCLK = OutputDevice(18) # シフトレジスタクロック
    
  3. 7セグメントディスプレイの各ディジット用のピンを初期化し、0から9までの数値を表示するためのバイナリコードを定義します。

    # 7セグメントディスプレイのディジット選択用のGPIOピンのセットアップ
    placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]
    
    # 7セグメントディスプレイに0から9までの数字を表示するためのセグメントコード
    number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
    
  4. 交通信号のシミュレーションに使用する赤、緑、黄色のLEDのGPIOピンを初期化します。交通信号システムの各色の状態の継続時間(秒単位)を設定します。参照のために、交通信号の色の名前も定義します。

    # 交通信号LEDのGPIOピンのセットアップ
    ledPinR = LED(25) # 赤色のLED
    ledPinG = LED(8)  # 緑色のLED
    ledPinY = LED(7)  # 黄色のLED
    
    # 交通信号の各色の継続時間設定
    greenLight = 30  # 緑色
    yellowLight = 5  # 黄色
    redLight = 60    # 赤色
    
    # 交通信号の色の名前
    lightColor = ("赤", "緑", "黄色")
    
  5. 現在の色の状態、タイミングのためのカウンタ、およびタイマーオブジェクトのプレースホルダを初期化します。

    # 状態変数の初期化
    colorState = 0
    counter = 60
    timer1 = None
    
  6. 交通信号システムを初期化し、タイマースレッドを開始します。

    def setup():
        """ 交通信号システムを初期化し、タイマーを開始します。 """
        global timer1
        timer1 = threading.Timer(1.0, timer)
        timer1.start()
    
  7. 7セグメントディスプレイの制御用の関数です。 clearDisplay はすべてのセグメントをオフにし、 hc595_shift はデータをシフトレジスタにシフトし、 pickDigit はディスプレイ上の特定のディジットをアクティブにします。

    def clearDisplay():
        """ 7セグメントディスプレイをクリアします。 """
        for _ in range(8):
            SDI.on()
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
    def hc595_shift(data):
        """ データを74HC595シフトレジスタにシフトしてディスプレイします。 """
        for i in range(8):
            SDI.value = 0x80 & (data << i)
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
    def pickDigit(digit):
        """ 7セグメントディスプレイ上に表示する特定のディジットを選択します。 """
        for pin in placePin:
            pin.off()
        placePin[digit].on()
    
  8. 交通信号の変更のタイミングを管理し、カウンターと色の状態を更新します。

    def timer():
        """ 交通信号の変更のタイミングを処理します。 """
        global counter, colorState, timer1
        timer1 = threading.Timer(1.0, timer)
        timer1.start()
        counter -= 1
        if counter == 0:
            counter = [greenLight, yellowLight, redLight][colorState]
            colorState = (colorState + 1) % 3
        print(f"カウンター : {counter}    色: {lightColor[colorState]}")
    
  9. 現在の色の状態に基づいて交通信号のLEDの状態を更新します。

    def lightup():
        """ 現在の状態に基づいて交通信号のLEDを更新します。 """
        global colorState
        ledPinR.off()
        ledPinG.off()
        ledPinY.off()
        [ledPinR, ledPinG, ledPinY][colorState].on()
    
  10. 7セグメントディスプレイの各セグメントに表示されるディジットを計算し、それに応じて更新します。

def display():
    """ 7セグメントディスプレイ上に現在のカウンター値を表示します。 """
    global counter

    for i in range(4):
        digit = counter // (10 ** (3 - i)) % 10
        if i == 0 and digit == 0:
            continue
        clearDisplay()
        pickDigit(3 - i)
        hc595_shift(number[digit])
  1. ディスプレイと交通信号のLEDを連続的に更新するメインループです。

def loop():
    """ ディスプレイとライトを連続的に更新するメインループです。 """
    while True:
        display()
        lightup()
  1. スクリプトが終了したときにLEDをオフにし、タイマースレッドを停止するなど、リソースをクリーンアップします。

def destroy():
    """ スクリプトが終了したときにリソースをクリーンアップします。 """
    global timer1
    timer1.cancel()
    ledPinR.off()
    ledPinG.off()
    ledPinY.off()
3.1.8 過熱モニター
概要

あなたは過熱監視デバイスを作成したいかもしれません。例えば、工場内で回路の過熱がある場合にアラームと機械の自動シャットダウンをしたい場合です。このプロジェクトでは、サーミスタ、ジョイスティック、ブザー、LED、およびLCDを使用して、しきい値が調整可能なスマートな温度監視デバイスを作成します。

必要なコンポーネント

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

_images/4.1.13_overheat_monitor_list.png
回路図
_images/4.1.13_overheat_monitor_schematic.png
実験手順

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

_images/4.1.13_overheat_monitor_circuit.png

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

cd ~/raphael-kit/python-pi5

ステップ 3: 実行可能ファイルを実行します。

sudo python3 3.1.8_OverheatMonitor_zero.py

コードが実行されると、現在の温度と高温閾値 40I2C LCD1602 に表示されます。現在の温度が閾値を超える場合、ブザーとLEDがアラームを鳴らします。

ここでの ジョイスティック は、高温閾値を調整するためのボタンです。 ジョイスティック をX軸およびY軸の方向に切り替えると(上下に動かすと)現在の高温閾値を調整できます。 ジョイスティック をもう一度押すと、閾値が初期値にリセットされます。

注釈

  • エラーが発生した場合、 FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1' 、I2Cを有効にするために I2C構成 を参照してください。

  • ModuleNotFoundError: No module named 'smbus2' エラーが発生した場合は、 sudo pip3 install smbus2 を実行してください。

  • エラー OSError: [Errno 121] Remote I/O error が表示された場合、モジュールが誤って配線されているか、モジュールが壊れていることを意味します。

  • コードと配線が正常であるにもかかわらず、LCDにコンテンツが表示されない場合、裏側のポテンショメーターを回してコントラストを調整できます。

コード

注釈

以下のコードを 修正/リセット/コピー/実行/停止 できます。ただし、それより前に、 raphael-kit/python のようなソースコードのパスに移動する必要があります。コードを修正した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3

import LCD1602
from gpiozero import LED, Buzzer, Button
import ADC0834
import time
import math

# ジョイスティックボタン、ブザー、LEDの初期化
Joy_BtnPin = Button(22)
buzzPin = Buzzer(23)
ledPin = LED(24)

# 初期の高温閾値を設定
upperTem = 40

# ADCとLCDモジュールのセットアップ
ADC0834.setup()
LCD1602.init(0x27, 1)

def get_joystick_value():
    """
    ジョイスティックの値を読み取り、ジョイスティックの位置に基づいて変更値を返します。
    """
    x_val = ADC0834.getResult(1)
    y_val = ADC0834.getResult(2)
    if x_val > 200:
        return 1
    elif x_val < 50:
        return -1
    elif y_val > 200:
        return -10
    elif y_val < 50:
        return 10
    else:
        return 0

def upper_tem_setting():
    """
    ジョイスティックの入力を使用して高温閾値を調整し、LCDに表示します。
    """
    global upperTem
    LCD1602.write(0, 0, '上限調整: ')
    change = int(get_joystick_value())
    upperTem += change
    strUpperTem = str(upperTem)
    LCD1602.write(0, 1, strUpperTem)
    LCD1602.write(len(strUpperTem), 1, '              ')
    time.sleep(0.1)

def temperature():
    """
    センサーから現在の温度を読み取り、摂氏で返します。
    """
    analogVal = ADC0834.getResult()
    Vr = 5 * float(analogVal) / 255
    Rt = 10000 * Vr / (5 - Vr)
    temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
    Cel = temp - 273.15
    return round(Cel, 2)

def monitoring_temp():
    """
    現在の温度と上限温度閾値を監視および表示します。温度が上限を超える場合、ブザーとLEDが作動します。
    """
    global upperTem
    Cel = temperature()
    LCD1602.write(0, 0, '温度: ')
    LCD1602.write(0, 1, '上限: ')
    LCD1602.write(6, 0, str(Cel))
    LCD1602.write(7, 1, str(upperTem))
    time.sleep(0.1)
    if Cel >= upperTem:
        buzzPin.on()
        ledPin.on()
    else:
        buzzPin.off()
        ledPin.off()

# メイン実行ループ
try:
    lastState = 1
    stage = 0
    while True:
        currentState = Joy_BtnPin.value
        # 設定モードと監視モードを切り替えます
        if currentState == 1 and lastState == 0:
            stage = (stage + 1) % 2
            time.sleep(0.1)
            LCD1602.clear()
        lastState = currentState
        if stage == 1:
            upper_tem_setting()
        else:
            monitoring_temp()
except KeyboardInterrupt:
    # クリーンアップして終了
    LCD1602.clear()
    ADC0834.destroy()

代码解释

  1. このセクションでは、プロジェクトに必要なライブラリをインポートします。 LCD1602 はLCDディスプレイ用、 gpiozero はLED、ブザー、およびボタン用のクラスを提供します。 ADC0834 はアナログデジタル変換用で、 time および math は時間関連の関数と数学操作のためのPython標準ライブラリです。

    #!/usr/bin/env python3
    
    import LCD1602
    from gpiozero import LED, Buzzer, Button
    import ADC0834
    import time
    import math
    
  2. ここで、ジョイスティックのボタン、ブザー、LEDを初期化します。 Button(22) はGPIOピン22に接続されたボタンオブジェクトを作成します。 Buzzer(23)LED(24) はそれぞれGPIOピン23と24にブザーとLEDを初期化します。

    # ジョイスティックボタン、ブザー、LEDの初期化
    Joy_BtnPin = Button(22)
    buzzPin = Buzzer(23)
    ledPin = LED(24)
    
  3. 初期の上限温度を設定し、ADCとLCDモジュールを初期化します。LCDはアドレス( 0x27 )とモード( 1 )で初期化されます。

    # 初期の上限温度閾値を設定
    upperTem = 40
    
    # ADCとLCDモジュールのセットアップ
    ADC0834.setup()
    LCD1602.init(0x27, 1)
    
  4. この関数はジョイスティックのXとYの値をADC0834を使用して読み取り、ジョイスティックの位置に基づいて変更値を返します。この変更値は温度の閾値を調整するために使用されます。

    def get_joystick_value():
        """
        ジョイスティックの値を読み取り、ジョイスティックの位置に基づいて変更値を返します。
        """
        x_val = ADC0834.getResult(1)
        y_val = ADC0834.getResult(2)
        if x_val > 200:
            return 1
        elif x_val < 50:
            return -1
        elif y_val > 200:
            return -10
        elif y_val < 50:
            return 10
        else:
            return 0
    
  5. ジョイスティックの入力を使用して上限温度を調整し、新しい閾値をLCDに表示します。

    def upper_tem_setting():
        """
        ジョイスティックの入力を使用して上限温度閾値を調整し、LCDに表示します。
        """
        global upperTem
        LCD1602.write(0, 0, '上限調整: ')
        change = int(get_joystick_value())
        upperTem += change
        strUpperTem = str(upperTem)
        LCD1602.write(0, 1, strUpperTem)
        LCD1602.write(len(strUpperTem), 1, '              ')
        time.sleep(0.1)
    
  6. センサーから現在の温度を読み取り、摂氏に変換します。

    def temperature():
        """
        センサーから現在の温度を読み取り、摂氏で返します。
        """
        analogVal = ADC0834.getResult()
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
        Cel = temp - 273.15
        return round(Cel, 2)
    
  7. 現在の温度と上限温度閾値を監視し、LCDに表示します。温度が上限を超える場合、ブザーとLEDが作動します。

    def monitoring_temp():
        """
        現在の温度と上限温度閾値を監視し、LCDに表示します。温度が上限を超える場合、ブザーとLEDが作動します。
        """
        global upperTem
        Cel = temperature()
        LCD1602.write(0, 0, '温度: ')
        LCD1602.write(0, 1, '上限: ')
        LCD1602.write(6, 0, str(Cel))
        LCD1602.write(7, 1, str(upperTem))
        time.sleep(0.1)
        if Cel >= upperTem:
            buzzPin.on()
            ledPin.on()
        else:
            buzzPin.off()
            ledPin.off()
    
  8. メイン実行ループはジョイスティックボタンの押下に基づいて設定モードと監視モードを切り替えます。設定または温度の監視を継続的に更新します。

    # メイン実行ループ
    try:
        lastState = 1
        stage = 0
        while True:
            currentState = Joy_BtnPin.value
            # 設定モードと監視モードを切り替える
            if currentState == 1 and lastState == 0:
                stage = (stage + 1) % 2
                time.sleep(0.1)
                LCD1602.clear()
            lastState = currentState
            if stage == 1:
                upper_tem_setting()
            else:
                monitoring_temp()
    except KeyboardInterrupt:
        # クリーンアップして終了
        LCD1602.clear()
        ADC0834.destroy()
    
3.1.9 パスワードロック
はじめに

このプロジェクトでは、キーパッドとLCDを使用して組み合わせ錠を作成します。LCDには、キーパッドにパスワードを入力するための対応するプロンプトが表示されます。パスワードが正しく入力されると、「正しい」と表示されます。

このプロジェクトを基に、ブザーやLEDなどの追加の電子コンポーネントを追加して、パスワードの入力に異なる実験現象を追加することができます。

必要な部品

このプロジェクトでは、次の部品が必要です。

_images/4.1.14_password_lock_list.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

GPIO17

Pin 11

0

17

GPIO27

Pin 13

2

27

GPIO22

Pin 15

3

22

SPIMOSI

Pin 19

12

10

SDA1

Pin 3

SCL1

Pin 5

_images/4.1.14_password_lock_schematic.png
実験手順

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

_images/4.1.14_password_lock_circuit.png

ステップ2: ディレクトリを変更します。

cd ~/raphael-kit/python-pi5

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

sudo python3 3.1.9_PasswordLock_zero.py

コードが実行されると、キーパッドを使用してパスワード(1984)を入力します。LCD1602に「CORRECT」が表示された場合、パスワードは正しいです。それ以外の場合、「WRONG KEY」が表示されます。

注釈

  • 「FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'」というエラーが表示される場合は、I2Cを有効にするために I2C構成 を参照してください。

  • 「ModuleNotFoundError: No module named 'smbus2'」エラーが表示される場合は、「sudo pip3 install smbus2」を実行してください。

  • エラー「OSError: [Errno 121] Remote I/O error」が表示される場合、モジュールが配線されていないか、モジュールが壊れていることを意味します。

  • コードと配線が正常であるが、LCDに内容が表示されない場合、背面のポテンショメータを回してコントラストを上げることができます。

コード

注釈

以下のコードを 変更/リセット/コピー/実行/停止 することができます。ただし、それを行う前に raphael-kit/python-pi5 のようなソースコードパスに移動する必要があります。コードを変更した後、それを直接実行して効果を確認できます。

#!/usr/bin/env python3

from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602

class Keypad:
    def __init__(self, rows_pins, cols_pins, keys):
        """
        指定された行と列のピンおよびキーでキーパッドを初期化します。
        :param rows_pins: 行のGPIOピンのリスト。
        :param cols_pins: 列のGPIOピンのリスト。
        :param keys: キーパッドのレイアウト内のキーのリスト。
        """
        self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]  # 行ピンの設定
        self.cols = [Button(pin, pull_up=False) for pin in cols_pins]  # 列ピンの設定
        self.keys = keys  # キーパッドのキーレイアウト

    def read(self):
        """
        現在押されているキーのリストを読み取り、返します。
        :return: 押されているキーのリスト。
        """
        pressed_keys = []
        for i, row in enumerate(self.rows):
            row.on()  # 現在の行をアクティブにする
            for j, col in enumerate(self.cols):
                if col.is_pressed:
                    index = i * len(self.cols) + j
                    pressed_keys.append(self.keys[index])
            row.off()  # チェック後に行を非アクティブにする
        return pressed_keys

# パスワードの検証設定
LENS = 4
password = ['1', '9', '8', '4']  # プリセットのパスワード
testword = ['0', '0', '0', '0']  # ユーザーの入力を格納
keyIndex = 0  # 入力キーのインデックス

def check():
    """
    入力されたパスワードがプリセットのパスワードと一致するか確認します。
    :return: 一致する場合は1、それ以外の場合は0。
    """
    for i in range(LENS):
        if password[i] != testword[i]:
            return 0
    return 1

def setup():
    """
    キーパッドとLCDディスプレイのセットアップを行います。
    """
    global keypad, last_key_pressed
    # キーパッドのピン設定
    rows_pins = [18, 23, 24, 25]
    cols_pins = [10, 22, 27, 17]
    keys = ["1", "2", "3", "A",
            "4", "5", "6", "B",
            "7", "8", "9", "C",
            "*", "0", "#", "D"]

    # キーパッドとLCDの初期化
    keypad = Keypad(rows_pins, cols_pins, keys)
    last_key_pressed = []
    LCD1602.init(0x27, 1)  # LCDの初期化
    LCD1602.clear()
    LCD1602.write(0, 0, 'WELCOME!')
    LCD1602.write(2, 1, 'パスワードを入力してください')
    sleep(2)

def loop():
    """
    キーパッドの入力とパスワードの検証を処理するメインループです。
    """
    global keyIndex, LENS, keypad, last_key_pressed
    while True:
        pressed_keys = keypad.read()
        if pressed_keys and pressed_keys != last_key_pressed:
            if keyIndex < LENS:
                LCD1602.clear()
                LCD1602.write(0, 0, "パスワードを入力:")
                LCD1602.write(15 - keyIndex, 1, pressed_keys[0])
                testword[keyIndex] = pressed_keys[0]
                keyIndex += 1

            if keyIndex == LENS:
                if check() == 0:
                    LCD1602.clear()
                    LCD1602.write(3, 0, "WRONG KEY!")
                    LCD1602.write(0, 1, "もう一度お試しください")
                else:
                    LCD1602.clear()
                    LCD1602.write(4, 0, "CORRECT!")
                    LCD1602.write(2, 1, "お帰りなさい")
                keyIndex = 0  # チェック後にキーインデックスをリセット

        last_key_pressed = pressed_keys
        sleep(0.1)

try:
    setup()
    loop()
except KeyboardInterrupt:
    LCD1602.clear()  # インタラクト時にLCD表示をクリア

コードの説明

  1. スクリプトはgpiozeroライブラリからデジタル出力デバイスとボタンの管理クラスをインポートします。また、timeモジュールからsleep関数をインポートし、スクリプトの実行中に遅延を追加します。さらに、LCD1602ライブラリもインポートして、LCD1602ディスプレイを制御します。

    #!/usr/bin/env python3
    from gpiozero import DigitalOutputDevice, Button
    from time import sleep
    import LCD1602
    
  2. キーパッドを管理するためのカスタムクラスを定義します。指定された行と列のピンでキーパッドを初期化し、押されたキーを検出する read メソッドを提供します。

    class Keypad:
        def __init__(self, rows_pins, cols_pins, keys):
            """
            指定された行と列のピンおよびキーでキーパッドを初期化します。
            :param rows_pins: 行のGPIOピンのリスト。
            :param cols_pins: 列のGPIOピンのリスト。
            :param keys: キーパッドのレイアウト内のキーのリスト。
            """
            self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]  # 行ピンの設定
            self.cols = [Button(pin, pull_up=False) for pin in cols_pins]  # 列ピンの設定
            self.keys = keys  # キーパッドのキーレイアウト
    
        def read(self):
            """
            現在押されているキーのリストを読み取り、返します。
            :return: 押されているキーのリスト。
            """
            pressed_keys = []
            for i, row in enumerate(self.rows):
                row.on()  # 現在の行をアクティブにする
                for j, col in enumerate(self.cols):
                    if col.is_pressed:
                        index = i * len(self.cols) + j
                        pressed_keys.append(self.keys[index])
                row.off()  # チェック後に行を非アクティブにする
            return pressed_keys
    
  3. パスワードの検証システムをセットアップします。 LENS はパスワードの長さを定義します。 password はプリセットの正しいパスワードで、 testword はユーザーの入力を保存するために使用されます。 keyIndex はユーザーの入力の現在位置を追跡します。

    # パスワードの検証設定
    LENS = 4
    password = ['1', '9', '8', '4']  # プリセットのパスワード
    testword = ['0', '0', '0', '0']  # ユーザーの入力を格納
    keyIndex = 0  # 入力キーのインデックス
    
  4. 入力されたパスワード( testword )とプリセットのパスワード( password )を比較し、結果を返す関数。

    def check():
        """
        入力されたパスワードがプリセットのパスワードと一致するか確認します。
        :return: 一致する場合は1、それ以外の場合は0。
        """
        for i in range(LENS):
            if password[i] != testword[i]:
                return 0
        return 1
    
  5. キーパッドとLCDディスプレイの初期化を行います。歓迎メッセージとパスワード入力の指示を表示します。

    def setup():
        """
        キーパッドとLCDディスプレイのセットアップを行います。
        """
        global keypad, last_key_pressed
        # キーパッドのピン設定
        rows_pins = [18, 23, 24, 25]
        cols_pins = [10, 22, 27, 17]
        keys = ["1", "2", "3", "A",
                "4", "5", "6", "B",
                "7", "8", "9", "C",
                "*", "0", "#", "D"]
    
        # キーパッドとLCDの初期化
        keypad = Keypad(rows_pins, cols_pins, keys)
        last_key_pressed = []
        LCD1602.init(0x27, 1)  # LCDの初期化
        LCD1602.clear()
        LCD1602.write(0, 0, 'WELCOME!')
        LCD1602.write(2, 1, 'パスワードを入力してください')
        sleep(2)
    
  6. キーパッド入力とパスワードの検証を処理するメインループです。入力されたパスワードに基づいてLCDディスプレイを更新し、パスワードが正しいかどうかに応じてフィードバックを提供します。

    def loop():
        """
        キーパッドの入力とパスワードの検証を処理するメインループです。
        """
        global keyIndex, LENS, keypad, last_key_pressed
        while True:
            pressed_keys = keypad.read()
            if pressed_keys and pressed_keys != last_key_pressed:
                if keyIndex < LENS:
                    LCD1602.clear()
                    LCD1602.write(0, 0, "パスワードを入力:")
                    LCD1602.write(15 - keyIndex, 1, pressed_keys[0])
                    testword[keyIndex] = pressed_keys[0]
                    keyIndex += 1
    
                if keyIndex == LENS:
                    if check() == 0:
                        LCD1602.clear()
                        LCD1602.write(3, 0, "WRONG KEY!")
                        LCD1602.write(0, 1, "もう一度お試しください")
                    else:
                        LCD1602.clear()
                        LCD1602.write(4, 0, "CORRECT!")
                        LCD1602.write(2, 1, "お帰りなさい")
                    keyIndex = 0  # チェック後にキーインデックスをリセット
    
            last_key_pressed = pressed_keys
            sleep(0.1)
    
  7. セットアップを実行し、メインループに入ります。キーボード割り込み(Ctrl+C)を使用してプログラムをクリーンに終了させることができます。LCD表示をクリアします。

    try:
        setup()
        loop()
    except KeyboardInterrupt:
        LCD1602.clear()  # インタラクト時にLCD表示をクリア
    
3.1.10 アラームベル
概要

このプロジェクトでは、手動アラームデバイスを作成します。トグルスイッチをサーミスタまたは光感知センサーに置き換えて、温度アラームまたは光アラームを作成できます。

必要なコンポーネント

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

_images/4.1.15_alarm_bell_list.png
回路図
_images/4.1.15_alarm_bell_schematic.png
実験手順

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

_images/4.1.15_alarm_bell_circuit.png

ステップ 2: ディレクトリを変更します。

cd ~/raphael-kit/python-pi5

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

sudo python3 3.1.10_AlarmBell_zero.py

プログラムを起動した後、トグルスイッチを右に切り替えると、ブザーからアラーム音が鳴ります。同時に、赤と緑のLEDが一定の頻度で点滅します。

コード

注釈

以下のコードを 修正/リセット/コピー/実行/停止 することができます。ただし、その前に raphael-kit/python-pi5 のソースコードパスに移動する必要があります。

#!/usr/bin/env python3

from gpiozero import LED, Button, TonalBuzzer
import time
import threading

# GPIOピン22にTonalBuzzerを初期化
BeepPin = TonalBuzzer(22)

# GPIOピン17と27にLEDを初期化
ALedPin = LED(17)
BLedPin = LED(27)

# GPIOピン18にボタンを初期化
switchPin = Button(18)

# ブザーとLEDの状態を管理するためのグローバルフラグ
flag = 0

def ledWork():
    """
    フラグの状態に基づいてLEDの点滅パターンを制御します。
    フラグがセットされている場合、ALedPinとBLedPinを交互に点滅させます。
    フラグがセットされていない場合、両方のLEDをオフにします。
    """
    while True:
        if flag:
            # LEDを交互に点滅
            ALedPin.on()
            time.sleep(0.5)
            ALedPin.off()
            BLedPin.on()
            time.sleep(0.5)
            BLedPin.off()
        else:
            # フラグがセットされていない場合、両方のLEDをオフにする
            ALedPin.off()
            BLedPin.off()

# 音楽の音符とその持続時間のリストとしてチューンを定義します
tune = [
    ('C4', 0.1), ('E4', 0.1), ('G4', 0.1),
    (None, 0.1),
    ('E4', 0.1), ('G4', 0.1), ('C5', 0.1),
    (None, 0.1),
    ('C5', 0.1), ('G4', 0.1), ('E4', 0.1),
    (None, 0.1),
    ('G4', 0.1), ('E4', 0.1), ('C4', 0.1),
    (None, 0.1)
]

def buzzerWork():
    """
    フラグの状態に基づいてブザーを使って曲を演奏します。
    フラグがセットされている場合のみ曲が演奏されます。
    曲が演奏中にフラグが解除されると、曲が停止します。
    """
    while True:
        for note, duration in tune:
            if flag == 0:
                break
            print(note)  # 現在の音符をコンソールに出力
            BeepPin.play(note)  # 現在の音符を演奏
            time.sleep(duration)  # 音符の持続時間だけ一時停止
        BeepPin.stop()  # 曲の演奏後にブザーを停止

def main():
    """
    ボタンの押下を監視してフラグの状態を更新します。
    ボタンが押されるとフラグがセットされます。
    """
    global flag
    while True:
        flag = 1 if switchPin.is_pressed else 0

try:
    # ブザーとLED制御のスレッドを初期化して開始します
    tBuzz = threading.Thread(target=buzzerWork)
    tBuzz.start()
    tLed = threading.Thread(target=ledWork)
    tLed.start()
    main()

except KeyboardInterrupt:
    # プログラムが中断されたときにブザーを停止し、LEDをオフにします
    BeepPin.stop()
    ALedPin.off()
    BLedPin.off()

コードの説明

  1. このセグメントでは、遅延とスレッド処理の実装に必要なライブラリのインポートを行います。また、Raspberry Pi上のGPIOデバイスを制御するために、gpiozeroライブラリからLED、Button、およびTonalBuzzerクラスもインポートしています。

    #!/usr/bin/env python3
    
    from gpiozero import LED, Button, TonalBuzzer
    import time
    import threading
    
  2. GPIOピン22にブザー、GPIOピン17と27にLED、GPIOピン18にボタンをセットアップします。ブザーとLEDの状態を管理するために、グローバルフラグも定義されています。

    # GPIOピン22にTonalBuzzerを初期化
    BeepPin = TonalBuzzer(22)
    
    # GPIOピン17と27にLEDを初期化
    ALedPin = LED(17)
    BLedPin = LED(27)
    
    # GPIOピン18にボタンを初期化
    switchPin = Button(18)
    
    # ブザーとLEDの状態を管理するためのグローバルフラグ
    flag = 0
    
  3. この関数は、フラグの状態に応じてLEDの点滅を制御します。フラグが設定されている(1)場合、各LEDをオンとオフに交互に切り替えます。フラグが設定されていない(0)場合、両方のLEDをオフにします。

    def ledWork():
        """
        フラグの状態に基づいてLEDの点滅パターンを制御します。
        フラグがセットされている場合、ALedPinとBLedPinを交互に点滅させます。
        フラグがセットされていない場合、両方のLEDをオフにします。
        """
        while True:
            if flag:
                # LEDを交互に点滅
                ALedPin.on()
                time.sleep(0.5)
                ALedPin.off()
                BLedPin.on()
                time.sleep(0.5)
                BLedPin.off()
            else:
                # フラグがセットされていない場合、両方のLEDをオフにする
                ALedPin.off()
                BLedPin.off()
    
  4. 音楽の音符(周波数)と持続時間(秒)のシーケンスである「tune」が定義されています。

    # 音楽の音符とその持続時間のリストとしてチューンを定義
    tune = [
        ('C4', 0.1), ('E4', 0.1), ('G4', 0.1),
        (None, 0.1),
        ('E4', 0.1), ('G4', 0.1), ('C5', 0.1),
        (None, 0.1),
        ('C5', 0.1), ('G4', 0.1), ('E4', 0.1),
        (None, 0.1),
        ('G4', 0.1), ('E4', 0.1), ('C4', 0.1),
        (None, 0.1)
    ]
    
  5. フラグが設定されている場合に予め定義されたメロディを演奏します。演奏中にフラグが解除されると、演奏が停止します。

    def buzzerWork():
        """
        フラグの状態に基づいてブザーを使って曲を演奏します。
        フラグがセットされている場合のみ曲が演奏されます。
        曲が演奏中にフラグが解除されると、曲が停止します。
        """
        while True:
            for note, duration in tune:
                if flag == 0:
                    break
                print(note)  # 現在の音符をコンソールに出力
                BeepPin.play(note)  # 現在の音符を演奏
                time.sleep(duration)  # 音符の持続時間だけ一時停止
            BeepPin.stop()  # 曲の演奏後にブザーを停止
    
  6. ボタンの状態を確認し、フラグを設定または解除します。

    def main():
        """
        ボタンの押下を監視してフラグの状態を更新します。
        ボタンが押されるとフラグがセットされます。
        """
        global flag
        while True:
            flag = 1 if switchPin.is_pressed else 0
    
  7. buzzerWorkledWork のスレッドを開始し、それらをメイン関数と同時に実行できるようにします。

    try:
        # ブザーとLED制御のスレッドを初期化して開始します
        tBuzz = threading.Thread(target=buzzerWork)
        tBuzz.start()
        tLed = threading.Thread(target=ledWork)
        tLed.start()
        main()
    
  8. プログラムが中断されたときに、きれいに終了するように、ブザーを停止し、LEDをオフにします。

    except KeyboardInterrupt:
        # プログラムが中断されたときにブザーを停止し、LEDをオフにします
        BeepPin.stop()
        ALedPin.off()
        BLedPin.off()
    
3.1.11 モールス信号ジェネレータ
はじめに

このプロジェクトでは、Raspberry Piに英字のシリーズを入力し、それをモールス信号として表示するモールス信号ジェネレータを作成します。

必要なコンポーネント

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

_images/4.1.16_morse_code_generator_list.png
回路図
_images/4.1.16_morse_code_generator_schematic.png
実験手順

ステップ1: 回路を組み立てます。(ブザーの極性に注意してください:+ラベルのある方が正極で、もう一方が負極です。)

_images/4.1.16_morse_code_generator_circuit.png

ステップ2: コードファイルを開きます。

cd ~/raphael-kit/python-pi5

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

sudo python3 3.1.11_MorseCodeGenerator_zero.py

プログラムが実行されたら、一連の文字列を入力し、ブザーとLEDが対応するモールス信号を送信します。

コード

#!/usr/bin/env python3
from gpiozero import Buzzer, LED
import time

# ブザーとLEDをGPIOピンに初期化
BeepPin = Buzzer(22)
ALedPin = LED(17)

# 文字のモールス信号表現
MORSECODE = {
    'A': '01', 'B': '1000', 'C': '1010', 'D': '100', 'E': '0', 'F': '0010', 'G': '110',
    'H': '0000', 'I': '00', 'J': '0111', 'K': '101', 'L': '0100', 'M': '11', 'N': '10',
    'O': '111', 'P': '0110', 'Q': '1101', 'R': '010', 'S': '000', 'T': '1',
    'U': '001', 'V': '0001', 'W': '011', 'X': '1001', 'Y': '1011', 'Z': '1100',
    '1': '01111', '2': '00111', '3': '00011', '4': '00001', '5': '00000',
    '6': '10000', '7': '11000', '8': '11100', '9': '11110', '0': '11111',
    '?': '001100', '/': '10010', ',': '110011', '.': '010101', ';': '101010',
    '!': '101011', '@': '011010', ':': '111000',
}

def on():
    """ ブザーとLEDをオンにします。"""
    BeepPin.on()
    ALedPin.on()

def off():
    """ ブザーとLEDをオフにします。"""
    BeepPin.off()
    ALedPin.off()

def beep(dt):  # dtは遅延時間用です。
    """
    指定された時間のブザー音とLEDフラッシュを生成します。
    :param dt: ブザー音とフラッシュのための期間。
    """
    on()
    time.sleep(dt)
    off()
    time.sleep(dt)

def morsecode(code):
    """
    入力されたコードをモールス信号に変換し、ブザーとLEDを使用して信号化します。
    :param code: モールス信号に変換するテキスト。
    """
    pause = 0.25
    for letter in code:
        for tap in MORSECODE[letter]:
            if tap == '0':
                beep(pause / 2)  # 短いビープ音
            if tap == '1':
                beep(pause)      # 長いビープ音
        time.sleep(pause)  # 文字間の休憩

def destroy():
    """ スクリプトの終了時にリソースをクリーンアップします。"""
    print("")
    BeepPin.off()
    ALedPin.off()

try:
    while True:
        code = input("メッセンジャーを入力してください:")
        code = code.upper()  # モールス信号検索用に大文字に変換
        print(code)
        morsecode(code)
except KeyboardInterrupt:
    destroy()

コードの説明

  1. このコードは、gpiozeroライブラリからBuzzerおよびLEDクラスをインポートしています。これらのクラスは、Raspberry Pi上の対応するGPIOデバイスを制御するために必要です。

    #!/usr/bin/env python3
    from gpiozero import Buzzer, LED
    import time
    
  2. GPIOピン22のブザーとGPIOピン17のLEDを初期化して、これらのコンポーネントを制御するのに役立てます。

    # ブザーとLEDをGPIOピンに初期化
    BeepPin = Buzzer(22)
    ALedPin = LED(17)
    
  3. MORSECODE 構造を定義します。これは、AからZまでの文字、0から9までの数字、および「?」、「/」、「:」、「,」、「.」、「;」、「!」、「@」などの記号のモールス信号表現を含む辞書です。ここで、 0 はドットを示し、 1 はダッシュを示します。

    # 文字のモールス信号表現
    MORSECODE = {
        'A': '01', 'B': '1000', 'C': '1010', 'D': '100', 'E': '0', 'F': '0010', 'G': '110',
        'H': '0000', 'I': '00', 'J': '0111', 'K': '101', 'L': '0100', 'M': '11', 'N': '10',
        'O': '111', 'P': '0110', 'Q': '1101', 'R': '010', 'S': '000', 'T': '1',
        'U': '001', 'V': '0001', 'W': '011', 'X': '1001', 'Y': '1011', 'Z': '1100',
        '1': '01111', '2': '00111', '3': '00011', '4': '00001', '5': '00000',
        '6': '10000', '7': '11000', '8': '11100', '9': '11110', '0': '11111',
        '?': '001100', '/': '10010', ',': '110011', '.': '010101', ';': '101010',
        '!': '101011', '@': '011010', ':': '111000',
    }
    
  4. on() 関数はブザーとLEDをオンにします。 off() 関数はブザーとLEDをオフにします。

    def on():
        """ ブザーとLEDをオンにします。"""
        BeepPin.on()
        ALedPin.on()
    
    def off():
        """ ブザーとLEDをオフにします。"""
        BeepPin.off()
        ALedPin.off()
    
  5. beep() 関数は、ブザーとLEDを指定された時間間隔で音を鳴らし、点滅させるために使用されます。

    def beep(dt):  # dtは遅延時間用です。
        """
        指定された時間のブザー音とLEDフラッシュを生成します。
        :param dt: ブザー音とフラッシュのための期間。
        """
        on()
        time.sleep(dt)
        off()
        time.sleep(dt)
    
  6. morsecode() 関数は、入力された文字のモールス信号を処理し、ブザーとLEDを使用してそれを示します。

    def morsecode(code):
        """
        入力されたコードをモールス信号に変換し、ブザーとLEDを使用して信号化します。
        :param code: モールス信号に変換するテキスト。
        """
        pause = 0.25
        for letter in code:
            for tap in MORSECODE[letter]:
                if tap == '0':
                    beep(pause / 2)  # 短いビープ音
                if tap == '1':
                    beep(pause)      # 長いビープ音
            time.sleep(pause)  # 文字間の休憩
    
  7. destroy() 関数は、スクリプトが終了したときにブザーとLEDの両方をオフにするようにします。これにより、GPIOピンがアクティブな状態にならないようになります。

    def destroy():
        """ スクリプトの終了時にリソースをクリーンアップします。"""
        print("")
        BeepPin.off()
        ALedPin.off()
    
  8. キーボードで関連する文字を入力すると、 upper() が入力文字を大文字に変換します。 printf() はコンピュータ画面にクリアテキストを表示し、 morsecode() 関数はブザーとLEDにモールス信号を出力させます。

    try:
        while True:
            code = input("メッセンジャーを入力してください:")
            code = code.upper()  # モールス信号検索用に大文字に変換
            print(code)
            morsecode(code)
    except KeyboardInterrupt:
        destroy()
    
3.1.12 ゲーム – 数当て
はじめに

数当ては、あなたと友達が交互に数字(0〜99)を入力する楽しいパーティーゲームです。数字の入力に従って、範囲は狭まっていき、プレイヤーが謎を正しく解答するまで続きます。その後、プレイヤーは負けて罰せられます。たとえば、幸運の数字が51で、プレイヤー1が50を入力した場合、数字の範囲は50〜99に変わります。プレイヤー2が70を入力すると、数字の範囲は50〜70になります。プレイヤー3が51を入力した場合、そのプレイヤーは不運です。ここでは、キーパッドを使用して数字を入力し、LCDを使用して結果を表示します。

必要なコンポーネント

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

_images/4.1.17_game_guess_number_list.png
回路図
_images/4.1.17_game_guess_number_schematic.png
実験手順

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

_images/4.1.17_game_guess_number_circuit.png

ステップ 2: I2Cをセットアップします(詳細は I2C構成 を参照)。

ステップ 3: ディレクトリを変更します。

cd ~/raphael-kit/python-pi5

ステップ 4: 実行します。

sudo python3 3.1.12_GAME_GuessNumber_zero.py

プログラムが実行されると、LCDに初期ページが表示されます:

ようこそ!
Aボタンを押して開始!

'A'ボタンを押すと、ゲームが開始し、LCDにゲームページが表示されます。

数字を入力してください:
0 ‹point‹ 99

ランダムな数字 '‹point‹' がゲーム開始時に生成されますが、LCDには表示されません。必要なことは、それを推測することです。入力した数値は、最終的な計算が終了するまで、最初の行の末尾に表示されます(比較を開始するには 'D' を押し、入力された数値が 10 より大きい場合、自動的な比較が開始されます)。

'‹point‹' の数値範囲が2行目に表示されます。指定された範囲内で数値を入力する必要があります。数値を入力すると、範囲が狭まり、幸運か不運かにかかわらず、「当たりました!」と表示されます。

注釈

  • エラー「 FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1' 」が表示される場合、I2Cを有効にするには I2C構成 を参照してください。

  • エラー「 ModuleNotFoundError: No module named 'smbus2' 」が表示される場合、「 sudo pip3 install smbus2 」を実行してください。

  • エラー「 OSError: [Errno 121] Remote I/O error 」が表示される場合、モジュールの接続が誤っているか、モジュールが壊れている可能性があります。

  • コードと配線が正常であるにもかかわらず、LCDにコンテンツが表示されない場合は、背面のポテンショメーターを回してコントラストを上げることができます。

コード

注釈

以下のコードを 修正/リセット/コピー/実行/停止 することができます。ただし、その前に「raphael-kit/python-pi5」のようなソースコードのパスに移動する必要があります。コードを変更した後、効果を確認するために直接実行できます。

#!/usr/bin/env python3

from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602
import random

class Keypad:
   def __init__(self, rows_pins, cols_pins, keys):
      """
      キーパッドを指定した行と列のピン、キーレイアウトで初期化します。
      :param rows_pins: 行のGPIOピンのリスト。
      :param cols_pins: 列のGPIOピンのリスト。
      :param keys: キーパッド上のキーの配置。
      """
      self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]  # 行のピンをセットアップ
      self.cols = [Button(pin, pull_up=False) for pin in cols_pins]  # 列のピンをセットアップ
      self.keys = keys  # キーパッドのレイアウトを定義

   def read(self):
      """
      現在押されているキーを読み取り、返します。
      :return: 押されたキーのリスト。
      """
      pressed_keys = []
      for i, row in enumerate(self.rows):
            row.on()  # 現在の行をアクティブにする
            for j, col in enumerate(self.cols):
               if col.is_pressed:
                  index = i * len(self.cols) + j
                  pressed_keys.append(self.keys[index])  # 押されたキーを追加
            row.off()  # 行を非アクティブにする
      return pressed_keys

# ゲームに関連する変数
count = 0
pointValue = 0
upper = 99
lower = 0

def setup():
   """
   キーパッドとLCDディスプレイを初期化するセットアップ関数。
   """
   global keypad, last_key_pressed, keys
   rowsPins = [18, 23, 24, 25]
   colsPins = [10, 22, 27, 17]
   keys = ["1", "2", "3", "A",
            "4", "5", "6", "B",
            "7", "8", "9", "C",
            "*", "0", "#", "D"]
   keypad = Keypad(rowsPins, colsPins, keys)
   last_key_pressed = []
   LCD1602.init(0x27, 1)  # LCDを初期化
   LCD1602.clear()
   LCD1602.write(0, 0, 'ようこそ!')
   LCD1602.write(0, 1, 'Aを押して開始!')

def init_new_value():
   """
   新しい目標値を初期化し、ゲームのパラメーターをリセットします。
   """
   global pointValue, upper, lower, count
   pointValue = random.randint(0, 99)
   upper = 99
   lower = 0
   count = 0
   print('目標値は %d です' % pointValue)

def detect_point():
   """
   推測された数値が目標と一致するか、高すぎるか、低すぎるかをチェックします。
   :return: 1(正しい推測)または0(それ以外)。
   """
   global count, upper, lower
   if count > pointValue and count < upper:
      upper = count
   elif count < pointValue and count > lower:
      lower = count
   elif count == pointValue:
      count = 0
      return 1
   count = 0
   return 0

def lcd_show_input(result):
   """
   LCDに現在のゲームの状態と結果を表示します。
   :param result: 最後の推測の結果(0または1)。
   """
   LCD1602.clear()
   if result == 1:
      LCD1602.write(0, 1, '当たりました!')
      sleep(5)
      init_new_value()
      lcd_show_input(0)
   else:
      LCD1602.write(0, 0, '数字を入力:')
      LCD1602.write(13, 0, str(count))
      LCD1602.write(0, 1, str(lower))
      LCD1602.write(3, 1, ' < 目標 < ')
      LCD1602.write(13, 1, str(upper))

def loop():
   """
   キーパッドの入力を処理し、ゲームの状態を更新し、LCDに結果を表示するメインループ。
   """
   global keypad, last_key_pressed, count
   while True:
      result = 0
      pressed_keys = keypad.read()
      if pressed_keys and pressed_keys != last_key_pressed:
            if pressed_keys == ["A"]:
               init_new_value()
               lcd_show_input(0)
            elif pressed_keys == ["D"]:
               result = detect_point()
               lcd_show_input(result)
            elif pressed_keys[0] in keys:
               if pressed_keys[0] in ["A", "B", "C", "D", "#", "*"]:
                  continue
               count = count * 10 + int(pressed_keys[0])
               if count >= 10:
                  result = detect_point()
               lcd_show_input(result)
            print(pressed_keys)
      last_key_pressed = pressed_keys
      sleep(0.1)

try:
   setup()
   loop()
except KeyboardInterrupt:
   LCD1602.clear()  # 割り込み時にLCDをクリア

コード説明

  1. GPIO Zeroライブラリからデジタル出力デバイスとボタンのための重要なクラスをインポートするセクションです。スクリプト内で遅延を導入するために、timeモジュールのsleep関数も含まれています。LCD1602ライブラリは、テキストやデータ出力を表示するために役立つLCDディスプレイの操作に利用されます。さらに、ランダムな数字を生成するための関数を提供するrandomライブラリも組み込まれています。これはプロジェクトのさまざまな面で有利になる可能性があります。

    #!/usr/bin/env python3
    
    from gpiozero import DigitalOutputDevice, Button
    from time import sleep
    import LCD1602
    import random
    
  2. キーパッドのクラスを定義し、行と列のピンで初期化し、押されたキーを読み取るメソッドを定義します。

    class Keypad:
       def __init__(self, rows_pins, cols_pins, keys):
          """
          指定された行と列のピン、およびキーレイアウトでキーパッドを初期化します。
          :param rows_pins: 行のためのGPIOピンのリスト。
          :param cols_pins: 列のためのGPIOピンのリスト。
          :param keys: キーパッド上のキーのレイアウト。
          """
          self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]  # 行ピンの設定
          self.cols = [Button(pin, pull_up=False) for pin in cols_pins]  # 列ピンの設定
          self.keys = keys  # キーパッドのレイアウトを定義
    
       def read(self):
          """
          現在押されているキーを読み取り、返します。
          :return: 押されたキーのリスト。
          """
          pressed_keys = []
          for i, row in enumerate(self.rows):
                row.on()  # 現在の行をアクティブにする
                for j, col in enumerate(self.cols):
                   if col.is_pressed:
                      index = i * len(self.cols) + j
                      pressed_keys.append(self.keys[index])  # 押されたキーを追加
                row.off()  # 行を非アクティブにする
          return pressed_keys
    
  3. ゲームに関連する変数「count」をゼロとして初期化し、キーパッドとLCDディスプレイを設定し、ウェルカムメッセージと指示を表示します。ゲームでの特定のスコアや値を表す可能性がある「pointValue」変数をゼロに初期化します。当初は99に設定された「upper」は、数字当てゲームの最大値として使用される可能性があります。ゲームの最小境界として使用される可能性のあるゼロからの「lower」限界を設定します。

    # ゲーム関連の変数
    count = 0
    pointValue = 0
    upper = 99
    lower = 0
    
  4. キーパッドとLCDディスプレイを設定し、ウェルカムメッセージと指示を表示します。

    def setup():
       """
       キーパッドとLCDディスプレイを初期化するためのセットアップ関数。
       """
       global keypad, last_key_pressed, keys
       rowsPins = [18, 23, 24, 25]
       colsPins = [10, 22, 27, 17]
       keys = ["1", "2", "3", "A",
                "4", "5", "6", "B",
                "7", "8", "9", "C",
                "*", "0", "#", "D"]
       keypad = Keypad(rowsPins, colsPins, keys)
       last_key_pressed = []
       LCD1602.init(0x27, 1)  # LCDの初期化
       LCD1602.clear()
       LCD1602.write(0, 0, 'Welcome!')
       LCD1602.write(0, 1, 'Press A to Start!')
    
  5. 新しいターゲット値を初期化し、ゲームのパラメータをリセットします。

    def init_new_value():
       """
       新しいターゲット値を初期化し、ゲームのパラメータをリセットします。
       """
       global pointValue, upper, lower, count
       pointValue = random.randint(0, 99)
       upper = 99
       lower = 0
       count = 0
       print('point is %d' % pointValue)
    
  6. 推測された数字がターゲットと一致するかどうかをチェックし、それに応じて推測範囲を更新します。

    def detect_point():
       """
       推測された数字がターゲットか、高すぎるか、低すぎるかをチェックします。
       :return: 正しい推測の場合は1、それ以外の場合は0。
       """
       global count, upper, lower
       if count > pointValue and count < upper:
          upper = count
       elif count < pointValue and count > lower:
          lower = count
       elif count == pointValue:
          count = 0
          return 1
       count = 0
       return 0
    
  7. LCDにゲームの状態を表示し、現在の推測、範囲、結果を示します。

    def lcd_show_input(result):
       """
       LCDに現在のゲームの状態と結果を表示します。
       :param result: 最後の推測の結果(0または1)。
       """
       LCD1602.clear()
       if result == 1:
          LCD1602.write(0, 1, 'You have got it!')
          sleep(5)
          init_new_value()
          lcd_show_input(0)
       else:
          LCD1602.write(0, 0, 'Enter number:')
          LCD1602.write(13, 0, str(count))
          LCD1602.write(0, 1, str(lower))
          LCD1602.write(3, 1, ' < Point < ')
          LCD1602.write(13, 1, str(upper))
    
  8. キーパッド入力の処理、ゲームの状態の更新、LCDへの結果の表示を行うメインループです。

    def loop():
       """
       キーパッド入力の処理とゲームの状態の更新を行うメインゲームループ。
       """
       global keypad, last_key_pressed, count
       while True:
          result = 0
          pressed_keys = keypad.read()
          if pressed_keys and pressed_keys != last_key_pressed:
                if pressed_keys == ["A"]:
                   init_new_value()
                   lcd_show_input(0)
                elif pressed_keys == ["D"]:
                   result = detect_point()
                   lcd_show_input(result)
                elif pressed_keys[0] in keys:
                   if pressed_keys[0] in ["A", "B", "C", "D", "#", "*"]:
                      continue
                   count = count * 10 + int(pressed_keys[0])
                   if count >= 10:
                      result = detect_point()
                   lcd_show_input(result)
                print(pressed_keys)
          last_key_pressed = pressed_keys
          sleep(0.1)
    
  9. セットアップを実行し、メインゲームループに入ります。キーボード割り込みを使用してクリーンな終了が可能です。

    try:
       setup()
       loop()
    except KeyboardInterrupt:
       LCD1602.clear()  # 割り込み時にLCDをクリア
    
3.1.13 GAME - 10秒間
はじめに

次に、集中力を試すゲームデバイスを作ってみましょう。 傾きスイッチを棒に結び付けて、魔法の杖を作ります。杖を振ると、 4桁のセグメント表示がカウントを開始し、もう一度振るとカウントが停止します。表示されたカウントを 10.00 で停止させることができれば、あなたの勝利です。友達とこのゲームをして、 誰が時間の魔法使いかを競い合うことができます。

必要なコンポーネント

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

_images/4.1.18_game_10_second_list.png
回路図

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

GPIO26

Pin 37

25

26

_images/4.1.18_game_10_second_schematic.png
実験手順

ステップ1: 回路を組み立てる。

_images/4.1.18_game_10_second_circuit.png

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

cd ~/raphael-kit/python-pi5

ステップ3: 実行可能ファイルを実行する。

sudo python3 3.1.13_GAME_10Second_zero.py

杖を振ると、4桁のセグメント表示がカウントを開始し、もう一度振るとカウントが停止します。表示されたカウントを 10.00 で停止させることができれば、あなたの勝利です。もう一度振ると、ゲームの次のラウンドが始まります。

コード

注釈

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

#!/usr/bin/env python3

from gpiozero import OutputDevice, Button
import time
import threading

# GPIO 26に接続されたボタンを初期化
sensorPin = Button(26)

# 74HC595シフトレジスタに接続されたGPIOピンを定義
SDI = OutputDevice(24)   # シリアルデータ入力
RCLK = OutputDevice(23)  # レジスタクロック
SRCLK = OutputDevice(18) # シフトレジスタクロック

# 7セグメント表示の各桁の選択用のGPIOピンを定義
placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]

# 7セグメント表示で0〜9の数字を表示するためのセグメントコードを定義
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# カウンターとタイマー変数
counter = 0
timer1 = None
gameState = 0

def clearDisplay():
    """ 7セグメント表示の全セグメントを消去します。 """
    for _ in range(8):
        SDI.on()
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def hc595_shift(data):
    """ デジットを表示するために74HC595シフトレジスタにデータをシフトします。 """
    for i in range(8):
        SDI.value = 0x80 & (data << i)
        SRCLK.on()
        SRCLK.off()
    RCLK.on()
    RCLK.off()

def pickDigit(digit):
    """ 7セグメント表示でどの桁を表示するかを選択します。 """
    for pin in placePin:
        pin.off()
    placePin[digit].on()

def display():
    """ 現在のカウンター値を7セグメント表示に表示します。 """
    global counter
    clearDisplay()
    pickDigit(0)
    hc595_shift(number[counter % 10])

    clearDisplay()
    pickDigit(1)
    hc595_shift(number[counter % 100 // 10])

    clearDisplay()
    pickDigit(2)
    hc595_shift(number[counter % 1000 // 100] - 0x80)

    clearDisplay()
    pickDigit(3)
    hc595_shift(number[counter % 10000 // 1000])

def stateChange():
    """ ボタン押下に基づいてカウンターの状態を変更します。 """
    global gameState, counter, timer1
    if gameState == 0:
        counter = 0
        time.sleep(1)
        timer()
    elif gameState == 1 and timer1 is not None:
        timer1.cancel()
        time.sleep(1)
    gameState = (gameState + 1) % 2

def loop():
    """ ボタンの状態をチェックし、表示を更新するメインループです。 """
    global counter
    currentState = 0
    lastState = 0
    while True:
        display()
        currentState = sensorPin.value
        if (currentState == 0) and (lastState == 1):
            stateChange()
        lastState = currentState

def timer():
    """ 0.01秒ごとにカウンターを増加させるタイマー関数です。 """
    global counter, timer1
    timer1 = threading.Timer(0.01, timer)
    timer1.start()
    counter += 1

try:
    loop()
except KeyboardInterrupt:
    if timer1:
        timer1.cancel()

コードの説明

  1. 必要なモジュールをインポートしてスクリプトを開始します。 gpiozero ライブラリはボタンなどのGPIOデバイスとのインターフェースに使用され、 time および threading モジュールはタイミング関連のタスクや並行操作を扱うために使用されるかもしれません。

    #!/usr/bin/env python3
    
    from gpiozero import OutputDevice, Button
    import time
    import threading
    
  2. GPIOピン26に接続された Button オブジェクトを初期化します。このセットアップにより、ボタン押下を検出することができます。

    # GPIO 26に接続されたボタンを初期化
    sensorPin = Button(26)
    
  3. シフトレジスタのシリアルデータ入力(SDI)、レジスタクロック入力(RCLK)、シフトレジスタクロック入力(SRCLK)に接続されたGPIOピンを初期化します。

    # 74HC595シフトレジスタに接続されたGPIOピンを定義
    SDI = OutputDevice(24)   # シリアルデータ入力
    RCLK = OutputDevice(23)  # レジスタクロック
    SRCLK = OutputDevice(18) # シフトレジスタクロック
    
  4. 7セグメント表示の各桁の選択用のピンを初期化し、0〜9の数字を表示するためのバイナリコードを定義します。

    # 7セグメント表示の各桁の選択用のGPIOピンを定義
    placePin = [OutputDevice(pin) for pin in (10, 22, 27, 17)]
    
    # 7セグメント表示で0〜9の数字を表示するためのセグメントコードを定義
    number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
    
  5. 7セグメント表示を制御するための関数です。 clearDisplay はすべてのセグメントをオフにし、 hc595_shift はシフトレジスタにデータをシフトし、 pickDigit は表示上の特定の桁をアクティブにします。

    def clearDisplay():
        """ 7セグメント表示の全セグメントを消去します。 """
        for _ in range(8):
            SDI.on()
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
    def hc595_shift(data):
        """ デジットを表示するために74HC595シフトレジスタにデータをシフトします。 """
        for i in range(8):
            SDI.value = 0x80 & (data << i)
            SRCLK.on()
            SRCLK.off()
        RCLK.on()
        RCLK.off()
    
    def pickDigit(digit):
        """ 7セグメント表示でどの桁を表示するかを選択します。 """
        for pin in placePin:
            pin.off()
        placePin[digit].on()
    
  6. 現在のカウンター値を7セグメント表示に表示する関数です。

    def display():
        """ 現在のカウンター値を7セグメント表示に表示します。 """
        global counter
        clearDisplay()
        pickDigit(0)
        hc595_shift(number[counter % 10])
    
        clearDisplay()
        pickDigit(1)
        hc595_shift(number[counter % 100 // 10])
    
        clearDisplay()
        pickDigit(2)
        hc595_shift(number[counter % 1000 // 100] - 0x80)
    
        clearDisplay()
        pickDigit(3)
        hc595_shift(number[counter % 10000 // 1000])
    
  7. ボタン押下に基づいてカウンターの状態を変更する関数です。

    def stateChange():
        """ ボタン押下に基づいてカウンターの状態を変更します。 """
        global gameState, counter, timer1
        if gameState == 0:
            counter = 0
            time.sleep(1)
            timer()
        elif gameState == 1 and timer1 is not None:
            timer1.cancel()
            time.sleep(1)
        gameState = (gameState + 1) % 2
    
  8. ボタンの状態を継続的にチェックし、表示を更新するメインループです。ボタンの状態が変わると、 stateChange を呼び出します。

    def loop():
        """ ボタンの状態をチェックし、表示を更新するメインループです。 """
        global counter
        currentState = 0
        lastState = 0
        while True:
            display()
            currentState = sensorPin.value
            if (currentState == 0) and (lastState == 1):
                stateChange()
            lastState = currentState
    
  9. 0.01秒ごとにカウンターを増加させるタイマー関数です。

    def timer():
        """ 0.01秒ごとにカウンターを増加させるタイマー関数です。 """
        global counter, timer1
        timer1 = threading.Timer(0.01, timer)
        timer1.start()
        counter += 1
    
  10. メインループを実行し、キーボード割り込み(Ctrl+C)を使用してプログラムからクリーンに終了することができます。

    try:
        loop()
    except KeyboardInterrupt:
        if timer1:
            timer1.cancel()
    
3.1.14 GAME– 逆逆
はじめに

このレッスンでは、面白いゲームデバイスを作ります。その名も「逆逆」です。

ゲーム中、ドットマトリクスはランダムに矢印を表示します。あなたがすることは、限られた時間内に矢印の反対方向のボタンを押すことです。時間切れ、または矢印と同じ方向のボタンを押すと、あなたはアウトです。

このゲームはあなたの逆向き思考を本当に鍛えることができます。さあ、試してみましょうか?

必要なコンポーネント

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

_images/3.1.14_game_not_not_list.png
回路図

T-Board Name

physical

wiringPi

BCM

GPIO17

Pin 11

0

17

GPIO18

Pin 12

1

18

GPIO27

Pin 13

2

27

GPIO20

Pin 38

28

20

GPIO26

Pin 37

25

26

_images/3.1.14_game_not_not_schematic.png
実験手順

ステップ1: 回路を組み立てる。

_images/3.1.14_game_not_not_circuit.png

ステップ2: コードファイルを開く。

cd ~/davinci-kit-for-raspberry-pi/python-pi5

ステップ3: 実行。

sudo python3 3.1.14_MotionControl_zero.py

プログラムを開始すると、ドットマトリクスに右または左を指す矢印が表示されます。あなたがすることは、限られた時間内に矢印の反対方向のボタンを押すことです。そうするとドットマトリクスに「」が表示されます。時間切れ、または矢印と同じ方向のボタンを押すと、アウトでドットマトリクスに「x」が表示されます。上下左右の4方向に対応するために、2つの新しいボタンを追加するか、ジョイスティックキーに置き換えてゲームの難易度を上げることもできます。

コード

注釈

下記のコードは 変更/リセット/コピー/実行/停止 が可能です。しかし、それを行う前に、 davinci-kit-for-raspberry-pi/python-pi5 のようなソースコードのパスに移動する必要があります。コードを変更した後、直接実行して効果を確認することができます。

#!/usr/bin/env python3
from gpiozero import OutputDevice, Button
import time
import threading
import random

# 74HC595シフトレジスタのGPIOピン
SDI = OutputDevice(17)   # シリアルデータ入力
RCLK = OutputDevice(18)  # レジスタクロック
SRCLK = OutputDevice(27) # シフトレジスタクロック

# ボタンのGPIOピン
AButtonPin = Button(20)  # ボタンA
BButtonPin = Button(26)  # ボタンB

# ゲーム変数の初期化
timerPlay = 0
timerCheck = 0
waypoint = "NULL"
stage = "NULL"

# LEDマトリクス表示の矢印グリフ
arrow = {
    "right": [0xFF, 0xEF, 0xDF, 0x81, 0xDF, 0xEF, 0xFF, 0xFF],
    "left": [0xFF, 0xF7, 0xFB, 0x81, 0xFB, 0xF7, 0xFF, 0xFF]
}

# 正解/誤りのフィードバックグリフ
check = {
    "wrong": [0xFF, 0xBB, 0xD7, 0xEF, 0xD7, 0xBB, 0xFF, 0xFF],
    "right": [0xFF, 0xFF, 0xF7, 0xEB, 0xDF, 0xBF, 0xFF, 0xFF]
}

def hc595_shift(dat):
    """ 74HC595シフトレジスタにデータをシフトします。 """
    for i in range(8):
        SDI.value = 0x80 & (dat << i)
        SRCLK.on()
        SRCLK.off()

def display(glyphCode):
    """ LEDマトリクスにグリフを表示します。 """
    for i in range(0, 8):
        hc595_shift(glyphCode[i])
        hc595_shift(0x80 >> i)
        RCLK.on()
        RCLK.off()

def creatGlyph():
    """ ゲームの新しいグリフを作成し、プレイタイマーを開始します。 """
    global waypoint, stage, timerPlay
    waypoint = random.choice(list(arrow.keys()))
    stage = "PLAY"
    timerPlay = threading.Timer(2.0, timeOut)
    timerPlay.start()

def checkPoint(inputKey):
    """ プレイヤーの入力をチェックし、ゲームの状態を更新します。 """
    global waypoint, stage, timerCheck
    if inputKey == "empty" or inputKey == waypoint:
        waypoint = "wrong"
    else:
        waypoint = "right"
    timerPlay.cancel()
    stage = "CHECK"
    timerCheck = threading.Timer(1.0, creatGlyph)
    timerCheck.start()

def timeOut():
    """ ゲームのタイムアウトシナリオを処理します。 """
    checkPoint("empty")

def getKey():
    """ ボタン押下を検出し、チェックポイントをトリガーします。 """
    if AButtonPin.is_pressed and not BButtonPin.is_pressed:
        checkPoint("right")
    elif not AButtonPin.is_pressed and BButtonPin.is_pressed:
        checkPoint("left")

def main():
    """ メインゲームループ。 """
    creatGlyph()
    while True:
        if stage == "PLAY":
            display(arrow[waypoint])
            getKey()
        elif stage == "CHECK":
            display(check[waypoint])

def destroy():
    """ プログラム終了時にリソースをクリーンアップします。 """
    global timerPlay, timerCheck
    timerPlay.cancel()  # プレイタイマーをキャンセル
    timerCheck.cancel()  # チェックポイントタイマーをキャンセル

# ゲームを実行し、キーボード割り込みでクリーンな終了を処理
try:
    main()
except KeyboardInterrupt:
    destroy()

コードの説明

1.1.6 LEDドットマトリクス を基にして、このレッスンでは 2 つのボタンを追加し、面白いゲームデバイスを作ります。ですので、ドットマトリクスにあまり慣れていない場合は、1.1.6 LEDドットマトリックス を参照してください。

  1. 必要なライブラリをインポートしてコードを開始します。「gpiozero」はボタンや出力デバイスなどのGPIOピンとのやり取りに使用されます。「time」は遅延を追加するため、「threading」は複数のタスクを同時に実行するため、「random」はプロジェクトでのランダム性を導入するのに役立ちます。

    #!/usr/bin/env python3
    from gpiozero import OutputDevice, Button
    import time
    import threading
    import random
    
  2. シフトレジスタ(「SDI」、「RCLK」、「SRCLK」)およびボタン(「AButtonPin」、「BButtonPin」)用のGPIOピンを初期化します。シフトレジスタは、少ないGPIOピンで複数のLEDを制御するために使用され、LEDマトリクス表示に不可欠です。

    # 74HC595シフトレジスタのGPIOピン
    SDI = OutputDevice(17)   # シリアルデータ入力
    RCLK = OutputDevice(18)  # レジスタクロック
    SRCLK = OutputDevice(27) # シフトレジスタクロック
    
    # ボタンのGPIOピン
    AButtonPin = Button(20)  # ボタンA
    BButtonPin = Button(26)  # ボタンB
    
  3. ゲームロジックに使用される変数、例えばタイマーやゲーム状態指標を初期化します。

    # ゲーム変数の初期化
    timerPlay = 0
    timerCheck = 0
    waypoint = "NULL"
    stage = "NULL"
    
  4. LEDマトリクスに表示する矢印とフィードバック(正解/誤り)のバイナリパターンを定義します。各配列要素はLEDマトリクスの行を表し、「1」と「0」はそれぞれLEDがオンまたはオフであることを示します。

    # LEDマトリクス表示の矢印グリフ
    arrow = {
        "right": [0xFF, 0xEF, 0xDF, 0x81, 0xDF, 0xEF, 0xFF, 0xFF],
        "left": [0xFF, 0xF7, 0xFB, 0x81, 0xFB, 0xF7, 0xFF, 0xFF]
    }
    
    # 正解/誤りのフィードバックグリフ
    check = {
        "wrong": [0xFF, 0xBB, 0xD7, 0xEF, 0xD7, 0xBB, 0xFF, 0xFF],
        "right": [0xFF, 0xFF, 0xF7, 0xEB, 0xDF, 0xBF, 0xFF, 0xFF]
    }
    
  5. この関数は1バイトのデータを74HC595シフトレジスタにシフトします。 dat バイトの各ビットに対して繰り返し処理を行い、 SDI ピンを高または低に設定し、 SRCLK ピンをトグルしてビットをレジスタにシフトします。

    def hc595_shift(dat):
        """ 74HC595シフトレジスタにデータをシフトします。 """
        for i in range(8):
            SDI.value = 0x80 & (dat << i)
            SRCLK.on()
            SRCLK.off()
    
  6. この関数はLEDマトリクスにグリフを表示します。 glyphCode で表されるグリフの各行とその行のアドレスを hc595_shift を使用してシフトレジスタに送信し、 RCLK ピンをトグルして表示を更新します。

    def display(glyphCode):
        """ LEDマトリクスにグリフを表示します。 """
        for i in range(0, 8):
            hc595_shift(glyphCode[i])
            hc595_shift(0x80 >> i)
            RCLK.on()
            RCLK.off()
    
  7. この関数はランダムに arrow 辞書からグリフを選択し、プレイタイマーを開始し、ゲームのステージを「PLAY」に設定します。ゲームでのタイミング制御には threading.Timer が使用されます。

    def creatGlyph():
        """ ゲームの新しいグリフを作成し、プレイタイマーを開始します。 """
        global waypoint, stage, timerPlay
        waypoint = random.choice(list(arrow.keys()))
        stage = "PLAY"
        timerPlay = threading.Timer(2.0, timeOut)
        timerPlay.start()
    
  8. この関数はプレイヤーの入力を現在のグリフと比較します。入力が正しい場合は、waypointを「right」に設定し、そうでない場合は「wrong」に設定します。次に現在のプレイタイマーをキャンセルし、次のグリフのための新しいタイマーを開始します。

    def checkPoint(inputKey):
        """ プレイヤーの入力をチェックし、ゲームの状態を更新します。 """
        global waypoint, stage, timerCheck
        if inputKey == "empty" or inputKey == waypoint:
            waypoint = "wrong"
        else:
            waypoint = "right"
        timerPlay.cancel()
        stage = "CHECK"
        timerCheck = threading.Timer(1.0, creatGlyph)
        timerCheck.start()
    
  9. この関数はゲームがタイムアウトしたときに呼び出されます。「empty」を引数として checkPoint を呼び出し、時間内にボタンが押されなかったことを示します。

    def timeOut():
        """ ゲームのタイムアウトシナリオを処理します。 """
        checkPoint("empty")
    
  10. この関数はボタンの状態を確認します。「AButtonPin」が押されていて「BButtonPin」が押されていない場合は、「right」として checkPoint を呼び出します。逆に「BButtonPin」が押されていて「AButtonPin」が押されていない場合は、「left」として checkPoint を呼び出します。

    def getKey():
        """ ボタン押下を検出し、チェックポイントをトリガーします。 """
        if AButtonPin.is_pressed and not BButtonPin.is_pressed:
            checkPoint("right")
        elif not AButtonPin.is_pressed and BButtonPin.is_pressed:
            checkPoint("left")
    
  11. main 関数はゲームの流れを制御します。グリフを作成して開始し、継続的にゲームのステージを確認します。"PLAY"ステージでは、現在のグリフを表示し、ボタン押下をチェックします。"CHECK"ステージでは、プレイヤーのアクションに基づいてフィードバックを表示します。

    def main():
        """ メインゲームループ。 """
        creatGlyph()
        while True:
            if stage == "PLAY":
                display(arrow[waypoint])
                getKey()
            elif stage == "CHECK":
                display(check[waypoint])
    
  12. この関数はプログラムが終了する際に実行中のタイマーをキャンセルし、クリーンなシャットダウンを保証します。

    def destroy():
        """ プログラム終了時にリソースをクリーンアップします。 """
        global timerPlay, timerCheck
        timerPlay.cancel()  # プレイタイマーをキャンセル
        timerCheck.cancel()  # チェックポイントタイマーをキャンセル
    
  13. ゲームは try ブロックで実行されます。 KeyboardInterrupt (Ctrl+Cを押すなど)が発生した場合、例外をキャッチし、 destroy を呼び出して終了前にクリーンアップします。

    # ゲームを実行し、キーボード割り込みでクリーンな終了を処理
    try:
        main()
    except KeyboardInterrupt:
        destroy()
    

Processingで遊ぶ (Pi 5用ではない)

Processingとは?

Processingは、アニメーションに重点を置いた視覚指向のアプリケーションの開発を容易にし、対話を通じてユーザーに即時のフィードバックを提供するために作成された単純なプログラミング環境です。 開発者は、コードでアイデアを「スケッチ」する手段を望んでいました。 その機能が過去10年間で拡大するにつれて、Processingは、スケッチの役割に加えて、より高度な本番レベルの作業に使用されるようになりました。 もともとアーティストやデザイナーを対象としたJavaのドメイン固有の拡張機能として構築されたProcessingは、大規模なインストール作業、モーショングラフィックス、複雑なデータの視覚化に使用される本格的なデザインおよびプロトタイピングツールに進化しました。

ProcessingはJavaに基づいていますが、Processingのプログラム要素は非常に単純であるため、Javaを知らなくても使用方法を学ぶことができます。 Javaに精通している場合は、APIがどのように機能するかを理解するまで、Processingはしばらくの間Javaと関係があることを忘れておくのが最善です。

このテキストは、チュートリアル Processing Overview からのものです。

Processingをインストールする

注釈

Processingを使用する前に、Raspberry Piデスクトップにリモートでアクセスするか( Raspberry Piの設定 ) 、RaspberryPiのディスプレイを接続する必要があります。

最初に https://processing.org/download にアクセスし、Linux ARM32-bit バージョンを選択します。

次に、ほとんどの Linux ユーザーになじみのある .tar.gz ファイルにダウンロードします。 ファイルをホーム ディレクトリにダウンロードし、ターミナル ウィンドウを開いて次のように入力します。

tar xvfz processing-xxxx.tgz

(xxxx をファイル名の残りの部分 (バージョン番号) に置き換えます。) これにより、processing-2.0 などの名前のフォルダーが作成されます。次に、そのディレクトリに移動します。

cd processing-xxxx

そしてそれを実行します:

./processing

運が良ければ、メインの Processing ウィンドウが表示されます。

_images/processing2.png

安装硬件 I/O

Raspberry Pi の GPIO を使用するには、 ハードウェア I/O ライブラリ を手動で追加する必要があります。

Sketch -> Import Library -> Add Library... をクリックします。

_images/import-00.png

ハードウェア I/O を見つけて選択し、[インストール] をクリックします。完了すると、チェックマーク アイコンが表示されます。

_images/import-02.png

プロジェクト

棒人間を描く

これで、Processing Development Environment(PDE)を実行しています。 それほど多くはありません。 広い領域はテキストエディタで、上部にボタンの列があります。 これがツールバーです。 エディタの下にはメッセージエリアがあり、その下にはコンソールがあります。 メッセージエリアは1行のメッセージに使用され、コンソールはより技術的な詳細に使用されます。

Processing を使って棒線画を描くことに慣れましょう。

スケッチ

以下のスケッチをProcessingにコピーして実行します。 新しい表示ウィンドウが表示され、応援の仲人が描かれます。

size(200,200);
background(92, 168, 0);
rectMode(CENTER);
rect(100,120,20,60);
ellipse(100,80,45,45);
line(90,150,80,170);
line(110,150,120,170);
line(90,110,70,100);
line(110,110,130,100);
_images/draw_one1.png

注釈

それを実行し、メッセージ領域が赤くなり、いくつかのエラーが報告された場合は、スケッチに問題があります。 サンプルスケッチを正確にコピーするようにしてください。数字は括弧で囲み、各数字の間にコンマを入れ、行はセミコロンで終了する必要があります。

原理

ここで重要なのは、表示ウィンドウを正方形の紙として扱うことができることを理解することです。

表示ウィンドウの各ピクセルは、空間内のポイントの位置を決定する座標(x、y)です。 座標の原点(0,0)は左上隅にあり、X軸の正の方向は水平方向に右、Y軸の正の方向は垂直方向に下向きです。

重要なのは、これらのピクセル座標にどのような形と色を表示するかを指定することです。

たとえば、座標(100,120)を中点として、幅20、高さ60の長方形を描画します。

rectMode(CENTER);
rect(100,120,20,60);
_images/draw_one_coodinate.png

表示ウィンドウと軸の関係を理解したら、このスケッチは難しくありません。いくつかの簡単なグラフィック描画ステートメントを理解する必要があります。

  • size(width, height): 表示ウィンドウの幅と高さの寸法をピクセル単位で定義します。

  • background(red, green, blue): 表示ウィンドウの背景色を設定します。

  • rectMode(mode): rect() に指定されたパラメーターの解釈方法を変更することにより、長方形が描画される場所を変更します。

  • rect(x, y, width, height): 画面に長方形を描画します。

  • ellipse(x, y, width, height): 画面に楕円(楕円)を描画します。

  • line(x1, y1, x2, y2): 画面に線(2点間の直接パス)を描画します。

詳細については、 Processing Reference を参照してください。

こんにちはマウス

このプロジェクトでは、マウスはポイントに向かって線を描き続けます。マウスを動かすと、ユニークな星の線が描画されます。マウスを押して、描画を再開します。

_images/hello_mouse1.png

スケッチ

int pointX = 172;
int pointY = 88;

void setup() {
    size(400, 400);
    stroke(255);
    background(192, 16, 18);
}

void draw() {
    line(pointX, pointY, mouseX, mouseY);
}

void mousePressed() {
    pointX=mouseX;
    pointY=mouseY;
    background(192, 16, 18);
}

原理

前のプロジェクトは、アニメーションやインタラクションなしで単一の画像を描画していました。

インタラクティブなスケッチを作成する場合は、 setup() 関数と draw() 関数(これらは自動的に呼び出される組み込み関数)を追加してフレームを作成する必要があります。

  • setup() : スケッチの開始時に1回だけ実行されます。

  • draw() :繰り返し実行されます。通常、アニメーションを描画するためのスケッチを追加します。

int pointX = 172;
int pointY = 88;

void setup() {
    size(400, 400);
    stroke(255);
    background(192, 16, 18);
}

void draw() {
    line(pointX, pointY, mouseX, mouseY);
}

上記のこのスケッチは、インタラクティブなスケッチとしてすでにスムーズに機能します。

次に、マウスクリックイベントを追加できます。 このイベントは、 mousePressed() 関数を使用して実装できます。この関数では、ステートメントを追加して、ターゲットポイントを更新し、画面をクリアします。

int pointX = 172;
int pointY = 88;

void setup() {
    size(400, 400);
    stroke(255);
    background(192, 16, 18);
}

void draw() {
    line(pointX, pointY, mouseX, mouseY);
}

void mousePressed() {
    pointX=mouseX;
    pointY=mouseY;
    background(192, 16, 18);
}

詳細については Processing Reference を参照してください。

クリック可能なドット

このプロジェクトでは、LEDと同期して点滅するProcessingにドットを描画します。図に示すように回路を構築し、スケッチを実行してください。

_images/clickable_dot_on.png

回路

_images/image491.png

スケッチ

import processing.io.*;
boolean state = false;
int ledPin = 17;

void setup() {
    GPIO.pinMode(ledPin, GPIO.OUTPUT);
    background(255);
}

void draw() {
    if (state == true) {
        GPIO.digitalWrite(ledPin, GPIO.LOW);
        fill(255, 0, 0);
    }else {
        GPIO.digitalWrite(ledPin, GPIO.HIGH);
        fill(155);
    }
    ellipse(width/2, height/2, width*0.75, height*0.75);
}

void mouseClicked() {
    //  toggles state:
    if (2*dist(mouseX,mouseY,width/2, height/2)<=width*0.75)
        {state = !state;}
}

原理

このプロジェクトには ドットの点滅 と多くの共通点がありますが、違いは、マウスイベントにトグル状態を設定することです。 これにより、LEDは自動的に点滅しませんが、マウスをクリックすると点灯および消灯します。

また、 mouseClicked() イベントでは、 dist() 関数を使用してクリック時のマウスの位置を決定します、マウスとドットの中心との距離が半径より小さい場合にのみ、ドットがクリックされたと見なされます。

詳細については、 Processing Reference を参照してください。

クリック可能なカラーブロック

クリック可能なドットを描画してLEDを制御しようとしたので、さらに一歩進んで3色の正方形を描画してRGBカラーを調整しましょう!

_images/colorful_square.png

回路

_images/image611.png

スケッチ

import processing.io.*; // use the GPIO library

int[] pins = { 17, 18, 27 };

void setup() {
    for (int i = 0; i < pins.length; i++) {
        GPIO.pinMode(pins[i], GPIO.OUTPUT);
    }
    size(300, 100);
    background(255);
}

void draw() {
    fill(255, 0, 0);
    rect(0, 0, width/3, height);

    fill(0,255,0);
    rect(width/3, 0, 2*width/3, height);

    fill(0,0,255);
    rect(2*width/3, 0, width, height);
}

void mouseClicked() {
    for (int i = 0; i < pins.length; i++) {
        GPIO.digitalWrite(pins[i],GPIO.LOW);
    }
    if (mouseX<width/3){
        GPIO.digitalWrite(pins[0],GPIO.HIGH);
    }else if (mouseX>width/3&&mouseX<2*width/3){
        GPIO.digitalWrite(pins[1],GPIO.HIGH);
    }else if (mouseX>2*width/3){
        GPIO.digitalWrite(pins[2],GPIO.HIGH);
    }
}

原理

このプロジェクトは、マウスクリックイベントを決定するための条件を改善することを除いて、 クリック可能なドット と多くの共通点があります。

最初に draw() で3つのカラーブロックを描画し、次にmouseX(マウスのX軸座標)の値に基づいてクリックされたカラーブロックを取得し、最後にRGBに対応する色を点灯させます。

それと?

光の追加に基づいて、RGBLEDディスプレイを7色にすることができます。緑に赤を追加すると黄色になります。 3つの原色すべてを足し合わせると白になります。 今、それを自分で試すことができます。

詳細については Processing Reference を参照してください。

ドットを膨らませる

次に、ボタンでドットのサイズを制御できる回路を作成しましょう。 ボタンを押すと、ドットがすぐに大きくなります。 ボタンを離すと、ドットが徐々に小さくなり、風船が膨らんでいるように見えます。

_images/dot_size.png

回路

_images/button_pressed.png

スケッチ

import processing.io.*;
int buttonPin = 18;

float diameter;

void setup() {
    size(200, 200);
    frameRate(64); //set frame rate
    GPIO.pinMode(buttonPin, GPIO.INPUT_PULLUP);
    diameter = width*0.5;
}

void draw() {
    if (GPIO.digitalRead(buttonPin)==GPIO.LOW) {
        if(diameter<width*0.8) {diameter=diameter+5;}
    } else {
        if(diameter>=width*0.2) {diameter--;}
    }
    background(192, 16, 18);
    ellipse(width/2, height/2,diameter, diameter);
}

原理

このプロジェクトは、GPIOの出力機能を使用していた前の2つのプロジェクトと比較して、入力機能を使用しています。

GPIO.pinMode() 関数は、 buttonPin をプルアップ入力モードに設定するために使用されます。これにより、ピンはデフォルト状態で自動的にHIGHになります。

次に、 GPIO.digitalRead() 関数を使用して buttonPin の値を読み取ります。 値がLOWの場合、ボタンが押されていることを意味します。その時点で、ドットの直径が5増加します。 ボタンを離すと、ドットの直径が1つ小さくなります。

詳細については、 Processing Reference を参照してください。

スイングのドット

このプロジェクトでは、ドットのサイズを変更するためのボタン、 位置を変更するためのボタン、色を変更するためのボタンの3つのボタンが接続されています。 3つのボタンすべてを同時に押すと、揺れるドットが表示され、色が変化します。

_images/dancing_dot.png

回路

_images/circuit_dancing_dot.png

スケッチ

import processing.io.*;

// Define an instance of the Dot object
Dot myDot;

// Define the pins that will be reading button presses
int[] pins = { 18, 23, 24 };

void setup() {
    size(400, 400);
    // Change the color mode of the sketch to HSB
    colorMode(HSB, 360, 100, 100);
    noStroke();

    for (int i = 0; i < pins.length; i++) {
        GPIO.pinMode(pins[i], GPIO.INPUT_PULLUP);
    }

    // Create a Dot in the middle of the screen
    myDot = new Dot(width / 2, height / 2, 100, 255);
}

void draw() {
    background(0);

    // Modify attributes of the Dot depending on which buttons are pressed
    if (GPIO.digitalRead(pins[0]) == GPIO.LOW) {myDot.setSize();}
    if (GPIO.digitalRead(pins[1]) == GPIO.LOW) {myDot.setPosition();}
    if (GPIO.digitalRead(pins[2]) == GPIO.LOW) {myDot.setColor();}

    // Update the Dot state
    myDot.update();
    // And draw it to the screen
    myDot.show();
}

class Dot {

    float initX;
    float initY;
    float currentX;
    float currentY;
    int positionRange = 60;

    float initSize;
    float currentSize;
    int sizeRange = 50;

    int initColor;
    int currentColor;
    int ColorRange = 80;

    float timer = 0.0;
    float speed = 0.06;

    Dot(float x, float y, float s, int c) {
        initX = x;
        initY = y;
        currentX = x;
        currentY = y;

        initSize = s;
        currentSize = s;

        initColor = c;
        currentColor = c;
    }

    void setSize() {
        currentSize = initSize + sizeRange * sin( timer );
    }

    void setPosition() {
        currentY = initY + positionRange * cos( timer *2);
    }

    void setColor() {
        currentColor = int(initColor + ColorRange * sin( timer ));
    }

    void update() {
        timer += speed;
    }

    void show() {
        fill(currentColor, 100, 100);
        ellipse(currentX, currentY, currentSize, currentSize);
    }
}

原理

ドットを直接描画する代わりに、ここで Dot クラスを作成します。 次に、オブジェクトを宣言します。(この場合は myDot

これは、複数の同一のプロパティを持つドットを描画する簡単な方法です。 たとえば、このプロジェクトのドットに3つの関数(サイズの変更、位置の変更、色の変更)を追加すると、宣言する各ドットは同じ関数になります。 同じボタンを使用して同じことを実行することも、異なるボタンを使用して各ドットを個別に制御することもできます。

Class (computer programming) - Wikipedia を使用すると、スケッチが美しく、強力で柔軟になります。

次に、 Dot クラスを詳しく見てみましょう。

Dot(float x, float y, float s, int c)

宣言では、位置のX座標値とY座標値、サイズ、および色(ここでは、 HSB color mode )に設定されています)の4つのパラメーターを渡す必要があります。

各パラメータは、2セットの値(初期値と現在の値)に割り当てられます。

float initX;
float initY;
float currentX;
float currentY;
int positionRange = 60;

float initSize;
float currentSize;
int sizeRange = 50;

int initColor;
int currentColor;
int ColorRange = 80;

初期値と現在の値に加えて、範囲値のセットもあります。 初期値がドットの初期状態(入力パラメータによって決定される)を決定するために使用され、現在の値が範囲内で変化してドットを移動させることを意味します。

したがって、X座標値を除いて、他の3つのパラメーターの現在の値は次のように計算されます:

void setSize() {
    currentSize = initSize + sizeRange * sin( timer );
}

void setPosition() {
    currentY = initY + positionRange * cos( timer *2);
}

void setColor() {
    currentColor = int(initColor + ColorRange * sin( timer ));
}

三角関数に精通している場合は、正弦と余弦 sine & cosine を理解するのは難しくありません。これにより、ドットの現在の値が滑らかに周期的に変化します(-1から1)。

また、周期的な変動のためにシード、 timer を追加する必要があります。 これは、メソッド update() に固定値を追加し、 draw() で呼び出されます。

void update() {
    timer += speed;
}

最後に、 draw() でも呼び出される show() メソッドを使用して、現在の値に従ってドットが表示されます。

void show() {
    fill(currentColor, 100, 100);
    ellipse(currentX, currentY, currentSize, currentSize);
}

それと?

クラスの使い方をマスターすれば、同じプロパティで複数のドットを描くことができるので、もっとクールなことをしてみませんか。 たとえば、安定した連星系を描いたり、'DUET'ゲームを作ったりするのはどうですか?

詳細については、 Processing Reference を参照してください。

メトロノーム

ここではメトロノームを作成します。 メトロノームは5つのレベルに分けられ、レベルが高いほどブザーの呼び出しが緊急になります。

_images/metronome.png

回路

_images/image1061.png

注釈

ここではアクティブブザーが使用されており、白いステッカーが貼られています。

スケッチ

import processing.io.*;

int level = 0;
int buzzerPin = 17;
int levelRange=5;
Slider mySlider;

void setup() {
    size(400, 200);
    frameRate(50);
    mySlider = new Slider(width * 0.2,height * 0.4,width * 0.8,height * 0.6,0,levelRange,level);
    GPIO.pinMode(buzzerPin, GPIO.OUTPUT);
}

void draw() {

    background(255);
    mySlider.show();
    if(level==0){
        GPIO.digitalWrite(buzzerPin, GPIO.HIGH);
    }else if((frameCount/5) % (levelRange-level+1) ==0){
        GPIO.digitalWrite(buzzerPin, GPIO.LOW);
    }else{
        GPIO.digitalWrite(buzzerPin, GPIO.HIGH);
    }
}

void mouseDragged(){
    level = mySlider.dragPoint(mouseX,mouseY);
}

class Slider{
    float slotPointAX;
    float slotPointBX;
    float slotPointAY;
    float slotPointBY;
    float linePoint;
    float depth;
    int maxRange;
    int minRange;
    int value;

    Slider(float ax, float ay, float bx, float by, int min, int max, int v){
        slotPointAX = ax;
        slotPointAY = ay;
        slotPointBX = bx;
        slotPointBY = by;
        maxRange = max;
        minRange = min;
        value = v;
        linePoint = slotPointAX;// + map(value, minRange, maxRange, slotPointAX, slotPointBX);
        depth = (slotPointBY - slotPointAY)*0.75;
    }

    void show(){
        rectMode(CORNERS);
        fill(200);
        stroke(255,0,0);
        rect(slotPointAX, slotPointAY, slotPointBX, slotPointBY);
        fill(255,0,0);
        rect(slotPointAX, slotPointAY, linePoint, slotPointBY);
        fill(200);
        textSize(depth);
        text(minRange, slotPointAX, slotPointBY+depth);
        text(maxRange, slotPointBX, slotPointBY+depth);
        text(value, linePoint, slotPointAY);
    }

    int dragPoint(float mx, float my){
        if(mx>=slotPointAX && mx<=slotPointBX && my>=slotPointAY && my<=slotPointBY){
            value = int(map(mx,slotPointAX,slotPointBX,minRange,maxRange));
            linePoint = map(value,minRange,maxRange,slotPointAX,slotPointBX);
        }
        return value;
    }
}

原理

ここでは、 Slider クラスを作成し、それを widget として機能させました。

Slider(ax, ay, bx, by, min, max, v)

宣言では、7つのパラメーターで渡す必要があります。

最初の4つのパラメーターはwidgetのサイズを決定し、その後に左上隅の開始点の座標(x1、y1)と右下隅の(x2、y2)が続きます。

最後の3つのパラメーターは、その数値範囲(最小から最大)と初期値を決定します。

これには2つのメソッドがあります。 dragPoint() の効果は、スライダーをドラッグ可能にして、スライダーの現在の位置の値を返すことです。

int dragPoint(float mx, float my){
    if(mx>=slotPointAX && mx<=slotPointBX && my>=slotPointAY && my<=slotPointBY){
        value = int(map(mx,slotPointAX,slotPointBX,minRange,maxRange));
        linePoint = map(value,minRange,maxRange,slotPointAX,slotPointBX);
    }
    return value;
}

別のメソッド show() は、スライダーを表示することです。 同時に、範囲値と現在値が対応する位置に表示されます。

void show(){
    rectMode(CORNERS);
    fill(200);
    stroke(255,0,0);
    rect(slotPointAX, slotPointAY, slotPointBX, slotPointBY);
    fill(255,0,0);
    rect(slotPointAX, slotPointAY, linePoint, slotPointBY);
    fill(200);
    textSize(depth);
    text(minRange, slotPointAX, slotPointBY+depth);
    text(maxRange, slotPointBX, slotPointBY+depth);
    text(value, linePoint, slotPointAY);
}

詳細については、 Processing Reference を参照してください。

番号を表示

このレッスンでは、processingを使用して7セグメントディスプレイを駆動し、0から9およびAからFの数値を表示します

回路

_images/image1251.png

スケッチ

import processing.io.*;

int SDI=17;   //serial data input
int RCLK=18;  //memory clock input(STCP)
int SRCLK =27;   //shift register clock input(SHCP)


int[] SegCode= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void hc595_shift(int dat){
  int i;

  for(i=0;i<8;i++){
        int n=(0x80 & (dat << i));
        if ( n==0){
          GPIO.digitalWrite(SDI, 0);
        } else {
          GPIO.digitalWrite(SDI, 1);
        }
        GPIO.digitalWrite(SRCLK, 1);
        delay(1);
        GPIO.digitalWrite(SRCLK, 0);
  }

        GPIO.digitalWrite(RCLK, 1);
        delay(1);
        GPIO.digitalWrite(RCLK, 0);
}

void setup() {
        size(400, 200);
        frameRate(10);

        GPIO.pinMode(SDI, GPIO.OUTPUT);
        GPIO.pinMode(RCLK, GPIO.OUTPUT);
        GPIO.pinMode(SRCLK, GPIO.OUTPUT);

        GPIO.digitalWrite(SDI, 0);
        GPIO.digitalWrite(RCLK, 0);
        GPIO.digitalWrite(SRCLK, 0);

        fill(0,25,88);
        textAlign(CENTER,CENTER);
        textSize(height*0.8);
}

void draw() {

        background(255);
        int number = (frameCount%100)/10;
        text(number, width/2, height/2);
        hc595_shift(SegCode[number]);
}

原理

processing.io.* をインポートし、GPIO関数ライブラリを使用してdigital tube pinsを制御します。

配列を定義する SegCode = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71} 16進数中で、0からFまでのセグメントコード配列を表す(共通カソード)

setup() 関数は、3つのピンSDI、RCLK、SRCLKを出力として設定し、初期データを0として設定します。

hc595_shift(int dat) 関数は、 SegCode を74HC595にシフトするために使用されます。

void hc595_shift(int dat){
  int i;

  for(i=0;i<8;i++){
        int n=(0x80 & (dat << i));
        if ( n==0){
          GPIO.digitalWrite(SDI, 0);
        } else {
          GPIO.digitalWrite(SDI, 1);
        }
        GPIO.digitalWrite(SRCLK, 1);
        delay(1);
        GPIO.digitalWrite(SRCLK, 0);
  }

        GPIO.digitalWrite(RCLK, 1);
        delay(1);
        GPIO.digitalWrite(RCLK, 0);
}

n=(0x80 & (dat << i)) は、 dati ビット左にシフトしてから、0x80と & 操作を実行することを意味します。

& 演算のルールは、 & の両側が1の場合、結果は1であり、それ以外の場合、結果は0です。

たとえば、 dat=0x3f,i=2 ( 0011 1111 << 2 shift to 1111 1100 ) , then 1111 1100 & 1000 0000 (0x80) = 1000 0000

最後に、 dat データをビット単位でSDI(DS)に割り当てます。

digitalWrite(SRCLK, 1) SRCLKが0から1までの立ち上がりエッジパルスを生成すると、データはDSレジスタからシフトレジスタに転送されます。

digitalWrite(RCLK, 1) RCLKが0から1までの立ち上がりエッジパルスを生成すると、データはシフトレジスタからストレージレジスタに転送されます。

fill(0,25,88);
textAlign(CENTER,CENTER);
textSize(height*0.8);
  • fill(): 図形の塗りつぶしに使用する色を設定します。

  • textAlign(CENTER,CENTER): テキストを描画するための現在の配置を設定します。 パラメータ LEFTCENTER 、および RIGHT は、 text() 関数のxおよびyパラメータの値に関連して文字の表示特性を設定します。

  • textSize(): 現在のフォントサイズを設定します。 このサイズは、以降の text() 関数のすべての呼び出しで使用されます。 フォントサイズはピクセル単位で測定されます。

これらの関数は、processingで表示されるテキストスタイルをカスタマイズできます。

void draw() {

        background(255);
        int number = (frameCount%100)/10;
        text(number, width/2, height/2);
        hc595_shift(SegCode[number]);
}

frameCount はシードであり、 frameRate に関連しています。 デフォルトでは、 frameRate は60です。これは、 frameCount が1秒間に60回累積することを意味します。

次に、processingと7セグメントディスプレイを使用して、0から9までの数字とAからFまでの数字を同時に表示できます。

詳細については Processing Reference を参照してください。

ドラッグ番号

7セグメントディスプレイを制御するためのスライダーバーを描いてみましょう。

_images/drag_servo.png

回路

_images/image1251.png

スケッチ

import processing.io.*;

int number = 0;
int levelRange=9;
Slider mySlider;

int SDI=17;   //serial data input
int RCLK=18;  //memory clock input(STCP)
int SRCLK =27;   //shift register clock input(SHCP)


int[] SegCode= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void hc595_shift(int dat){
int i;

for(i=0;i<8;i++){
    int n=(0x80 & (dat << i));
    if ( n==0){
    GPIO.digitalWrite(SDI, 0);
    } else {
    GPIO.digitalWrite(SDI, 1);
    }
    GPIO.digitalWrite(SRCLK, 1);
    delay(1);
    GPIO.digitalWrite(SRCLK, 0);
}

    GPIO.digitalWrite(RCLK, 1);
    delay(1);
    GPIO.digitalWrite(RCLK, 0);
}

void setup() {
    size(400, 200);
    frameRate(50);
    mySlider = new Slider(width * 0.2,height * 0.4,width * 0.8,height * 0.6,0,levelRange,number);
    GPIO.pinMode(SDI, GPIO.OUTPUT);
    GPIO.pinMode(RCLK, GPIO.OUTPUT);
    GPIO.pinMode(SRCLK, GPIO.OUTPUT);

    GPIO.digitalWrite(SDI, 0);
    GPIO.digitalWrite(RCLK, 0);
    GPIO.digitalWrite(SRCLK, 0);
}

void draw() {

    background(255);
    mySlider.show();
    hc595_shift(SegCode[number]);
}

void mouseDragged(){
    number = mySlider.dragPoint(mouseX,mouseY);
}



class Slider{
    float slotPointAX;
    float slotPointBX;
    float slotPointAY;
    float slotPointBY;
    float linePoint;
    float depth;
    int maxRange;
    int minRange;
    int value;

    Slider(float ax, float ay, float bx, float by, int min, int max, int v){
        slotPointAX = ax;
        slotPointAY = ay;
        slotPointBX = bx;
        slotPointBY = by;
        maxRange = max;
        minRange = min;
        value = v;
        linePoint = slotPointAX;// + map(value, minRange, maxRange, slotPointAX, slotPointBX);
        depth = (slotPointBY - slotPointAY)*0.75;
    }

    void show(){
        rectMode(CORNERS);
        fill(200);
        stroke(255,0,0);
        rect(slotPointAX, slotPointAY, slotPointBX, slotPointBY);
        fill(255,0,0);
        rect(slotPointAX, slotPointAY, linePoint, slotPointBY);
        fill(200);
        textSize(depth);
        text(minRange, slotPointAX, slotPointBY+depth);
        text(maxRange, slotPointBX, slotPointBY+depth);
        text(value, linePoint, slotPointAY);
    }

    int dragPoint(float mx, float my){
        if(mx>=slotPointAX && mx<=slotPointBX && my>=slotPointAY && my<=slotPointBY){
            value = int(map(mx,slotPointAX,slotPointBX,minRange,maxRange));
            linePoint = map(value,minRange,maxRange,slotPointAX,slotPointBX);
        }
        return value;
    }
}

原理

このプロジェクトは、前のコースの「スライダー」と「7セグメントディスプレイ」を統合します。 具体的な知識のポイントについては、 番号を表示 および メトロノーム を参照してください。

Scratch で遊ぶ (Pi 5用ではない)

Scratchは、コーディングの教育ツールとして主に8〜16歳の子供を対象としたブロックベースのビジュアルプログラミング言語およびWebサイトです。 サイトのユーザーは、ブロックのようなインターフェイスを使用してWeb上にプロジェクトを作成できます。 このサービスはMITメディアラボによって開発され、70以上の言語に翻訳されており、世界のほとんどの地域で使用されています。

ここでは、RaspberryPiでScratch3を使用し、オンラインScratchでは不可能なScratchでRaspberry Pi GPIOにアクセスする方法を学習します。

Scratchに関するクイックガイド

注釈

Scratch 3でプログラミングする場合、より良いエクスペリエンスのために画面が必要になる場合があります。 もちろん、画面がない場合は、リモートで Raspberry Pi デスクトップにアクセスすることもできます。詳細なチュートリアルについては、 Raspberry Piの設定 を参照してください。

さらに、Scratch3を実行するには少なくとも1GBのRAMが必要です。 少なくとも2GBのRAMを搭載したRaspberry Pi 4をお勧めします。 Scratch3はRaspberry Pi 2、3、3B +、または1GBRAMのRaspberry 4で実行できますが、これらのモデルのパフォーマンスは低になります。 その同時に、実行する他のソフトウェアの影響を受けて、メモリ不足が起こり、Scratch3が起動しない場合があります。

Scratch3をインストールする

Raspberry pi OSのインストール ときは、デスクトップ付きのバージョンを選択する必要があります。 デスクトップのみ、またはデスクトップと推奨ソフトウェア付きのも問題ありません。

推奨ソフトウェアを使用してバージョンをインストールすると、 Programming のシステムメニューにScratch 3が表示されます。

デスクトップのみのバージョンをインストールした場合は、以下に説明するように、Scratchを手動でインストールする必要があります。

メニューを開き、 Preferences -> Recommended Software をクリックします。

_images/quick_scratch1.png

Scratch 3を見つけて確認し、 Apply をクリックして、最後にインストールが完了するのを待ちます。

_images/quick_scratch2.png

インストールが完了すると、システムメニューの Programming に表示されます。

_images/quick_scratch3.png
Scratch3のインターフェースについて

Scratch 3は、楽しく、教育的で、簡単に習得できるように設計されています。 ブロックベースのプログラミングを使用して、インタラクティブなストーリー、ゲーム、アート、 シミュレーションなどを作成するためのツールがあります。 Scratchには、独自のペイントエディタとサウンドエディタも組み込まれています。

スクラッチ3の上部にはいくつかの基本的なオプションがあり、左から右への最初のオプションは言語オプションです。 プログラミング用にさまざまな言語を選択できます。 2つ目は File オプションです。 このオプションを使用すると、新しいファイルを作成したり、ローカルファイルを読み取ったり、現在のファイルを保存したりできます。 3つ目は、Edit オプションです。これを使用すると、一部の削除操作を再開して、加速モード(spritesの動きが特に速くなる)を有効にできます。 4つ目は、Tutorials オプションです。これを使用すると、一部のプロジェクトのチュートリアルを表示できます。 5つ目は、プロジェクトの名前を変更できるファイル名付けオプションです。

_images/quick_scratch13.png

コード

ステージ領域、ブロックパレット、コーディング領域の3つの主要なセクションがあります。 ブロックパレットのブロックをクリックしてコーディング領域にドラッグすることによるプログラミング。 最後に、プログラミング結果がステージ領域に表示されます。

_images/quick_scratch4.png

これがScratch3のsprites areaです。 この領域の上にspritesの基本パラメータがあり、Scratch 3に付属のspritesを追加したり、 ローカルspritesをアップロードしたりできます。

_images/quick_scratch5.png

これがScratch3のbackdrop areaです。 主にステージに適したbackdropを追加するために、 Scratch 3に付属のbackdropを追加するか、 ローカルのものをアップロードできます。

_images/quick_scratch6.png

これは Add Extension ボタンです。

_images/quick_scratch7.png

Scratch 3では、あらゆる種類の便利な拡張機能を追加できます。 ここでは、 Video Sensing を例として取り上げ、それをクリックします。

_images/quick_scratch8.png

block paletteに表示され、この拡張機能に関連付けられている機能を使用できます。 カメラを接続している場合は、stage areaにカメラ画面が表示されます。

_images/quick_scratch9.png

コスチューム

左上隅の Costumes オプションをクリックして、costumes paletteに入ります。 costumesが異なれば、spritesの静的な動きも異なります。これらの静的な動きをつなぎ合わせると、一貫した動的な動きが形成されます。

_images/quick_scratch10.png

音声

実験をより面白くするために、いくつかの音楽クリップを使用する必要があるかもしれません。 左上隅の Sounds オプションをクリックすると、現在のサウンドを編集したり、新しいサウンドを選択/アップロードしたりできます。

_images/quick_scratch11.png

プロジェクト

この章では、Scratch3から18のプロジェクトで遊んでいきます。

Scratch 3を使用したばかりのユーザーの場合は、Scratch 3をすぐに使い始めることができるように、プロジェクトを順番に試すことをお勧めします。

注釈

プロジェクトを試す前に、関連する資料とコードファイルをダウンロードしておく必要があります。 ターミナルを開き、次のコマンドを入力してgithubからダウンロードします。

git clone https://github.com/sunfounder/davinci-kit-for-raspberry-pi.git
1.1 魔法の杖

今日は、LED、Raspberry Pi、Scratchを使って楽しいゲームを作ります。 魔法の杖を振ると、LEDが点滅します。

_images/1.1_header.png
必要な部品
_images/1.1_list.png
回路を構築する
_images/1.1_image49.png
GPIO拡張機能を追加する

左下隅にある Add Extension ボタンをクリックしてから、すべてのScratchプロジェクトに使用する拡張機能である Raspberry Pi GPIO を追加します。

_images/1.1_scratchled1.png _images/1.1_scratchled2.png _images/1.1_scratchled3.png
コードをロードして、何が起こるかを確認します

コンピューター( home/pi/davinci-kit-for-raspberry-pi/scratch/code )からScratch3にコードファイルをロードします。

_images/1.1_scratch_step1.png _images/1.1_scratch_step2.png

stage areaの魔法の杖をクリックすると、LEDが2秒間点滅します。

_images/1.1_step3.png
Spriteに関するヒント

Upload Sprite をクリックします。

_images/1.1_upload_sprite.png

Wand.pnghome/pi/davinci-kit-for-raspberry-pi/scratch/picture パスからScratch3にアップロードします。

_images/1.1_upload.png

最後に、 Sprite1 を削除します。

_images/1.1_delete.png
コードに関するヒント
_images/1.1_LED1.png

これは、ステージ上の緑色の旗をクリックすることをトリガー条件とするイベントブロックです。 すべてのコードの先頭にトリガーイベントが必要です。block palette の Events カテゴリで他のトリガーイベントを選択できます。

_images/1.1_events.png

たとえば、トリガーイベントをspriteのクリックに変更できるようになりました。

_images/1.1_LED2.png

これは、設定されたサイクル数のブロックです。 数字の10を入力すると、ブロック内のイベントが10回実行されます。

_images/1.1_LED4.png

このブロックは、プログラムを秒単位で一時停止するために使用されます。

_images/1.1_LED3.png

ScratchではBCMの命名方法が使用されているため、このコードはGPIO17(BCM17)を0V(低レベル)に設定しています。 LEDのカソードがGPIO17に接続されているため、LEDが点灯します。 逆に、GPIO(BCM17)を高く設定すると、LEDが消灯します。

1.2 五色の玉

stage areaの異なる色のボールをクリックすると、RGBLEDが異なる色で点灯します

_images/1.2_header.png
必要な部品
_images/1.2_list.png
回路を構築する
_images/1.2_image61.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.2_colorful_balls.sb3 )をScratch 3にロードした後、対応するボールをクリックすると、RGB LEDがそれぞれ黄色、青、赤、緑、または紫に点灯します。

Spriteに関するヒント

デフォルトのspriteを削除してから、 Ball spriteを選択します。

_images/1.2_ball.png

そしてそれを5回複製します。

_images/1.2_duplicate_ball.png

これらの5つの Ball spriteに異なる costumes を選択し、対応する位置に移動します。

_images/1.2_rgb1.png
コードに関するヒント

コードを理解する前に、 RGB color model

RGBカラーモデルは、赤、緑、青の光をさまざまな方法で足し合わせて、さまざまな色を再現する加法色モデルです。

加法混色:緑に赤を加えると黄色になります。 青に緑を加えるとシアンになります。 赤に青を加えるとマゼンタになります。 3つの原色すべてを足し合わせると白になります。

_images/1.2_rgb_addition.png

RGB LEDは、3つのLED(赤色LED、緑色LED、青色LED)を1つのパッケージに組み合わせたもので、 これら3つの色を組み合わせることでほぼすべての色を生成できます。 4つのピンがあり、そのうちの1つはGNDで、他の3つのピンはそれぞれ3つのLEDを制御します。

したがって、RGBLEDを明るい黄色にするコードは次のとおりです。

_images/1.2_rgb3.png

Ball sprite(黄色のボール)をクリックすると、GPIO17が高(赤のLEDがオン)、GPIO18が高(緑のLEDがオン)、GPIO27が低(青のLEDがオフ)に設定され、RGBLEDが黄色に点灯するように設定します。

同じ方法で他のspriteにコードを書き込んで、RGB LEDを対応する色で点灯させることができます。

1.3 不倒翁

In this project, we will make a tilt switch controlled tumbler toy.

_images/1.3_header.png
必要な部品
_images/1.3_component.png
回路を構築する
_images/1.3_fritzing.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.3_tumbler.sb3 )をScratch3にロードします。

チルトスイッチを直立させると、タンブラーは立ったままになります。 傾けるとタンブラーも落ちます。 再び直立させると、タンブラーが再び立ち上がります。

Spriteに関するヒント

Sprite1を選択し、左上隅の Costumes をクリックします。 Upload Costume ボタンを使用して、 home/pi/davinci-kit-for-raspberry-pi/scratch/picture パスから tumbler1.pngtumbler2.png をアップロードします。 デフォルトの2つのcostumesを削除し、 spriteの名前を tumbler に変更します。

コードに関するヒント
_images/1.3_title2.png

緑の旗をクリックすると、GPIO17の初期状態がlowに設定されます。

_images/1.3_title4.png

pin17が低い場合(チルトスイッチが直立している場合)、tumbler sprite の costume を tumbler1(直立状態)に切り替えます。

_images/1.3_title3.png

pin17がハイ(チルトスイッチが傾いている)のとき、tumbler sprite の costume を tumbler2(チルト状態)に切り替えます。

1.4 兎

今日は、Button、Raspberry Pi、Scratchを使用して、さまざまな変更を加えたウサギを作成します。

最初のボタンを押すと、stage areaのうさぎの体色が変わります。 2番目のボタンを押すと、うさぎは体のサイズを変更します。 3番目のボタンを押すと、うさぎは一歩前進します。

_images/1.4_header.png
必要な部品
_images/1.4_list.png
回路を構築する
_images/1.4_scratch_button.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.4_hare.sb3 )をScratch3にロードします。

これで、3つのボタンをそれぞれ押して、ステージ上のうさぎがどのように変化するかを確認できます。

Spriteに関するヒント

sprite areaの右下隅にある Choose a Sprite ボタンをクリックし、検索ボックスに Hare と入力して、クリックして追加します。

_images/1.4_button1.png

Sprite1を削除します。

_images/1.4_button2.png
コードに関するヒント
_images/1.4_button3.png

これは、GPIO17のレベルが高いときにトリガーされるイベントブロックです。つまり、その瞬間にボタンが押されます。

_images/1.4_button4.png

これは Hare の色を変更するためのブロックです。値の範囲は0〜199で、199を超えると再び0から変更されます。

_images/1.4_button5.png

これは、spriteのサイズを変更するために使用されるブロックです。値が大きいほど、spriteは大きくなります。

注釈

spriteも無限に大きくはなく、その最大サイズは元の画像サイズに関連しています。

_images/1.4_button6.png

これはスプライトコスチュームを切り替えるブロックであり、Hare のコスチュームが切り替わり続けると、一連の一貫したアクションを実行します。 たとえば、このプロジェクトでは、Hare に一歩前進させます。

1.5 梟を起こす

今日はフクロウを起こすゲームをします。

誰かがPIRセンサーモジュールに近づくと、フクロウは眠りから目覚めます。

PIR モジュールには 2 つのポテンショメータがあり、 1 つは感度を調整するためのもので、もう 1 つは検出距離を調整するためのものです。 PIR モジュールがうまく機能するためには、両方を完全に反時計回りに回す必要があります。

_images/1.5_header.png
必要な部品
_images/1.5_component.png
回路を構築する
_images/1.5_fritzing.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.5_wake_up_the_owl.sb3 ) をScratch3にロードします。

PIRセンサーモジュールに近づくと、stage areaのフクロウが羽を開いて目を覚ますのがわかります。離れると、フクロウは再び眠りに戻ります。

Spriteに関するヒント

Sprite1を選択し、左上隅にある コスチューム をクリックします。 owl1.png と owl2.png を、[コスチュームのアップロード]ボタンを介して home/pi/davinci-kit-for-raspberry-pi/scratch/picture パスからアップロードします。 デフォルトの2つのコスチュームを削除し、スプライトの名前を owl に変更します。

_images/1.5_pir1.png
コードに関するヒント
_images/1.3_title2.png

緑の旗をクリックすると、GPIO17の初期状態がlowに設定されます。

_images/1.5_owl1.png

pin17が低い(誰も近づいていない)場合は、フクロウのSpriteのcostumeをowl1(sleeping状態)に切り替えます。

_images/1.5_owl2.png

pin17が高い(誰かが近づいている)とき、フクロウのSpriteのcostumeをowl2(wake up状態)に切り替えます。

1.6 光が流れるLED

今日はLED Bargraph、Raspberry Pi、Scratchを使ってストリーマーLEDを作ります。

LED棒グラフがstage上の矢印の方向に合わせて点灯します。

_images/1.12_header.png
必要な部品
_images/1.12_list.png
回路を構築する
_images/1.12_image66.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.6_water_lamp.sb3 )をコンピューターからScratch3にロードします。

Arrow1 をクリックすると、LEDバーのLEDが左から右に(一度に1つずつ)順番に点灯し、その後消灯します。 Arrow2 をクリックすると、LEDが逆の順序で点灯します。

Spriteに関するヒント

デフォルトのspriteを削除し、Arrow1 spriteを選択します。

_images/1.12_graph1.png

ここでは、2つの Arrow1 spriteが必要です。これは、複製ボタンを利用し完成できます。

_images/1.12_scratch_duplicate.png

Arrow 2 のSpriteをクリックし、costume2を選択して矢印の方向を変更します。

_images/1.12_graph2.png

それでは、変数を作成しましょう。

_images/1.12_graph3.png

num という名前を付けます。

_images/1.12_graph4.png

同じ方法に従って、 led というリストを作成します。

_images/1.12_graph6.png

追加すると、stage areaに num 変数と led リストが表示されます。

+ をクリックして 10 個のリスト項目を追加し、ピン番号を順番に入力します (17、18、27、22、23、24、25、2、3、8)。

_images/1.12_graph7.png
コードに関するヒント
_images/1.12_graph10.png

これは、現在のspriteがクリックされたときにトリガーされるイベントブロックです。

_images/1.12_graph8.png

num 変数の初期値は、どの LED が最初にオンになるかを決定します。

_images/1.12_graph9.png

LEDリストの num に対応するピンをlowに設定してLEDを点灯させ、 次に num-1 に対応するピンをhighに設定して前のLEDをオフにします。

1.7 ドアベル

今日はドアベルを作り、ステージ上のbutton3 spriteをクリックすると、ブザーが鳴ります。 もう一度クリックすると、ブザーが鳴り止みます。

_images/1.13_header.png
必要な部品
_images/1.13_list.png
回路を構築する
_images/1.13_image106.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.7_doorbell.sb3 )をScratch3にロードします。

ステージ上の緑色の旗をクリックします。 ボタン3のspriteをクリックすると、青色に変わり、ブザーが鳴ります。 もう一度クリックすると、Button3 スプライトが灰色に戻り、ブザーが鳴り止みます。

Spriteに関するヒント

デフォルトのspriteを削除してから、Button 3 のspriteを選択します。

_images/1.13_scratch_button3.png

次に、サイズを200に設定します。

_images/1.13_scratch_button3_size.png
コードに関するヒント
_images/1.13_buzzer4.png

このブロックを使用すると、spriteのcostumeを切り替えることができます。

_images/1.13_buzzer5.png

gpio17をlowに設定して、ブザーを鳴らします。 high 設定するとブザーが鳴りません。

ここでは status スイッチを使用します。ここでは、コード全体を理解するのに役立つflowchartを使用します。

緑のフラグがクリックされると、status が最初に0に設定され、この時点でspriteがクリックされるのを待ちます。 button3 spriteをクリックすると、button-b costume(青)としてcostumeに切り替わり、status が1に設定されます。 メインプログラムが status を受信すると 1として、0.1秒間隔でブザーを鳴らします。 button3 をもう一度クリックすると、button-a costume(灰色)に切り替わり、status が再び0に設定されます。

_images/1.13_scratch_code.png
1.8 だるまさんがころんだ

今日はだるまさんがころんだのゲームをします。

緑の旗をクリックしてゲームを開始し、キーボードの右矢印キーを押したままにしてspriteを右に動かします。 緑色のライトが点灯している場合、スプライトは移動できます。 ただし、赤いLEDが点灯している場合は、スプライトの移動を停止する必要があります。 そうしないと、ブザーが鳴り続けます。

_images/1.14_header.png
必要な部品
_images/1.14_component.png
回路を構築する
_images/1.14_fritzing.png
コードをロードして、何が起こるかを確認します

コードをロードして、何が起こるかを確認します コードファイル( 1.8_123_wooden_man.sb3 )をScratch3にロードします。

緑色のLEDが点灯している場合は、右矢印キーを使用して Avery を制御して右に歩くことができます。 赤いLEDが点灯しているときに、Avery を右に動かし続けると、アラームが鳴ります。

Spriteのヒント

デフォルトのSpriteを削除してから、Avery Walking spriteを選択します。

_images/1.14_wooden1.png
コードに関するヒント
_images/1.14_wooden2.png

すべてのピンをHighに初期化します。

_images/1.14_wooden3.png

ゲームが開始したら、ステータス変数を1に割り当てて、Avery Walking spriteが移動可能であることを示します。次に、GPIO18を低に設定します。これにより、緑色のLEDが5秒間点灯します。

_images/1.14_wooden4.png

GPIO18を高に設定してから、GPIO27を低に設定します。これは、緑色のLEDをオフにし、黄色のLEDを0.5秒間点灯させることを意味します。

_images/1.14_wooden5.png

ステータス変数を0に割り当てます。これは、Avery Walking spriteが移動していないことを意味します。 次に、GPIO27をlowに設定し、GPIO17をhighに設定します。これにより、黄色のLEDがオフになり、次に赤色のLEDが3秒間点灯します。 最後に、GPIO17をhighに設定して、赤いLEDをオフにします。

_images/1.14_wooden6.png

キーボードのright arrowキーを押すと、Averyが右に歩いているのが見えるように、Avery Walking spriteを次のcostumeに切り替える必要があります。 次に、status 変数の値を決定する必要があります。 0の場合は、現時点でAvery Walking spriteが動いていないことを意味し、right arrowキーを再度押すことができないことを警告するブザーが鳴ります。

1.9 風船を膨らませる

ここでは、バルーニングのゲームをします。

スライドを左に切り替えてバルーンを膨らませ始めると、この時点でバルーンはどんどん大きくなります。 風船が大きすぎると爆発します。 気球が小さすぎると空中に浮きません。 ポンプを停止するには、スイッチを右に切り替えるタイミングを判断する必要があります。

_images/1.15_header.png
必要な部品
_images/1.15_component.png
回路を構築する
_images/1.15_scratch_fritzing.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.9_inflating_the_balloon.sb3 )をScratch3にロードします。

スライダーを左に切り替えてバルーンを膨らませ始めると、この時点でバルーンはどんどん大きくなります。 風船が大きすぎると爆発します。 気球が小さすぎると空中に浮きません。 ポンプを停止するには、スイッチを右に切り替えるタイミングを判断する必要があります。

Spriteに関するヒント

前のSprite1 spriteを削除してから、Balloon1 spriteを追加します。

_images/1.15_slide1.png

このプロジェクトでは風船爆発効果音を使用しているので、どのように追加されたか見てみましょう。

上部の Sound オプションをクリックし、Upload Sound をクリックして、 boom.wavhome/pi/davinci-kit-for-raspberry-pi/scratch/sound パスからScratch3にアップロードします。

_images/1.15_slide2.png
コードに関するヒント
_images/1.15_slide3.png

これはイベントブロックであり、トリガー条件はGPIO17がハイである、つまりスイッチが左に切り替えられることです。

_images/1.15_slide4.png

Ballon1 spriteのサイズしきい値を120に設定します。

_images/1.15_slide7.png

Balloon1 spriteの座標を、stage areaの中心である(0,0)に移動します。

_images/1.15_slide8.png

Balloon1 spriteのサイズを50に設定し、stage areaに表示します。

_images/1.15_slide5.png

バルーンを膨らませるループを設定します。このループは、スライダースイッチを右に切り替えると停止します。

このループ内で、バルーンサイズは0.1秒ごとに1ずつ増加し、 maxSize より大きい場合はバルーンが破裂し、その時点でブーム音が鳴り、コードが終了します。

_images/1.15_slide6.png

最後のループが終了した後(スライダーが右に切り替わります)、サイズに基づいてBalloon1 spriteの位置を決定します。 Balloon1 spriteのサイズが90より大きい場合は、持ち上げて(座標を(0,90)に移動します)、 そうでない場合は着陸します(座標を(0,-149)に移動します)。

1.10 回転扇

このプロジェクトでは、回転する星のspriteとファンを作成します。

_images/1.17_header.png
必要な部品
_images/1.17_list.png
回路を構築する
_images/1.17_image117.png
コードをロードして、何が起こるかを確認します

コードファイル( 1.10_rotating_fan.sb3 )をScratch3にロードします。

ステージ上の緑色の旗をクリックした後、star spriteをクリックすると、それとモーターが時計回りに回転します。 2つの arrow spritesをクリックすると、回転方向を変更できます。 star spriteをもう一度クリックすると、star spriteとモーターの回転が停止します。

Spriteに関するヒント

デフォルトのspriteを削除してから、Star spriteと Arrow1 spriteを選択し、Arrow1を1回コピーします。

_images/1.17_motor1.png

Costumes オプションで、Arrow2 spriteを別の方向のcostumeに変更します。

_images/1.17_motor2.png

spriteのサイズと位置を適切に調整します。

_images/1.17_motor3.png
コードに関するヒント

流れ図

_images/1.17_scratch.png

このコードでは、カスタムブロック(関数)である2つのピンクのブロックが左に曲がって右に曲がっています。

_images/1.17_new_block.png

ブロックを作る方法は?

ブロック(関数)の作り方を学びましょう。 ブロック(関数)は、プログラムを単純化するために使用できます。特に同じ操作を複数回実行する場合です。 これらの操作を新しく宣言されたブロックに入れると、非常に便利です。

最初にblock paletteで My Blocks を見つけてから、Make a Block を選択します。

_images/1.17_motor4.png

新しいブロックの名前を入力します。

_images/1.17_motor5.png

coding areaに新しいブロックの機能を書き込んだ後、それを保存すると、blocks paletteでブロックを見つけることができます。

_images/1.17_motor6.png

turn left

これは、モーターを反時計回りに回転させるための左折ブロック内のコードです。

_images/1.17_motor12.png

turn right

これは、モーターを時計回りに回転させるための右折ブロック内のコードです。

_images/1.17_motor11.png

他言語(Pi 5用)

Raspberry Pi 5のリリースにより、より強力なモデルが私たちにもたらされましたが、GPIOに最も顕著な変更が導入されました。

標準の40ピンインターフェースは保持されていますが、新しく統合されたRP1サウスブリッジチップとの接続により機能が変更されました。このカスタムRP1チップは現在、Pi 5上の周辺機器を処理し、さまざまな互換性の懸念が生じています。

C言語

C言語の実装は、wiringPiライブラリに依存しています。しかし、wiringPiコミュニティライブラリは現在アーカイブされており、更新が行われなくなり、Raspberry Pi 5プロジェクトには不適切です。詳細については、以下を参照してください:https://github.com/WiringPi/WiringPi

_images/pi5_c_language.png

Processing

Raspberry Pi 5でProcessing 4を使用する際、GPIOプログラミングには課題が伴います。"Invalid argument"や"GPIO pin 17 seems to be unavailable on your platform"などのエラーがGPIO関連のコードの実行中に発生します(添付画像で示されているように)。詳細については、こちらをご覧ください:https://github.com/benfry/processing4/issues/807

_images/pi5_processing.png

Node.js

Node.jsは、現時点でRaspberry Pi 5をサポートしていないpigpioライブラリを使用します。さらなる洞察については、こちらを訪れてください:https://github.com/joan2937/pigpio/issues/589

_images/pi5_nodejs.png

Scratch

64ビットシステムでは、Raspberry Pi GPIOライブラリのインポートに問題が発生し、反応しなくなります。詳細については、こちらを訪れてください:https://github.com/raspberrypi/bookworm-feedback/issues/91

付録

I2C構成

ステップ1: Raspberry PiのI2Cポートを有効にしてください(有効にしている場合はスキップしてください。

sudo raspi-config

3 Interfacing options

_images/image282.png

P5 I2C

_images/image283.png

<Yes>、次に<Ok> -> <Finish>

_images/image284.png

ステップ2: i2cモジュールがロードされ、アクティブになっているかどうかを確認します。

lsmod | grep i2c

すると、次のようなコードが表示されます(番号は異なる場合があります)。

i2c_dev                     6276    0
i2c_bcm2708                 4121    0

ステップ3: i2c-toolsをインストールします。

sudo apt-get install i2c-tools

ステップ4: I2Cデバイスのアドレスを確認します。

i2cdetect -y 1      # For Raspberry Pi 2 and higher version
i2cdetect -y 0      # For Raspberry Pi 1
pi@raspberrypi ~ $ i2cdetect -y 1
    0  1  2  3   4  5  6  7  8  9   a  b  c  d  e  f
00:           -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

I2Cデバイスが接続されている場合は、デバイスのアドレスが表示されます。

ステップ5:

C言語をお使いの方へ: libi2c-devをインストールしてください。

sudo apt-get install libi2c-dev

Pythonユーザーの場合:

For Python users:

  1. 仮想環境の有効化。

注釈

  • 有効化する前に、仮想環境を作成していることを確認してください。詳細はこちらを参照してください: 仮想環境の作成.

  • Raspberry Piを再起動するたびや、新しいターミナルを開くたびに、仮想環境を有効化するために次のコマンドを再度実行する必要があります。

source myenv/bin/activate

仮想環境が有効化されると、コマンドラインのプロンプトの前に環境名が表示され、仮想環境内で作業していることが示されます。

  1. I2Cのためのsmbusのインストール。

sudo pip3 install smbus2
  1. 仮想環境からの退出。

作業を完了し、仮想環境から退出したい場合は、単純に次のコマンドを実行します:

deactivate

これにより、システムのグローバルPython環境に戻ります。

SPI構成

ステップ1:Raspberry PiのSPIポートを有効にします(有効にしている場合はスキップします。有効にしたかどうかわからない場合は続行してください)。

sudo raspi-config

3 Interfacing options

_images/image282.png

P4 SPI

_images/image285.png

<YES> をクリックし、<OK> と <Finish> をクリックします。 これで、 sudo reboot コマンドを使用してRaspberryPiを再起動できます。

_images/image286.png

ステップ2: spiモジュールがロードされてアクティブになっていることを確認します。

ls /dev/sp*

次に、次のコードが表示されます(番号は異なる場合があります)。

/dev/spidev0.0  /dev/spidev0.1

ステップ3: PythonモジュールSPI-Pyをインストールします。

git clone https://github.com/lthiery/SPI-Py.git
cd SPI-Py
sudo python3 setup.py install

注釈

この手順はPythonユーザー向けです。C言語を使用している場合は、スキップしてください。

仮想環境の作成

Raspberry Piや類似のデバイスを使用する場合、 pip を仮想環境でパッケージをインストールすることをお勧めします。これにより、依存関係の分離、システムのセキュリティの向上、システムのクリーンさの維持、プロジェクトの移行と共有の容易化が行われ、依存関係の管理が簡素化されます。これらの利点により、仮想環境はPython開発において非常に重要で便利なツールとなっています。

以下に、仮想環境を作成する手順を示します。

1. 仮想環境の作成

まず、システムにPythonがインストールされていることを確認する必要があります。Pythonバージョン3.3以降では、仮想環境を作成するための venv モジュールが付属しており、別途インストールする必要はありません。Python 2またはPython 3.3以前のバージョンを使用している場合は、 virtualenv をインストールする必要があります。

  • Python 3の場合:

Python 3.3以降のバージョンでは、 venv モジュールを直接使用できます:

python3 -m venv myenv

これにより、現在のディレクトリに名前が myenv の仮想環境が作成されます。

  • Python 2の場合:

まだPython 2を使用している場合は、まず virtualenv をインストールする必要があります:

pip install virtualenv

次に、仮想環境を作成します:

virtualenv myenv

これにより、現在のディレクトリに名前が myenv の仮想環境が作成されます。

2. 仮想環境の有効化

仮想環境を作成した後、使用するためにそれを有効化する必要があります。

注釈

Raspberry Piを再起動するたびや、新しいターミナルを開くたびに、仮想環境を有効化するために次のコマンドを再度実行する必要があります。

source myenv/bin/activate

仮想環境が有効化されると、コマンドラインのプロンプトの前に環境名が表示され、仮想環境内で作業していることが示されます。

3. 依存関係のインストール

仮想環境を有効化した状態で、pipを使用して必要な依存関係をインストールできます。例:

pip install requests

これにより、requestsライブラリがグローバル環境ではなく、現在の仮想環境にインストールされます。このステップは1度だけ行えば十分です。

4. 仮想環境の終了

作業を完了し、仮想環境から退出したい場合は、単純に次のコマンドを実行します:

deactivate

これにより、システムのグローバルPython環境に戻ります。

5. 仮想環境の削除

特定の仮想環境をもはや必要としない場合は、単純にその仮想環境を含むディレクトリを削除できます:

rm -rf myenv

FAQ

Cコードが機能していませんか?

  • 配線に问题がないか確認してください。

  • コードがエラーを報告しているかどうかを確認します。

  • 実行する前にコードを進めましたか。

  • 上記の 3 つの条件がすべて問題ない場合は、wireingPi バージョン (2.50) が Raspberry Pi 4B 以降と互換性がない可能性があります。「WiringPi を確認してインストールする」を参照して、手動でバージョン 2.52 にアップグレードしてください

ありがとうございました

私たちの製品を評価してくれた評価者、チュートリアルの提案をしてくれたベテラン、 そして私たちをフォローしてサポートしてくれたユーザーに感謝します。 私たちへのあなたの貴重な提案は、より良い製品を提供するという私たちの動機です!

特に感謝します

  • Len Davisson

  • Kalen Daniel

  • Juan Delacosta

さて、このアンケートに記入するために少し時間を割いていただけませんか?

注釈

アンケートを送信した後、トップに戻って結果を確認してください。