Pico PR

RaspberryPi Pico MicroPythonでGPIOの割り込み使う方法 【有効・無効化付き】

記事内に商品プロモーションを含む場合があります

はじめに

RaspberryPi Picoで、GPIOの割り込み(ハードウェア割り込み)を使う方法を解説します。回路はタクトスイッチとLED、言語はMicroPythonを使います。

入力信号を確認する際、入力をループで確認する「ポーリング処理」をよく使いますが、読み込みの間に信号が来た場合の「取りこぼし」が不安になります。

今回解説する「GPIOの割り込み」を使うと、取りこぼしの心配はなくなりますし、信号が来た際の立ち上り・たち下がりのタイミングも引数の設定のみで指定できます。

今回は上記、「GPIOの割り込み」の使い方について解説します。

環境

環境 バージョン 備考
開発用PCのOS Windows11 Windows10でもOKです
言語 MicroPython
開発環境 Thonny 3.3.13
ボード RaspberryPi Pico

※ Picoのセットアップ方法については、こちらの記事をご覧ください。

RaspberryPi Picoとの接続

RaspberryPi PicoののGPIOに「タクトスイッチ」「LED」を以下のようにつなげます。

抵抗は220Ωのような小さなものでもOKです(直結防止)。LEDは足の長い方(アノード)をPico側に接続してください。

Picoと回路の接続を説明する画像
ピン番号 内容 備考
38 GND グラウンド
36 3V3(OUT) 電源(3.3V)
25 GP19 タクトスイッチの入力に使います。
21 GP16 LEDの出力に使います。

Picoピンアサイン(Pin-Out)

RaspberryPi Picoのピンアサイン(pinout)の画像

Pico公式サイトより引用

使用する部品

今回の回路では、以下のものを使用します。

ブレッドボード

サンハヤト性のブレッドボードです。少々堅めの指し心地ですが、などの品質も高く、おすすめの一品です。

タクトスイッチ

ブレッドボードで使えるものであればOKです。

抵抗

お手持ちのものでOKです。ない方は一度セットで揃えてしまうと送料と時間が節約できます。

プログラム概要

今回のプログラムの概要は以下の通りです。

  • タクトスイッチが押されたら、割り込み処理を行う。
  • 割り込みでフラグが立ったら、LEDを0.5秒間つける

実行結果

後述するプログラムの実行結果です。タクトスイッチが押されると割り込みが発生し、LEDが点灯します。

実行結果の画像、タクトスイッチを押す前
実行結果の画像、タクトスイッチを押して、LEDが点灯している状況

全体コード

全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。

from machine import Pin
import _thread, time, micropython

# 割り込み処理中の例外を作成するための設定です
micropython.alloc_emergency_exception_buf(100)

#
# 割り込み処理用に登録する関数です。
# 
def DetectInput( pin ):
    
    # detectTactSw をグローバル指定します
    global detectTactSw
    
    # 検知フラグをTrueにします。
    detectTactSw = True
    

# タクトスイッチ(入力)用のピンを設定します
tactSw = machine.Pin(19, machine.Pin.IN, machine.Pin.PULL_DOWN)

# Led(出力)の設定です。
Led = machine.Pin(16, machine.Pin.OUT)

# タクトスイッチの検知のフラグです
detectTactSw = False 
        
# タクトスイッチの割り込み処理を設定します。
tactSw.irq(trigger=Pin.IRQ_RISING,  handler=DetectInput)
        
#
# メイン処理
#
while(True):
        
    #
    # 割り込み処理でタクトスイッチが検知された場合
    #
    if detectTactSw == True:
        
        # フラグを書き換える前に割り込みを止めます
        state = machine.disable_irq()
        detectTactSw = False
        
        # 書き換え後に割り込みを再開します。
        machine.enable_irq(state)
        
        # LEDを0.5秒点灯します
        Led.value(1)
        time.sleep(0.5)
        Led.value(0)
        
    else:
        print("タクトスイッチ検知なし")
        time.sleep(1)

Pico/Pico Wだけ(PCなし)でプログラムを実行する場合は、ファイル名を「main.py」にして、Pico/Pico W本体に保存してください。

コードのポイント

例外用の容量確保

割り込み処理内で例外が発生した場合、デフォルトでは情報が少ないので、デバッグが大変です。以下のコードで例外用のバッファを設定しておくと、例外時の情報が多くなるのでデバッグが楽になります。

# 割り込み処理中の例外を作成するめの設定です
micropython.alloc_emergency_exception_buf(100)

GPIOピンに割り込み処理をつける

GPIOピンに、ポート番号や、入出力、プルアップの設定をしたあと、irq関数で割り込みの設定を行います。引数には、割り込みタイミング(トリガ)、割り込み処理用の関数名を指定します。

IRQ: Interrupt ReQuest

# タクトスイッチ(入力)用のピンを設定します
tactSw = machine.Pin(19, machine.Pin.IN, machine.Pin.PULL_DOWN)

# Led(出力)の設定です。
Led = machine.Pin(16, machine.Pin.OUT)

