Raspberry Pi PicoでPicoMite(MMBasic)を使う〜I2CデバイスのADT7410で温度計測

ADT7410を使用した温度センサーモジュール[秋月電子通商のAE-ADT7410](https://akizukidenshi.com/catalog/g/g106675/)をRaspberry Pi Picoに接続し、温度測定するプログラムを作成する。
# センサーの接続
ADT7410センサーモジュールとRaspberry Pi Picoを下表に示すように接続する。

| センサーのピン | Picoのピン（物理ピン）  |
| :-----: | :------: |
|   VDD   | 3V3(37)  |
|   SCL   | GP17(22) |
|   SDA   | GP16(21) |
|   GND   | GND(38)  |

実体配線図を以下に示す。

<!-- ここに実体配線図 -->
![ADT7410-Pico_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/388433e0-96a6-4462-b2b9-087b9bc2d1d7.png)


## ADT7410について
ADT7410は13/16 ビットADC を内蔵しており、測定した温度を13ビットあるいは16ビットデータとして出力する。それぞれの先頭ビットは符号ビットであるため、符号ビットの値によって温度の計算が変わる。
また、13ビット設定時は分解能が0.0625℃(1/16)、16ビット設定時の分解能は0.0078℃(1/128)になっている。

I$^2$Cチャンネルからのデータの受信はバイト単位なので2バイト分のデータを受取り、シフト演算で13ビットあるいは16ビットの値に変換する必要がある。
### 13ビットデータからの温度計算

13ビットデータの場合の計算式を以下に示す。
- $正の温度=読み取ったデータ/16$
- $負の温度=(読み取ったデータ - 8192)/16$
温度の正負判定はADT7410からのデータは2の補数なのでデータの最上位ビット（MSB）が1か否かで判断できる。13ビット出力の場合、4096以上の値が負数である。
### 16ビットデータからの温度計算

16ビットデータの場合の計算式を以下に示す。
- $正の温度=読み取ったデータ/128$
- $負の温度=(読み取ったデータ - 65536)/128$
16ビット出力の場合、読み取ったデータが32768以上の値が負数である。
# 温度データの読み取りと温度の計算プログラム
## 処理手順

MMBasicでI$^2$Cデバイスからデータを読み込み、利用する手順は次の通り。
- `SETPIN`コマンドでI$^2$CのSDAとSCLに割り当てるピンを指定する
- `I2C OPEN`コマンドでI$^2$Cチャンネルを開く
- `I2C READ`コマンドでI$^2$Cチャンネルからデバイスのデータを読み込む。
- 取得したデータを処理する。ここでは温度データへの変換処理とコンソールへの出力。
- `I2C CLOSE`コマンドでI$^2$Cチャンネルを閉じる

## MMBasicでのプログラム
以下に手順にしたがったコードを示す。ADT7410の出力はデフォルトの13ビットである。
```BASIC
DIM data%(2), raw%, temp!　　　　　　　　　' Define variables
SETPIN GP16, GP17, I2C                  ' Set I2C pins
I2C OPEN 400,100                        ' Open I2C channel 1
I2C READ &H48, 0, 2, data%()            ' Read data from ADT7410
raw% = data%(0) << 8 Or data%(1)        ' Convert read data
raw% = raw% >> 3
IF raw% >= 4096 THEN raw% = raw% - 8192 ' Converte value
temp! = raw% / 16.0
PRINT temp!                             ' Print temperature
I2C CLOSE                               ' Close I2C
```

1行目：DIMは変数宣言、変数名の接尾語はデータ型を示している。
- data%(2) ：2つの要素を持つ整数型配列
- raw% ：ADT7410から読み取ったデータそのものを保存する整数型の変数
- temp! ：ADT7410空読み取ったデータから計算した温度データ補を保存する浮動小数点型の変数
2行目：`SETPIN`コマンドでGP16ピンをデバイスのSDAに、GP17ピンをデバイスのSCLに、I2Cのチャンネル1で接続することを指定している。I2CはI2Cチャンネル1を示し、チャンネル2はI2C2と表記する。
3行目：`I2C OPEN`でI2Cチャンネル1をクロック周波数400kHz、タイムアウト時間100ミリ秒で開く
4行目：`I2C READ`コマンドでI2Cアドレス＆H48（16進数）から、通常動作で2バイト分のデータを読み取り、配列data%に順に格納する。
5行目：I2Cデバイスから読み取った2バイトのデータを結合して16ビットのデータにするために最初に読み取った1バイト（8ビット）のデータdata%(0)を左へ8ビットシフトし、2番目に受取ったデータと論理和を求め、変数raw%に格納。
6行目：ADT7410のデフォルトの出力データは13ビットなので16ビットにしたデータを右へ3ビットシフトする。
7行目：ADT7410から読み取ったデータが負数の場合は8192を引く。
8行目：分解能が0.0625℃なのでその逆数で割り、温度を求める。
9行目：求めた温度を表示。
10行目：I2Cチャンネルを閉じる。
## MMBasicのデータ型

MMBasicのデータ型は次の表に示す種類がある。接尾語を省略した場合、倍精度浮動小数点数となる。

| 接尾語 | 型           |
| :-: | ----------- |
|  %  | 64ビット符号付き整数 |
|  !  | 倍精度浮動小数点数   |
|  $  | 文字列         |

接頭語&H、＆O、&Bをつけて16進、8進、2進数を定義すると64ビット符号なし整数を作ることができる。

## 16ビット出力でのプログラム

ADT7410の出力をデフォルトの13ビットから16ビットに変更したプログラムを以下に示す。

```BASIC
DIM data%(2), raw%, temp!　　　　　　　　　  ' Define variables
SETPIN GP16, GP17, I2C                    ' Set I2C pins
I2C OPEN 400,100                          ' Open I2C channel 1
I2C WRITE &H48, 0, 2, &H03, &H80          ' Set 16bit output
I2C READ &H48, 0, 2, data%()              ' Read data from ADT7410
raw% = data%(0) << 8 Or data%(1)          ' Convert read data
IF raw% >= 32768 THEN raw% = raw% - 65536 ' Converte value
temp! = raw% / 128.0
PRINT temp!                               ' Print temperature
I2C CLOSE                                 ' Close I2C
```
13ビット出力のプログラムとの違いはADT7410の出力を16ビット化するために4行目の`I2C WRITE`コマンドでADT7410のレジスタ＆H03に16ビット出力するコード＆H80を書き込み、7、8行目で16ビット出力に合わせた温度データの算出している。
# 参考：OPTIONの設定確認とリセット

システム用に使用されてるI2CチャンネルなどのOPTIONコマンドによる設定はコマンドプロンプトで`OPTION LIST`コマンドを実行して確認できる。

```SHELL
> OPTION LIST
PicoMite MMBasic RP2040 Edition V6.00.01
OPTION SYSTEM I2C GP4,GP5
OPTION COLOURCODE ON
```
OPTIONによる設定をすべて削除するには`OPTION RESET`コマンドを使用する。

```SHELL
> OPTION RESET
```