概要
SPIデバイスをmicro:bitに接続してみる。SPIデバイスにはADコンバーターMCP3008を使う。10ビット、8チャンネルのADCである。
micro:bitにもアナログ入力はあるので、アナログ入力の数を増やしたい場合を除けばADコンバーターを外づけする意味はない。SPIバスの動作を確かめるだけである。
下の回路で試してみる。
- SPI関連の端子はデフォルトのままとする。!CS端子にはP16を使うことにする。
- SPIモードは0(0,0)とする。

spiモジュールの使いかた
- 初期化:
microbit.spi.init(baudrate=1000000, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)
(引数は全部オプション) - read操作:
microbit.spi.read(バイト数)
- write操作:
microbit.spi.write(バイトバッファー)
- write/read操作:
microbit.spi.write_readinto(書き込みバイトバッファー, 読み出しバイトバッファー)
読み書きに使う2つのバイトバッファーはサイズが同じでなければならない。両方とも同じバイトバッファーを指定してもよい。
spiモジュールを使ってMCP3008から10ビットのADC値を読み出す方法
以下の手順で3バイトをwriteして3バイトをreadし、readした3バイトの中から10ビットを取り出す。ビットの送り順はMSBファーストである。
[0]バイト目:
0b 0000 0001をwriteする。この1がスタートビットとして働く。
→同時に、ADCから1バイトが返ってくる。このバイトデータは使わない。
[1]バイト目:
ビット7でシングルエンド(1)か差動(0)か指定し、ビット6:4でチャンネル(0~7)を指定する。下の例では、シングルエンドでチャンネル0を使うので0b 1000 ----をwriteしている。
→同時に、ADCから0b ---- -0??が返ってくる。??の位置にある2ビットが10ビットデータの上位2ビットである。
[2]バイト目:
ダミーバイトをwriteする。下の例では0をwriteしたが何でもよい。
→同時に、ADCから10ビットデータの下位8ビットが返ってくる。
まとめ
まとめると次のとおりである。これで、チャンネル0に印加された電圧が10ビットにAD変換される。?で表した10ビットがそのAD変換値である。spiを使わずに独自に実装するのであればもはや8ビット単位にこだわる必要はないのでスタートビットから始めればよい。
[0]バイト目 | [1]バイト目 | [2]バイト目 | |
---|---|---|---|
マスターからスレーブへ転送するデータ | 0b 0000 0001 | 0b 1000 ---- | 0b ---- ---- |
スレーブからマスターへ転送されるデータ | 0b ---- ---- | 0b ---- -0?? | 0b ???? ???? |
1回だけADC値を読み出すためのMicroPythonスクリプト
上の手順をそのままMicroPythonで再現する。spiモジュールのおかげでえらく単純である。AD変換値を電圧値に戻してみる(要するにディジタル電圧計である)。
from microbit import *
mosi = bytearray([1, 0b10000000, 0])
miso = bytearray([0, 0, 0])
pin16.write_digital(1)
spi.init()
pin16.write_digital(0)
spi.write_readinto(mosi, miso)
pin16.write_digital(1)
print("MOSI data: %s" % ([bin(b) for b in mosi]))
print("MISO data: %s" % ([bin(b) for b in miso]))
ADdata = (raw[1]<<8 | raw[2]) & 1023
volt = ADdata * 3.23/1024.0 # 3.23はMCP3008のVREF端子の実測値。
print("AD %d, %.2f(V)" % (ADdata, volt))
実行結果



整理してクラス化した
from microbit import *
class MCP3008:
def __init__(self, CSpin=pin16):
self.CS = CSpin.write_digital
self.CS(1)
self.mosi = [bytearray([1, (1<<7)|(ch<<4), 0]) for ch in range(8)]
self.miso = bytearray([0, 0, 0])
def read(self, CH):
self.CH = CH
self.CS(0)
spi.write_readinto(self.mosi[CH], self.miso)
self.CS(1)
return (self.miso[1]<<8 | self.miso[2]) & 1023
##############
# how to use #
##############
if __name__ == "__main__":
# Initialize the microbit.spi module.
# You can also specify any of the following options:
# baudrate=1000000, bits=8, mode=0, sclk=pin13, mosi=pin15, and miso=pin14
spi.init()
# Instantiate the MCP3008 class with !CS assigned to pin16.
adc = MCP3008(CSpin=pin16)
while True:
# Get 10-bit data by converting the voltage applied to the channel 0 of MCP3008.
ADdata = adc.read(CH=0)
volt = ADdata * 3.23/1024.0
print("AD %d, %.2f(V)" % (ADdata, volt))
sleep(1000)
実行結果
参考
- http://microbit-micropython.readthedocs.io/en/latest/spi.html
- Harry Fairhead, micro:bit IoT in C, pp.139-144