tmct-web

電子工作・DIYの製作例やノウハウを公開しています

【簡単制御!】Raspberry PiのGPIOを自在に制御する

※「GPIOが足りないんだ」という方はこちらをご覧ください。

リンク
MCP23017 MCP23017でRaspberry PiやArduinoのI/Oを増やす
PCA9535 PCA9535でRaspberry PiやArduinoのI/Oを増やす

ラズパイ、引き出しで寝てるってよ

Raspberry Pi

あなたのラズパイはこんなことになっていませんか?

  • Raspberry Piって面白そうだからRSでポチッたけど、よく考えたら使い道がなかった。
  • 色々できるらしいがLチカしかやったことがない。
  • パソコンやNASの代わりに…と思って買ったけど管理が面倒くさすぎて結局本物を買い直した。
  • 安いし子供用のパソコンに、と思ったけども、子供が使うには敷居が高すぎた。
    そういえば自分もそんなに知らないから質問にも答えられないよアハハ!(涙)

世界中で引き出しの肥やしになっているラズパイは出荷数量のうち相当数を占めるのではないかと…(まあビジネスとしては売れればいいのか…環境活動家のグ○タさんは怒りそうだけど)

そもそもRaspberry Pi(以下、ラズパイ)はArduinoでは性能が不足するような高性能なIoTエンドポイント向けに作られたものなので、パソコンやサーバー用途としては少々難があるのです。

しかしLinuxが動作してデスクトップPCやサーバーとして「使えなくはない」ということで、誤って購入される事故(?)が多発して肥やし化が助長されているように思います。

この記事では、Raspberry Pi(ラズパイ)のGPIOを使って、ラズパイを本来想定された用途に近い「超高性能なコントローラ」として使うための方法を紹介します。

せっかく遠路はるばる海外からやってきたのですから、寿命尽きるまで何かしら活躍してほしいものですね。

GPIOって何?

GPIOは General Purpose Input/Output の略で、そのまま訳すと「汎用目的入出力」です。

ラズパイにはEthernetやUSBなど色々なインターフェイスが備わっていますがGPIOもその中の1つで、3.3Vのデジタル信号(High/Low)を入出力するためのインターフェイスです。

簡単に言うと、ラズパイからの出力でなにかのスイッチをON/OFFさせたり、逆にスイッチからの信号を入力して、ON/OFFを検出することで何かの処理を始めたり……なんてことができます。

ラズパイを見ると40ピンほどのピンヘッダが立っていると思います。「きっと自分には関係ないだろう」と思ってスルーしている人が多いかもしれませんが、それがGPIOに使うピンヘッダです。

普通サイズのラズパイ(Raspberry Pi無印・2・3・4など)は下記写真の右側の2列のピンヘッダがそれです。

Normal Raspberry Pi series

ラズパイゼロ系は下記写真の右側の穴が空いたパターンがそれです。購入形態によりますが、多くの場合、購入時にピンヘッダは実装されていないようですね。

Raspberry Pi Zero series

このピンヘッダにはGPIOが24本アサインされていて、それぞれ個別にプログラムから状態を取得したり(入力)、状態を変更したり(出力)できます。

ピンアサイン

さて、このGPIOピンヘッダのピンにはそれぞれ以下のような信号名が付いています。(写真の向きで見たときのピンアサインです)

全部がGPIOとして使えるわけではなく、この中で「GPIO」で始まる信号名のピン(24本)がGPIOとして使用できます。

ちなみに、GPIO 2とGPIO 3はラズパイの基板上でPull Upされています。

Signal Name Pin No. Pin No. Signal Name
3.3V_OUT1 1 2 5V_PWR2
GPIO 2 3 4 5V_PWR2
GPIO 3 5 6 GND3
GPIO 4 7 8 UART_TX
GND3 9 10 UART_RX
GPIO 17 11 12 GPIO 18
GPIO 27 13 14 GND3
GPIO 22 15 16 GPIO 23
3.3V_OUT1 17 18 GPIO 24
GPIO 10 19 20 GND3
GPIO 9 21 22 GPIO 25
GPIO 11 23 24 GPIO 8
GND3 25 26 GPIO 7
(RESERVED) 27 28 (RESERVED)
GPIO 5 29 30 GND3
GPIO 6 31 32 GPIO 12
GPIO 13 33 34 GND3
GPIO 19 35 36 GPIO 16
GPIO 26 37 38 GPIO 20
GND3 39 40 GPIO 21

入出力してみる

実際に入出力を試すために、ラズパイに下図のような回路を接続したとします。

Test circuit

また、OSはRaspberry Pi財団の標準OSであるRaspbianを使います。ライブラリとしてWiring Piというものもありますが、ここではOSの標準機能だけを使って制御することを考えます。

制御の流儀

GPIOはOSから見ると共有リソースなので、制御するには決められた手順を踏む必要があります。

