💡

普通のパソコンでもGPIOを使ってみよう[デジタルI/O編]

2024/07/16に公開

はじめに

皆さんが使う普通のPC(WindowsでもmacOSでもLinuxでも)で、安く簡単にGPIOを使う方法について説明します。
今回はそのGPIOの簡単なデジタルI/O(入出力)の使い方について説明します。

方法

以前の投稿記事
https://zenn.dev/headwaters/articles/b9183cca7e7233
こちらで、使用していたFT2232Dというデバイスを使います。
普段はUART通信で、マイコンやRS232Cインターフェースを搭載した機器とパソコンの通信に使う事が多いですが、モードを切り替えることでGPIOやI2C/SPI通信といったものも利用する事ができます。

Pythoで手軽にGPIOを使った開発をしよう

使用するライブラリ

対応デバイス

PyFtdiでは以下のデバイスをサポートしています

Supported FTDI devices include:
UART and GPIO bridges
FT232R (single port, 3Mbps)
FT230X/FT231X/FT234X (single port, 3Mbps)

UART and multi-serial protocols (SPI, I2C, JTAG) bridges
FT2232C/D (dual port, clock up to 6 MHz)
FT232H (single port, clock up to 30 MHz)
FT2232H (dual port, clock up to 30 MHz)
FT4232H (quad port, clock up to 30 MHz)
FT4232HA (quad port, clock up to 30 MHz)

入手しやすいデバイス

対応デバイスの中で入手性の良いものをピックアップしました。
秋月電子やSwitchScienceなどで手ごろな価格で入手可能となっています。

Windowsのみlibusb-win32ドライバへの入れ替えが必要

libusbドライバを使用します。macOS,Linuxには基本的にインストールされているので、USB接続してそのまま使えますが、Windowsの場合はメーカーの純正ドライバがインストールされます。
この純正ドライバではGPIO等を使えない為、libusbをWindows向けに移植したlibusb-win32に置き換えます。
Windowsでのドライバ置き換えについては下記の記事を参照ください。
https://eblot.github.io/pyftdi/installation.html#windows

その他、使用するもの

  • 上記のデバイス(今回はFT2232Dを使用します)
  • ブレッドボード
  • ジャンプワイヤ(オスーオス)
  • タクトスイッチ
  • 3色LED
  • 1/4Wカーボン抵抗(100Ω)
    下記のようにセットアップします。

回路図

実際の配線(※タクトスイッチを入れ忘れました・・・)

実際にPythonで実装してIOを叩いてみる

  • ライブラリのインストール
pip install pyftdi
  • デバイスのURLを取得する
from pyftdi.ftdi import Ftdi
Ftdi.show_devices()

実行すると、ターミナルにFTDIデバイスのURLが表示されます。

Available interfaces:
  ftdi://ftdi:2232:0:1/1  (Dual RS232)
  ftdi://ftdi:2232:0:2/1  (Dual RS232)

このFT2232Dはデュアルタイプでチップが2つ入っているので2つ表示されます。
今回はftdi://ftdi:2232:0:2/1 (Dual RS232)を使います。

  • デバイスのオープンとポートの初期化
FTDI_DEVICE_URL = "ftdi://ftdi:2232:0:1/1"

ftdi_gpio = gpio.GpioAsyncController()
ftdi_gpio.open_from_url(url=FTDI_DEVICE_URL, direction=0b00000111, initial=0b00000101)

open_from_url関数のurlで使用するデバイスの指定、directionで8bitのIO入出力方向の設定、initialで出力の初期値を設定します。
利用する8bitのIOは回路図のAD0-7の8本で、それぞれ末尾の番号が各bitに相当します。
次に、GPIOの入出力方向をdirection引数に8ビットの値で設定します。
入出力方向と論理の設定値は以下の通りです。

Hi(1):出力
Lo(0):入力

