M5StackシリーズATOM LiteとMCP3008を使って、MicroPythonで電圧(アナログ入力)を取得しました。
マイコン制御のとあるシステムを作ろうとしていて、最初ラズパイPicoを使おうかなと思っていましたがやっぱWIFI飛ばしたい、ATOM Liteはアナログ入力は3ch(無線不使用なら5ch)使えますが、もっとCH数が欲しい、ってことで、8chのADコンバータMCP3008を使ってみることにしました。
10bit 8ch ADコンバータ MCP3008-I/P ¥240
https://akizukidenshi.com/catalog/g/gI-09485/
MCP3008はSPIという通信規格を使うので、MicroPythonでSPIを使います。
SPIのモジュールには、ハードウェアSPIとソフトウェアSPIがあって、今回はソフトウェアSPIを使います。
ハードSPIはハードウェアが処理するため、専用の端子が決まっておりサンプリングレートが高速です。一方、サンプリングレートが低速ですが、任意のGPIO端子で使えます。
■ 配線
SPIでは通信に4つの端子を使い、配線先は以下の通り。
SCK -CLK
MISO-DOUT
MOSI-DIN
CS -CS
MCP3008のピン配列
今回は、GPIOはSCK:G22、MOSI:G23,、MISO:G19,CS:G21に割り振ったので、以下の通りに配線しました。
MCP3008 : ATOM VDD -------3V3 VREF-------3V3 VGND-------GND CLK--------G22 DOUT-------G19 DIN--------G23 CS---------G21 DGND-------GND
■ コード
以下のサイトのコードを使わせてもらいました(ちょっと簡略化)。
Raspberry Pi Pico project 2 – MCP3008
http://blog.rareschool.com/2021/02/raspberry-pi-pico-project-2-mcp3008.html
class MCP3008: def __init__(self, spi, cs): self.cs = cs self.cs.value(1) # ncs on self._spi = spi self._out_buf = bytearray(3) self._out_buf[0] = 0x01 self._in_buf = bytearray(3) def read(self, pin): self.cs.value(0) # select self._out_buf[1] = 1 | (pin << 4) self._spi.write_readinto(self._out_buf, self._in_buf) self.cs.value(1) # turn off return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2] from machine import Pin, SoftSPI from time import sleep spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(22), mosi=Pin(23), miso=Pin(19)) cs=Pin(21, Pin.OUT) cs.value(1) adc=MCP3008(spi,cs) while(True): print(adc.read(0)/1024*3.3) sleep(1)
テキトーに分圧して取得電圧を確認しましたが、ちゃんと取れていました。
より精度の高い(12bit)のADCであるMCP3204を使う場合は、配線は同じで、コードは以下のサイトを参照(もといコピー)すれば良いはずです。
MicroPythonでADC(MCP3204)を使う
https://blog.boochow.com/article/micropython-mcp3204-rpi.html
その他、参考サイト。プログラムの中身の解説は以下より。
ラズパイでADコンバーターMCP3008の使い方・SPI通信
https://101010.fun/iot/raspi-spi.html
ESP32 と MCP3008 で SPI の勉強
https://qiita.com/nanbuwks/items/9a9169a2afbad95ae7ca
ESP32 用クイックリファレンス
https://micropython-docs-ja.readthedocs.io/ja/latest/esp32/quickref.html#software-spi-bus