プルアップとかUARTがちょっとわかるようになるお話

本記事は株式会社ソラコム Advent Calendar 2021 の12日目の記事となっております。SORACOMのテクノロジーに限らずIoTに関わる記事が目白押しですので、ぜひぜひ他の記事もチェックしてみてください！
本記事では私がハードウェア(電子回路)出身ということでデバイスのインターフェースに関する内容となっておりますが、ハードウェアが専門外という方に向けた内容になっておりますのでご安心ください(笑)


# デバイスインターフェースとは？
* GPIO
* UART
* I2C
* SPI
* USB
* PCIe

IoTでは必ずデバイスとデバイスの間でコミュニケーションをとる必要があります。そのときに利用するのがデバイスインターフェース。このデバイスインターフェースには上にあげたように様々な種類があります。ただ使う分にはコネクタをつなぎ、ソフトウェアのライブラリを利用すれば使えてしまうことがほとんどです。
ですが、場合によってはデバイス同士の接続を自作したり、ソフトウェアを自前で書いたりする必要も出てくるのがIoTの世界。そんなときにインターフェースの仕様を知っていると比較的簡単に対応できることもあります。
知っているようで意外と知らない(？)デバイスインターフェースについてちょっと突っ込んで解説をしていこうと思います。

## 入力と出力
デバイスで信号をやり取りするためには必ず入力と出力が存在します。
入力を信号を外から受け取ることであり、出力は信号を外に出すことを指します。データを送る際には送る側のデバイスの出力端子と受け取る側の入力端子を接続し、データの送信を行います。
出力端子と入力端子はデバイスインターフェースによってそれぞれ専用の端子を用意する規格もあれば、別々に用意する規格も存在します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/ce3dae22-8300-f118-8f9d-4d2826b50c1f.png)


## GPIO（接点）
基本中の基本となる接続です。出力と入力の一対一の接続にてHigh or Lowにてデータを判断します。
よくある接点もこの仕組を利用して出力を判断します。

### プルアップ・プルダウン
ここでGPIOを使っているとよく出てくるプルアップ・プルダウンについて説明しておきたいと思います。
なんとなく必要だから入れてみたという人も多いのではと思われるプルアップ・プルダウン(笑)。これらの主たる目的は **入力の値を安定させる** ことにあります。
下の図のようにある入力端子に注目したとき、そこに何も繋がれていない状態があるとします。そのときに、この端子は0でしょうか？それとも1でしょうか？
答えは不定です。不定とは端子に信号が加わっていないので端子の電圧が何Vかわからない状態であるため、0と1が確実に決められない状態であることを示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/210f7f9d-fe59-a350-91df-c37cba6c78d6.png)

この状態を回避するために、未入力状態のときに0に固定するのがプルダウン、1に固定するのがプルアップになります。
このように抵抗を介してHighレベルになる電圧とつなくのがプルアップ、GNDにつなぐのがプルダウンと呼ばれ、そこに挟む抵抗のことをプルダウン抵抗、プルアップ抵抗と呼ばれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/2a6896dc-3656-f316-600d-fa3739ec0c77.png)

### オープンドレイン出力
このプルアップを利用して便利な入出力機構を実現している例を紹介します。
プルアップは未接続時の入力を1(High)に固定する役割を持たせる仕組みでしたが、別の見方をすると**Highレベル信号の電圧を入力側が決められる**ということにもなります。出力側の電圧レベルに依存せずにHigh信号を入力できるため、非常に便利です。
とはいえ、少しでも電気回路に知識がある人であれば、疑問が出てくると思います。理屈的には出力に依存しないといっても物理的につないだときに電圧差があるとうまく動かなかったり、壊れたりするのでは？と。
それは全くそのとおりです。ですので、出力側では**電圧をかけないHigh出力**が必要になります。電圧をかけないHigh出力なんてあるのか？と思われた方もいらっしゃるかもしれませんが、実は存在します。それがオープンドレイン出力(またはオープンコレクタ出力)と呼ばれる出力です。
仕組みとしては非常にシンプルでスイッチをGNDにつなげただけの出力回路となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/6585575c-a283-e120-27f1-fe5a3c3c45fe.png)

スイッチを閉じたときにはGNDとつながるのでLowを出力し、スイッチを開いたときには不定を出力します。不定なので単体で見ると当然まともな信号出力とはなりません。しかし入力がプルアップされていれば、出力はHighに固定されるため不定ではHigh信号として取り扱うことが可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/6dc1256c-b910-81b2-120b-1981c25f73c9.png)
このオープンドレイン出力は出力側がどんな電圧で駆動していても信号を出力できる仕組みとして広く利用されています。