という事で、direction=0b00000111はAD0-2が出力、AD3-7が入力という設定になります。
次に、initialでは出力ポートの出力状態を決めます。
こちらも、論理の設定値は以下の通りです。

Hi = 1
Lo = 0

initial=0b00000101はAD0,AD2がHiで、GPIO1がLoになります。
ちなみに、入力設定になっているAD3-7のいずれかのポートを1に設定しても何も起きません。

出力状態を変更してみる

ここまでは、デバイスの初期化処理でしたが実際にポートの出力を行ってみます。
GPIOの出力ポートを操作するには、write()関数を使用します
せっかく3色LEDなので、様々なパターンで色を表現してみたいと思います。
R,G,Bの単色点灯パターンは以下の通りです。
0b001 -> 赤
0b010 -> 青
0b100 -> 緑
3色の点灯パターンを組み合わせると、消灯を除いて7色点灯することができます。
実際のコードがこちら

# R,G,B 全パターンで点灯
while True:
    for i in range(1, 8, 1):
        ftdi_gpio.write(i)
        time.sleep(1)

実際に点灯させてみた様子

※白飛びしてあまり鮮やかに撮影できておらずすみません・・・

ちなみに、マイコンのタイマーを利用すると8bit分解能場合、R,G,Bの出力をPWM制御[1]すると、8bit(256)の3色ということで、理論的には16,777,216色まで発光させることもできます。

入力状態を取得してみる

入力状態はread()関数で取得できます。

ftdi_gpio.read()

そのままprintに渡しても10進数表記で見づらいので、今回は2進数表記に変更します。

print(bin(ftdi_gpio.read()))

今回のデバイスはGPIOのポートが8bitなので、read()関数で取得したデータも8bitとなります。
ただし、GPIO0-2は出力設定になっており、0-3bit目までは現在の出力状態が、残りのGPIO3-7が入力状態を表しています。

0b11110111
0b11110001
0b11111010
0b11110011
0b11110100

上位5bitが入力で3bit目のGPIO3にタクトスイッチが、下位3bitが出力でR,G,BのフルカラーLEDが接続されています。
ドキュメントによると、入力設定したポートは75kΩでプルアップ[2]されています。
スイッチの片側をポートに接続し、残りをGND側に接続して使うので、 負論理[3]となり、スイッチを押す(ON状態)とLoになり、スイッチを離す(OFF状態)とHiになります。
上記の出力結果3bit目を見ると、スイッチがON->ON->OFF->ON->ON->・・・となっているのが分かります。

まとめ

GPIOの基本的なデジタルI/Oが普通のパソコン上でも使えるようになります

メリット

  • 安い

  • USBポートがあれば増設できる

  • Windows/Linux/macOSプラットフォーム問わず開発ができる
    前回の記事で紹介したWSL上のUbuntuでもGPIOを使う事ができた

  • Pythonで手軽にI/Oを使う事ができる
    GPIOだけでなく、I2CやSPIも利用する事ができる

デメリット

  • マイコンと比較して細かい事ができない
    特に・・・

    • 電源ONですぐに動かない
    • 電源ON後のI/O状態が不定
    • ハードウェアタイマーが直接使用できない
  • RaspberryPiでは使えるライブラリが使えない場合がある

  • 困ったときの情報が少ない

余談

次回は引き続きこのデバイス使い、I2C通信のやり方について投稿したいと思います。
ちなみに、ライブラリではFT2232DのI2C通信のサポートが中途半端なために、少し躓いたところがあるので、問題なく使いたい方はFT232Hの方をお勧めします。

脚注
  1. PWM制御とは、周期内におけるONとOFFの時間の比率を変更することで任意の出力電圧を得る制御 ↩︎

  2. プルアップとは、入力信号を安定させるために抵抗を介して電源に接続することを指します ↩︎

  3. 負論理とは、Loを1、Hiを0と定義するものです。 ↩︎

ヘッドウォータース

Discussion