大まかには以下の手順です。

  1. リザーブする
    RaspbianはマルチタスクOSです。ということは、自分が独占して制御しているつもりでも同時に動作している他のソフトウェアやタスクが勝手に状態を変えてしまうかもしれません。
    周辺回路が「ああ、しんし゛ゃった!」とならないためにも、これから使おうとするGPIOピンをリザーブ(予約)します。
    逆に、すでに他のソフトウェアやタスクがGPIOピンを利用中の場合は、リザーブしようとした時点でエラーが発生します。
  2. 入出力を設定する
    IOというだけあって、入力も出力もできます。
    該当のピンをどちらで使いたいのか設定します。
  3. 入力または出力する
    入力ピンならピンの状態を取得、出力ピンならピンの状態を設定します。
  4. リザーブを解除する
    用が済んだら、他のソフトウェアやタスクからこのピンを利用できるよう、ピンのリザーブを解除します。
    リザーブを解除しても、再び制御されるまでは現在の状態が保持されます。(要するに入力ピンなら入力状態を保持、出力ピンならピンの状態をそのまま保持)
    ちなみにそのままラズパイを再起動した場合、ピンの状態は保持されず全部入力ピンとして初期化された状態で起動します。

コマンドラインで制御する

まずは出力させてみます。GPIO 2の出力を制御するには、コマンドラインから以下のように入力します。この方法は管理者権限が必要ですが、追加ライブラリなしで手軽に実行できます。

スクリプト化してサービスとして定期的に実行する場合はこの方法が軽くて良いでしょう。

echo 2 > /sys/class/gpio/export                 # GPIO 2をリザーブする
echo "out" > /sys/class/gpio/gpio2/direction    # GPIO 2を出力にする
echo 1 > /sys/class/gpio/gpio2/value            # GPIO 2に High(1) レベルを出力する
echo 0 > /sys/class/gpio/gpio2/value            # GPIO 2に Low(0) レベルを出力する
echo 2 > /sys/class/gpio/unexport               # GPIO 2のリザーブを解除する

わかる人にはわかると思いますが、/sys/class/gpio にディレクトリを生成し、そこに対して値を書き込むことで制御します。

次に入力です。GPIO 3のスイッチの状態を取得するには、コマンドラインから以下のように入力します。

echo 3 > /sys/class/gpio/export             # GPIO 3をリザーブする
echo in > /sys/class/gpio/gpio3/direction   # GPIO 3を入力にする

ここまででGPIO 3が入力に設定され、状態を取得する準備ができます。

GPIO 3は基板上でPull Upされているので、スイッチを押してないときは High(1)、押している間は Low(0) が取得されるはずです。では状態を取得してみましょう。

cat /sys/class/gpio/gpio3/value

これもわかる人はわかると思いますが、/sys/class/gpio/gpio3/value ファイルの中身を表示しているだけです。要するにOSから見るとGPIOはファイルの一つとして見えているわけですね。

GPIO 3の状態がHigh(上記の回路だとスイッチを離しているとき)は 1、Low(スイッチを押しているとき)は 0が出力されます。

最後に、ピンのリザーブを解除します。

echo 3 > /sys/class/gpio/unexport           # GPIO 3のリザーブを解除する

C言語から制御する

なぜコマンドラインから先に説明したのか、勘の良い人ならお気付きでしょう。
C言語でも、やることは一緒だからです。

ここまで説明したらいちいち説明するよりコードを見たほうが早いと思うので、コードを載せます。以下のコードはGCCでコンパイルして動作することを確認済みです。

ただし、このバイナリの実行には管理者権限が必要ですし、あまりおすすめしません。
C言語で記述するならWiring Piなどのライブラリを使った方が管理者権限も必要なく、記述も楽なのでそちらを推奨します。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv)
{
    int fd = 0;

    // GPIO 2をリザーブする
    fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0) {
        printf ("GPIO reserve error.\n");
        exit(1);
    }
    write(fd, "2", 2);  // 2バイト書き込み
    close(fd);

    // 0.1秒待つ (確実にリザーブされるまでの待ち時間)
    usleep(10 * 1000);

    // GPIO 2を出力に設定
    fd = open("/sys/class/gpio/gpio2/direction", O_WRONLY);
    if (fd < 0) {
        printf ("GPIO direction error.\n");
        exit(1);
    }
    write(fd, "out", 4);    // 4バイト書き込み
    close(fd);

    // GPIO 2 に High(1) を出力する (LED OFF)
    fd = open("/sys/class/gpio/gpio2/value", O_WRONLY);
    if (fd < 0) {
        printf ("GPIO value error.\n");
        exit(1);
    }
    write(fd, "1", 2);  // 2バイト書き込み
    
    // GPIO 2 に Low(0) を出力する (LED ON)
    write(fd, "0", 2);  // 2バイト書き込み
    close(fd);

    // GPIO 2のリザーブを解除する
    fd = open("/sys/class/gpio/unexport", O_WRONLY);
    if (fd < 0) {
        printf ("GPIO release error.\n");
        exit(1);
    }
    write(fd, "2", 2);  // 2バイト書き込み
    close(fd);

    return 0;
}

入出力される信号

