FT232HとMCP3004/MCP3008でPCにアナログ入力

# Windows PCにPython、FT232H、MCP3004の組み合わせでアナログ信号処理


GPIOボードFT232HとACコンバータMCP3004の組み合わせ。
BLINKA使用

※ラズパイの記事や、古い作法しか見つけられなかったため、メモとして残す。
※書いてる人は普段は電気/電子回路やらない人です。

## FT232Hについて
秋月：https://akizukidenshi.com/catalog/g/gM-08942/
本家：https://learn.adafruit.com/adafruit-ft232h-breakout
USB接続でGPIO入出力ポートを設けるモジュール。
単純なデジタル信号だけでなく、I2CとSPI、2種のシリアルフォーマットも利用できる。

FT232HとCircuitPython、BLINKAのインストールについては本記事では省略
↓　adafruitの「setup」に倣った。
https://learn.adafruit.com/circuitpython-on-any-computer-with-ft232h/setup

## MCP3004 について
秋月：https://akizukidenshi.com/catalog/g/gI-11987/
製品説明書：https://akizukidenshi.com/download/ds/microchip/mcp3008.pdf
10bit X 4チャンネル、SPIシリアル出力のADコンバーター。
姉弟製品に2チャンネルのMCP3002や8チャンネルのMCP3008がある。
※シリアル出力ということは信号線が1本ということ、「10bitだから10ポート」ではない。
* 5V 電源での最大サンプルレート 200 ksps /　3Vでは100ksps程度。
* 最大クロックは1~3MHzあたり（？）
* サンプリングが実用的クロックは（使用環境次第で）10kHz程度まで下がる（説明書のp22）
* ※高レートほど消費電力が増えるような？


### FT232Hへの接続
とにかく7～14番はすべて繋いでしまえ！　（※厳密には12番はアナログ入力のグランドですが、ここではアナログ信号の電源もFT232Hからとってる前提。）
・電源V_DDはFT232Hの5V、（3.3Vでも可のはず）
・参照電圧V_REFは電源と同じ、
・クロックは当然接続必須だろう。
・チップセレクトはどういうものかよくわからないがCircuitPython側で必須っぽい。FT232HのD5に繋いだ。
・SerialDataOutは、今回は入力信号だけなので繋がなくてもよいのか？とか思たけど、これ繋がないと動作しない感じだった。
↓ SPIのSCLK、MOSI、MISOについてはBlinkaで指定されているから迷うこともない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469875/b21d8d1f-1788-1db3-9aa0-f6689829ea0c.png)

※CSチップセレクトについて、恐らく（実態と違うかもしれないがコンセプト的には）、複数のSPI/I2Cデバイスでクロック等を共有し、CSで処理対象を切り替えるといった使い方をする。のかな（？）



## CircuitPythonのMCP3XXXシリーズのバンドルを利用
ヘルパーというのかドライバーというのかしらないけど、要するに必要なものはすでに用意されているということ。
https://github.com/adafruit/Adafruit_CircuitPython_MCP3xxx/tree/df768ac18242e15077d96dd4aa6fc714de5c9133/adafruit_mcp3xxx

``` : pipで追加インストール
> C:\**\python.exe  -m pip install adafruit-circuitpython-mcp3xxx
```

## サンプルコード

MCP3004の0番ポート（1番ピン）にアナログ信号を入力する場合のサンプルです。

``` : Python3
#!python3

import os
os.environ['BLINKA_FT232H'] = '1' #Setting Environmental Variable

import board
import busio
import digitalio

import adafruit_mcp3xxx.mcp3004 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn

##  https://github.com/adafruit/Adafruit_CircuitPython_MCP3xxx/blob/df768ac18242e15077d96dd4aa6fc714de5c9133/adafruit_mcp3xxx/mcp3004.py
##  ( https://learn.adafruit.com/circuitpython-on-any-computer-with-ft232h/spi )

##  create library object using our Bus SPI port
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

# create the cs (chip select)
cs = digitalio.DigitalInOut(board.D5)

# create the mcp object
VR=5.0  ##  3.3
mcp = MCP.MCP3004(spi, cs, ref_voltage=VR )

# create an analog input channel on pin 0
chan = AnalogIn(mcp, MCP.P0)

print("Raw ADC Value: %d / (Max%d) "%( chan.value>>6, 2**10) )
print("ADC Voltage: %g / (Max%g) V"%(chan.voltage, VR) )
```

※ ADコンバータMCP3004の分解能は10bitですが、PythonAPI上（MCP.MCP3004の中）で16bitに換算された値がchan.valueに格納されてます。
上のサンプルでは6ビットシフトして10bitに戻した値を表示しています。


# ロジアナ
なんか妙に遅いので
ロジックアナライザで信号みてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469875/4ab49521-9188-8958-b0d3-cd71761e18b5.png)

黄緑色チャンネル/橙色６角形が MISO（MPC3008の出力側）
ADの値は　509 = 0111111101　（値が一個ずれてるのはクロックの設定がまずいのかな）
0CHで非差動
（青色チャネル/黄緑６角形 MOSIの「１」2個はStart信号1と非差動の1で、直後の「0」3個がCH番号です。）
１個の値取得に3バイト分24単位ほど通信するようですね。
SPIクロック2MHz弱で作動している模様。cs0._pin.mpsse_gpio._controller.frequency　の値2000000と一致。（？）
 24 / 2M = 12 マイクロ秒 くらい。

ただし......

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469875/abc4581d-e4f1-6c8f-833c-4c76a2fecafa.png)


↑ このように CS が落ちてからと、CS 上がるまでのタイムラグが長い。
全体で0.8ミリ秒くらいかかってます。
ということは1チャンネルのデータ取得を反復したときに1000Hz強くらいのサンプリングレートになる。
遅いのこの部分か。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469875/95c5e69a-0a70-2906-a085-474726c521e1.png)

↑　2 データ続けて取得した場合