# タクトスイッチの検知のフラグです
detectTactSw = False 
        
# タクトスイッチの割り込み処理を設定します。
tactSw.irq(trigger=Pin.IRQ_RISING,  handler=DetectInput)

関数はirq関数の設定より前(上の行)に書いてくださいirq関数よりも後に書くと関数が定義されていない。としてエラーになってしまいます。

トリガーの指定

triggerには以下を指定することができます。

trigger名 割り込み生成タイミング
IRQ_FALLING 立ち上がりエッジ(入力用)
IRQ_RAISING 立ち下がりエッジ(入力用)
IRQ_LOW_LEVEL ローレベル(出力用)
IRQ_HIGH_LEVEL ハイレベル(出力用)

※ 以下のMicroPythonのリファレンスから引用しています。

https://micropython-docs-ja.readthedocs.io/ja/latest/library/machine.Pin.html

割り込み処理は短く

割り込み処理としてirq関数に登録する関数です。メイン処理と共有するフラグをグローバル変数に指定し、フラグを書き換えます。

割り込み処理中は、メインの処理が「停止」するため、割り込み処理はできるだけ短時間で終わる処理にします。

#
# 割り込み処理用に登録する関数です。
# 
def DetectInput( pin ):
    
    # detectTactSw をグローバル指定します
    global detectTactSw
    
    # 検知フラグをTrueにします。
    detectTactSw = True

sleepはもちろん、printも実は重い(時間のかかる)処理なので、デバッグの時以外の使用は厳禁です。

Pico/Pico W だけ(PCなし)でプログラムを実行したい場合は「main.py」というファイル名で、Picoにファイルを保存してください。

割り込みを停止する

割り込み処理と共有しているフラグを書き換える際、割り込みを停止しないと、フラグを書き換えている「最中」に割り込みが発生する可能性があり、「FalseにしたのにTrueのまま」のような挙動になってしまいます。

そのため、割り込み処理と共有する変数等へのアクセス(クリティカルセクション)を行う際は、割り込み停止による排他制御(≒ロック)を行うと安全です。

なお、sleepや信号の送受信処理では、内部的に割り込みを使用しているものもあり、割り込み停止によりフリーズ等が発生する場合もあります。そのため、クリティカルセクションは「共有データの書き換え処理のみ」に限定します。

    #
    # 割り込み処理でタクトスイッチが検知された場合
    #
    if detectTactSw == True:
        
        # フラグを書き換える前に割り込みを止めます
        state = machine.disable_irq()
        detectTactSw = False
        
        # 書き換え後に割り込みを再開します。
        machine.enable_irq(state)
        
        # LEDを0.5秒点灯します
        Led.value(1)
        time.sleep(0.5)
        Led.value(0)

まとめ

RaspberryPi Picoで、GPIOの割り込み処理をする方法について解説しました。

「処理内容は短く」「停止はピンポイントで」など、お約束ごともありますが、信号入力を効率的で簡単に処理できる便利な機能です。

使っていくと排他制御などの、一歩進んだプログラミングの知識を身に着けることもできるので、是非積極的に使っていただけたらうれしいです。

お知らせ

今月号のInterfaceは『RaspberryPi 5』特集

3月25日発売のInterfaceは「RaspberryPi 5」特集!

実験などを通じた性能測定や特徴・変更点の解説。新規に追加されたI/Oボード「RP1」の特徴と謎。Pi5のはじめかたやLinuxコマンド入門などが特集されています。

Pico/Pico W関連のおすすめ本

RaspberryPi Pico / Pico W関連のおすすめ本を独断と偏見で3つ選んでみました。Picoやるならとりあえずこれ買っとけ的な本や、電子工作全般で使える本などを厳選しています。

見た目のいい工具をお探しの方へ

よく使うツールは『見た目』が重要。モチベもあがりますし、仲間との話のネタにもなります。以下のサイトは、デザイン性の高い工具が集めたサイトなので、興味がある方はぜひご覧ください。

お知らせ

今月号のInterfaceは『RaspberryPi 5』特集

3月25日発売のInterfaceは「RaspberryPi 5」特集!

実験などを通じた性能測定や特徴・変更点の解説。新規に追加されたI/Oボード「RP1」の特徴と謎。Pi5のはじめかたやLinuxコマンド入門などが特集されています。

Pico/Pico W関連のおすすめ本

RaspberryPi Pico / Pico W関連のおすすめ本を独断と偏見で3つ選んでみました。Picoやるならとりあえずこれ買っとけ的な本や、電子工作全般で使える本などを厳選しています。

見た目のいい工具をお探しの方へ

よく使うツールは『見た目』が重要。モチベもあがりますし、仲間との話のネタにもなります。以下のサイトは、デザイン性の高い工具が集めたサイトなので、興味がある方はぜひご覧ください。

質問・要望 大歓迎です

「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。

使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。

ABOUT ME
えす
現役のソフトウェアエンジニアです。 C++ C# Python を使ってます。10年ちょい設計/開発部門にいましたが、今はQAエンジニアっぽいことをしています。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Index