GPIOで入出力される信号は「3.3V CMOSレベル」という仕様のデジタル信号ですが、それがよくわからないから何も接続できずにいる、という人も居るのではないかと思います。

ラズパイのGPIOで入出力できる信号の素性を書いておきますので、参考にしてください。
日本語でおk、という人は、ラズパイを壊さないためにももう少し電気的な知識を身に着けてからの方が無難でしょう。

入力

GPIOで入力に設定したピンには、下記の電圧レベルを入力することができます。

電圧 ラズパイの認識値 備考
3.6V以上 ××× ラズパイが壊れる
2.3〜3.5V High(1) CMOSレベルなのでだいたい 3.3V×0.7 程度がしきい値になる
2.2〜0.9V ??? 不定値なので入力するべきではない
0〜0.8V Low(0) CMOSレベルなので0.8V以下が Low
  • ラズパイは電源投入時には全てのGPIOピンが入力に設定されていて、GPIO 2と3だけは3.3V 1.8kΩでPull Upされていますが、その他のピンはすべてPull Downされています。
  • GPIO 2と3のPull Upは基板上の抵抗で物理的にPull Upされているため、Pull Up/Downの状態をソフトウェアから制御することができません。
    その他のピンは Pull Up/Down/なし をソフトウェアから制御することができます。
  • 電流は基本的にほとんど流れ込みませんが、目安として下記の電流が流れ込みます。
    GPIO 2または3をLowに落とした時 = それぞれ約1.8mA
    その他のピンでPull Up/Downと逆の論理で駆動した時 = 数十uA
    その他のピンでPull Up/Downと同じ論理で駆動した時 = 数uA

参考までに、スイッチを接続する回路を載せます。

一般的な電子機器でスイッチから信号を入力する場合、スイッチからの信号を負論理(押すとLow(1)・離すとHigh(1))とするのが一般的です。
なぜかというと、人が触るデバイスからの信号線は静電気などで信号線の電圧が上昇することが多々あるからです。正論理だとスイッチを押してないのにHigh(1)として認識され機器が誤作動する可能性があります。

一方、静電気で信号線の電圧が上昇することはありますが、電圧レベルが落ちることはまずないので負論理だと誤作動が抑制できます。先人の知恵っぽいものですが、私の経験でもそれなりに効果があるので倣った方が良いでしょう。

Input from switch(1)

ちなみに、不定な電圧が入力される可能性がある場合はシュミットトリガバッファなどで白黒つけてから入力するのがベターです。

こういう用途には7414というICが使われるので、以下に参考回路を載せておきます。

Input from switch(2)

出力

GPIOで出力に設定したピンは、下記いずれかの電圧レベルが出力されます。

ラズパイの設定値 電圧
1(High) 約3.3V
0(Low) 約0V
  • 出力可能な電流量は1ピンあたり16mA(0.016A)、全GPIOピンの合計50mA(0.05A)までです。
    たとえば1ピンあたり8mA取り出す場合は 8mA × 6本 = 48mA となるので6本まで使えますが、その他のピンの出力電流は合計2mA以下に抑える必要があります。
  • 出力電流が足りない場合は、外部にトランジスタなどを付けてください。

参考までに、ラズパイからの出力でリレーを動作させる回路を載せます。

ラズパイからの出力でトランジスタを動作させ、リレーをドライブします。1(High)を出力するとON、0(Low)を出力するとOFFになります。

リレーは動作電流が60mA程度以下のものなら下記の回路でもそのまま動くでしょう。パワーリレーとかはこのトランジスタでは駆動しきれないので、トランジスタをもっと大きな電流が駆動できるものに変えないといけません。また、リレーの電源電圧を上げる場合はツェナーダイオードも変える必要があります。

Output relay

まとめ

ラズパイのGPIOはソフトウェアから簡単に制御できることを紹介しました。

外部に何を接続するかは工夫次第ですが、とりあえずリレーを接続すればネットワーク経由で家電をON/OFFすることも簡単にできます。あなたの引き出しに眠っているラズパイを久しぶりに起こしてみてはどうでしょうか?

 

 


  1. 外部へ供給する電源として3.3Vが出力されます。ただし供給できる電流は0.1A(100mA)程度です。あまり多くの電流を取り出すとラズパイの電源回路が焼損して二度と起動しなくなります。 ↩︎ ↩︎

  2. 5Vの電源ピンです。micro-USBの電源ピンがそのままつながっているので、micro-USBから電源を供給しているときはこのピンから電源が出力されます。また、micro-USBから電源を供給せずこのピンから電源を供給することもできます。ただしラズパイ単体でも1Aほど電流を消費するので電流供給能力には注意してください。 ↩︎ ↩︎

  3. 信号・電源のGND(グランド)です。接続する相手先と必ずGNDを接続してください。基本的にGNDが正しく接続されていないと、相手方に信号が正しく伝わらず正常に動作しないと考えてください。 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

最終更新: 2021-07-03
作成: 2020-02-09
  • Raspberry Pi
  • Arduino

© 2025 tmct-web All Rights Reserved.
Powered by Hugo. Theme by TechDoc. Designed by Thingsym.