### 接点出力
さらにこのオープンドレイン出力をコントロールするスイッチに注目してみてください。この仕組みを使うとスイッチが閉じている(ON)のときにLow信号、スイッチが開いている(OFF)のときにHigh信号が出力されます。つまり**スイッチの状態を知る**ことができるのです。
これを利用したのが接点出力と呼ばれる回路です。プルアップされた入力にスイッチをつなぐとスイッチの状態をすることができるため、非常にシンプルに信号のやりとりができます。
SORACOM LTE-M Button Enterpriseも同じ仕組みでプルアップされた入力をもつ接点入力デバイスです。

https://soracom.jp/store/5207/

## データ入出力インターフェース
これまでGPIOについて述べてきましたが、GPIOでは0と1。つまり1bitのデータしか送受信できません。これでは非常に不便ですので、このGPIOをベースにバイト単位でデータのやり取りを可能するインターフェースが様々生まれてきました。

### シリアルインターフェースとパラレルインターフェース
データ入出力インターフェースには大きく分けて二種類。シリアルインターフェースとパラレルインターフェースが存在します。

* パラレルインターフェース
 * 各入出力端子を1bitとしてそれを必要なバイト数分だけ並列に接続するインターフェース
 * 代表例：PCI(PCIeは違うよ)
* シリアルインターフェース
 * 入出力端子に1bitずつ連続でデータを送信するインターフェース
 * 代表例：UART、I2C、USB

### パラレルインターフェースの衰退
パラレルインターフェースでは物理的な配線を増やすことで同時に複数のbitを送信できるため性能面で優れた仕様でした。しかし、それは時代とともに大きな弱点となっていき、今では限られた場面でしか使われていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/950f6f1a-0d16-d3d0-3980-cc7dca0984e8.png)

１つ目の変化は大容量化です。昔はCPUやメモリが8bitで動いていた時代はバス幅も8bitであったため、それほど多くの配線が必要ではありませんでした。しかし、8bit→16bit→32bit→64bitとバス幅が増えるにしたがって配線数も増え、コストとスペースの問題が顕著になってきました。
２つ目は高速化です。パラレルインターフェースは全ての配線から同時にデータを受信することを前提とした仕組みです。データ送信が数kHz程度であれば信号のスピードに対して十分に遅かったので問題はありませんでした。しかし、周波数が高くなるにつれ、各配線の長さの差や形状、周囲の物質の違いといった影響による信号到達の時間差が無視できない問題発生。さらに配線が増加したことでクロストーク(信号が近くの配線にノイズとして影響する現象)も多く発生し、通信エラーが急増しました。
以上の理由から一般的なインターフェースはシリアルインターフェースが優勢となり、多くの場面で使われるようになりました。

## UART
では、代表的なインターフェースとしてはUARTをご紹介します。
非常によく使われているインターフェースで、非常にシンプルな仕様のシリアルインターフェースです。

### UARTの物理接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/66ffd6f6-2380-ece5-6ca4-c59902775e0f.png)
UARTは送信を行うTX信号と受信を行うRX信号の2本の信号線を必要とします。それぞれのデバイスのTXとRXをつなぐ必要があるのですが、初めての方はTX、RX同士を接続してしまい通信ができないというケースを良く見ますね(笑)。

### UARTの信号
UARTは送信と受信を別々の配線で行うため、全二重通信が可能です。信号を同期するクロックがないため調歩同期方式(非同期方式)での通信となりますので、事前にそれぞれのデバイスでボーレートをあわせて通信速度を同じにしておく必要があります。
全二重通信や同期方式について、もっと優しく解説してほしいよーという方がいればまた記事にするかもしれません（笑）。

https://ja.wikipedia.org/wiki/%E8%A4%87%E4%BF%A1#%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F%E3%81%AE%E7%A8%AE%E5%88%A5

https://ja.wikipedia.org/wiki/%E5%90%8C%E6%9C%9F%E6%96%B9%E5%BC%8F#%E8%AA%BF%E6%AD%A9%E5%90%8C%E6%9C%9F%E5%BC%8F

プロトコルは非常にシンプルです。非通信時は信号ラインは常にHigh状態を保っており、通信開始時にはスタートビットと呼ばれるLow信号を1bit出力します。そのスタートビットのあとにあらかじめ決めておいた長さのデータビットを送ります。このデータビットが送信したいデータになります。データビットの後ろにパリティビットを付与し、最後に通信終了を示す。ストップビットとしてを1-2bitのHigh信号を出力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37160/6a24f566-3263-461b-6738-127672afa29a.png)

UARTは非常にシンプルなプロトコルなので、専用のインターフェースがなくてもGPIOを利用してソフトウェア的に実装することも十分に可能です。
年末の自由研究的にトライしてみるのも面白いのではないでしょうか？

#　まとめ
いかがでしたでしょうか。
本記事ではデバイスのインターフェースの基本となる部分を初心者でも簡単にわかるように解説しました。
他にはI2CやUSBといったよく使われているインターフェースがたくさんあるので、もし反響が大きければまた続きを書いてみようと思います（笑）。

最後まで読んでいただい方、ありがとうございました。
引き続き、株式会社ソラコム Advent Calendar 2021をお楽しみください。
ありがとうございました〜