IoT演習第４回、GPIOと電気回路その２

# 1. はじめに
[IoT演習シラバス案その２（授業計画表）](https://qiita.com/takashiyamanoue/items/0cf9d58265bff5883698)の第４週に予定している内容の一部です。

マイクロコントローラ（マイコンと呼ぶこともあります）は、コンピュータ(CPU+メモリ)と入出力機能を、ICの１つのチップや１枚のボードにまとめたものです。マイコンには電源を供給する端子の他に入出力を行う端子がついています。マイコンの入出力端子に、情報を入力するセンサ、情報を出力する表示装置、動作を行うアクチュエータ（モータなど）を接続して、様々な物を制御することができます。

https://ja.wikipedia.org/wiki/マイクロコントローラ

今回も、マイクロコントローラの入出力を行う端子のうち、GPIO (General Purpose Input Output ) 端子について説明します。内容は以下のとおりです。


1. GPIOからデジタル値の入力方法, 
2. Pull-UpとPull-Down
3. パソコンの端末でPico Wのデジタル値の入出力を制御
4. 演習1: Pico Wの外部に接続したスイッチを押すと外部のLEDを点灯し、スイッチを離すとそのLEDを消灯するプログラムを作成する
5. 演習2: Pico W の外部に接続したスイッチを押すと外部のLEDを消灯し, スイッチを離すとそのLEDを点灯するプログラムを各班で考えて作成する
6. 授業の振り返り

# 2. GPIOからのデジタル値の入力方法

汎用入出力端子(General Purpose I/O 端子、GPIOピン)とは、入出力機能を持つマイクロコントローラ等で、実行時の設定により、入力にも出力にもなる端子（ピン）のことを表します。Raspberry Pi Pico W(Pico W)のPINOUT図の、GP0からGP28までのGPで始まってその後ろに数字が続く名前のついた端子がGPIO端子を表します。

![20240623-pico-w-pinout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/820b1ced-5bff-4298-94b8-4f2445beac3d.png)


一つの端子（ピン）に複数の名前がついている場合がありますが、これはそのピンが、それぞれの名前が表す複数の機能を持つことを表します。この機能はプログラムによって切り替えることができます。GPIOは、High(高い電圧、1と書くこともあります)かLow(低い電圧、0と書くこともあります)の値を入力したり、出力したりします。なお、入力の時は、この端子とGNDとラベルが付いた端子の間に外部から電圧をかけます。出力の時は、この端子とGNDとラベルが付いた端子の間にPico Wによって電圧がかかります。

(<文字列>は、実際のプログラムの中では、この部分が名前や数字などで置き換えられることを表します)

Pico W の MicroPython において、GPIO端子の１つを入力端子に設定する場合、以下の文を実行します。ここで<pin名>は、プログラム中で使う端子の名前を表す変数名です。<GPIOの端子番号>は、GPIOの端子番号を表します。
```
<pin名> = Pin(<GPIOの端子番号>, Pin.IN, Pin.PULL_UP)
```
この端子のHighまたはLowを検出するには、関数
```
<pin名>.value()
```
を実行します。<pin名>に関連づけられた番号のGPIO端子にHigh(2.0V以上)の電圧がかかっていればこの関数値は整数値の1, Low(0.8V以下)の電圧の時は、この関数値は整数値の0になります。

https://deepbluembedded.com/raspberry-pi-pico-w-pinout-diagram-gpio-guide/#google_vignette

GPIOの端子からデジタル値を入力するPico W の具体的なプログラムの例を以下に示します。このプログラムは5秒ごとに14番のGPIO端子からデジタル値を入力し、その値をREPL端末に出力するものです。
```Python
from machine import Pin
import time
sw01 = Pin(14, Pin.IN, Pin.PULL_UP)
while True:
  time.sleep(5.0)
  print(sw01.value())
```

第２回・第３回に示した要領で、Micro Pico をinstallしたVSCodeの編集領域に、上のプログラムを入力します。

ブレッドボードを使って、Pico W とタクトスイッチ（ボタンを押すと端子間がつながるスイッチ）をジャンプワイヤで以下の図のように接続し、回路を作成します。

![20240623-gpio-in-bb-shcim-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/855fa68d-50d6-53b1-93fe-41e241e781c2.png)


(以下は、[第２回](https://qiita.com/takashiyamanoue/items/4baba8e23c86dc07962d)で説明している、Anaconda(Python), VSCode, VSCodeのMicroPicoのExtentionがインストール済みであることを前提としています。)


第２回・第３回に示した要領で、VSCodeを動かしているPCとタクトスイッチを接続したPico WをUSBケーブルで接続し、VSCodeの下の方に表示されている Run ボタンをclickして、プログラムを実行します。

![20240623-gpio-in-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/e75f95aa-044a-e104-f940-9255c293ba91.png)


5秒ごとにREPL端末に 1が表示されますが、タクトスイッチを押して、押したたままにすると、0が表示されます。


![20240623-gpio-in-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/ff061189-3c6b-e4b3-87dd-42eccbfdb48a.png)

# 3. Pull-Up と Pull-Down
先ほどの
```
<pin名> = Pin(<GPIOの端子番号>, Pin.IN, Pin.PULL_UP)
```
の、PULL_UPは、このGPIO端子に何も接続されていなくて外からの電圧がかかっていない場合、Highになるよう、設定されることを表します。この端子をたとえばボタンを押したら端子が繋がるタイプのスイッチ（タクトスイッチ）を通じてGNDに接続したとき、
```
<pin名>.value()
```
の値は、ボタンを押していない時は High、押した時は Low になります。

PULL_UPは、Pico Wの内部でこの端子と+電圧(3.3V)との間を抵抗（のようなもの）で接続することで実現しています。この抵抗の値はおよそ24KΩのようです。

https://www.youtube.com/watch?v=PDAFOvtA1Qc

PULLUPの代わりに、PULLDOWNを使って、
```
<pin名> = Pin(<GPIOの端子番号>, Pin.IN, Pin.PULL_DOWN)
```
を実行すると、このGPIO端子に何も接続されていなくて外からの電圧がかかっていない場合、入力は Low になるよう、設定されます。この端子をたとえばボタンを押したら端子が繋がるタイプのスイッチ（タクトスイッチ）を通じて3.3Vの出力端子(36番ピンの、3V3OUT)に接続したとき、
```
<pin名>.value()
```
の値は、ボタンを押していない時は Low、押した時は High になります。

```
<pin名> = Pin(<GPIOの端子番号>, Pin.IN)
```
のように、PULLUPも、PULL_DOWNも指定しない場合は、内部でのPull up抵抗やPull down抵抗が接続されません。この時は、
外部でPull up 抵抗または Pull down 抵抗を接続しないと、入力が不安定になります。

# 4. パソコンでPicoのデジタル値の入出力を制御

第２回で示したように、Micro Python は REPL端末でPythonの文を、１文ずつ直接実行することができます。以下の図は、パソコンのVSCodeのREPL端末で、Pin classのimport, GPIOピンの入力設定、入力設定したピンからデータ(High(1)またはLow(0))を入力するPythonの文を入力して、その結果をREPL端末に出力することを、直接行なった時の例です。このようにして、プログラムを実行する前や後に、パソコン端末のREPL端末でPicoの入出力を試すことによって、回路に間違いがないか、などを知ることができます。

![20240623-gpio-in-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/68614bc9-7599-0024-d119-4b60122ffdf5.png)


# 5. 演習1: Pico Wの外部に接続したスイッチを押すと外部のLEDを点灯し、スイッチを離すとそのLEDを消灯する回路とプログラムを作成する

第2回のプログラム・回路と、今回のプログラム・回路を組み合わせて、Pico Wの外部に接続したスイッチを押すと外部のLEDを点灯し、スイッチを離すとそのLEDを消灯するプログラムを作成してみてください。

- 解答例　(回路)
![20240629-led-sw-bb-schimatic-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/9c7ecae7-e229-a1e3-9358-4c40f58eb0b6.png)


- 解答例　（プログラム）
```Python
from machine import Pin
import time
red = Pin(15, Pin.OUT)
sw01 = Pin(14, Pin.IN, Pin.PULL_UP)
while True:
   v=sw01.value()
   if v==0:
      red.on()
   else:
      red.off()
   time.sleep(0.5)
```
- 解答例（実行例）

![20240629_sw_led_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/452824db-216c-091b-e21b-d750c9d25f78.jpeg)

![20240629_sw_led_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/e42893cc-b1aa-929d-64bd-8fe2db746fab.jpeg)


# 6. 演習2: Pico Wの外部に接続したスイッチを押すと外部のLEDを消灯し、スイッチを離すとそのLEDを点灯するプログラム

7.演習1のプログラムを少し変更して、Pico Wの外部に接続したスイッチを押すと外部のLEDが消灯し、スイッチを離すとそのLEDが点灯するプログラムを作成してみてください。

- 解答例　(回路)
演習１と同じ。
- 解答例　(プログラム)
```Python
from machine import Pin
import time
red = Pin(15, Pin.OUT)
sw01 = Pin(14, Pin.IN, Pin.PULL_UP)
while True:
   v=sw01.value()
   if v!=0:
      red.on()
   else:
      red.off()
   time.sleep(0.5)
```