マイクロビットでUARTを使ってみる

マイクロビット2個をジャンパワイヤで繋いでUARTで文字列を送信してみます。

UARTというのはUniversal Asynchronous Receiver/Transmitter(汎用非同期送受信機)の頭文字を取ったもので、2本のラインでシリアルデータを交換できる仕組みを指します。


※各々のマイクロビットは個別に電源を確保しているものとする


今回は上の図のようにマイクロビット2個を繋いで、UARTを試してみます。



送信側のボタンAを押すと、受信側に 0 という値を送信、ボタンBを押すと 1 という値を送信し、受信側では受け取った値をディスプレイに出力してみます。




今回はマイクロビットをシリアルデータの送信用と受信用に分けてコードを作成します。


送信用

from microbit import *

uart.init(baudrate=9600, tx=pin0, rx=pin1)

while True:
	if button_a.is_pressed() or button_b.is_pressed():
		# ボタンを押したか?を可視化するためにディスプレイにチェックを表示します
		display.show(Image.YES)
		if button_a.is_pressed():
			msg = b'0'
		else:
			msg = b'1'
		uart.write(msg)
		sleep(1000)
	else:
		display.show(Image.ASLEEP)

上のコードでは、送信用のマイクロビットのボタンAを押すと、受信用の方に 0 の値を送信し、ボタンBを押すと、 1 の値を送信します。


送信時の値の

msg = b'0'

は文字列型のデータをバイト型に変換しています。

マイクロビット等のマイコンではデータの送信時はバイト型の値に変換する必要があります。




続いて、受信側のコードを作成します。


from microbit import *

uart.init(baudrate=9600, tx=pin0, rx=pin1)

while True:
	# UART経由で何らかの値を受信できたか?を調べる
	if uart.any():
		# ボタンを押したか?を可視化するためにディスプレイにチェックを表示します
		display.show(Image.YES)
		msg = uart.read()
		
		# 値が取得できているか?念の為に確認
		if msg != None:
			display.scroll(msg)
		sleep(1000)
	else:
		display.show(Image.ASLEEP)

各々のマイクロビットにコードをフラッシングした後に送信側のマイクロビットの方でボタンAとボタンBを押し、受信側の方に何らかの動作が発生することを確認します。

動作は冒頭付近のようにボタンAを押した時には 0 が表示され、ボタンBを押した時には 1 が表示されることを確認します。


コードの解説の前に、今回受信側で得た値をmicro:bit Python Editorのシリアルを表示を使ってみようで触れた方法で確認を行わなかった理由ですが、マイクロパイソンのエディタのシリアルの表示でもUARTを用いて受信していて、今回のジャンパワイヤ形式とかぶります。


uart.init(baudrate=9600, tx=pin0, rx=pin1)

今回は上記のコードでジャンパワイヤ経由の初期化をしていて、エディタの方のシリアルとの繋がりが切断されます。


この内容を踏まえた上で、マイクロビットのUARTについてを見ていくことにしましょう。




uart.init(baudrate=9600, tx=pin0, rx=pin1)

上記のUARTの初期化のコードを改めて見てみます。


はじめにbaudrate(ボーレート)ですが、一秒間にどれだけの変復調できるか?の単位になります。

変復調というのは何かですが。

上の図の信号の送信で、HIGH(上向きの矢印)とLOW(下向きの矢印)が合わさって、1 とします。

初期化の際にボーレートを9600にしましたが、これは変復調が1秒間に9600回発生することが出来るということになります。

ボーレートは接続する二つのマイクロビットで同じにする必要があります。


マイクロビットのUARTのボーレートでは9600, 14400, 19200, 28800, 38400, 57600, 115200 が用いられるそうです。

microbit.uart.init - UART — BBC micro:bit MicroPython 1.0.1 ドキュメント




続いて、TXとRXはTXがTransmitterで送信になり、RXがreceiverで受信の意味になります。

マイクロビット同士に限らず、二つのマイコン間でUARTを用いる場合は、片方のTXともう片方のRX、片方のRXともう片方のTXとクロスするようにワイヤをつなぎます。



今回の回路も左側のマイクロビットのTXと右側のマイクロビットのRXが繋がり、左側のマイクロビットのRXと右側のマイクロビットのTXが繋がるようになっています。

上記の規則を把握していれば、マイクロビットとラズベリーパイPico Wと繋いでUARTでやり取りをするといったことも可能になります。


余談ですが、マイクロビットからUSB経由でパソコン等のシリアルデータを送信したい場合は、

uart.init(baudrate=9600, tx=None, rx=None)

UARTの初期化時にtxとrxの値をNoneにすれば良いです。




今回のコードですが、何度か実行をしていると、



受信側のディスプレイで意図していない値が出力されることがあります。

? が出力されたり、他の数字が出力されたりします。


おそらくこれは受信側の方でシリアルデータの受取に失敗したことが要因である可能性が高いです。

シリアルデータが正しく送受信できないと困ることが多いので、解決策を模索していくことにします。




はじめにUARTについての仕様を改めて確認してみます。


ドキュメントでUARTの初期化に関するコードを見てみますと、

 microbit.uart.init(baudrate=9600, bits=8, parity=None, stop=1, *, tx=None, rx=None)

bits(ビット)、parity(パリティビット)とstop(ストップビット)の指定があります。


UARTで 0 という値を送信するとして話を進めていきます。

マイコン間のUARTではデータの転送はバイト型に変換して行う必要があります。


バイト型というのは、例えば 0 という値であれば、ASCIIコードで 0x30 が割り当てられています。

数字の前の 0x は以後の値(今回であれば30)が16進法で表記されているという意味になりまして、0x30 を10進法では 48 に該当します。


0x30 は8ビットの記述で 00110000 として表すことができ、UARTではこの値を送信します。

※上記内容はinit時のbits=8の箇所が該当


UARTで 0 という値を送信する時、



上記のようにスタートビット + 送信したい値 + パリティビット(任意) + ストップビットの構成で送信されます。

UARTでは送信していない状態の時はHIGHにしておいて、何らかの値を送信する時に開始の合図として、0 の値を送信します。

受信側では 0 を受け取った時にその後に続く信号を実際の値として認識します。

※注意として、上の図は受信側になるので値の並び方が逆順になるらしい。


今回の例ではbits=8で設定していますので、受信側ではスタートビットの後の8ビット分を受信したい値だと判断します。


8ビットの値の後のパリティビットですが、データ送信時の誤り検出符号として用いられます。

マイクロビットのパリティの設定にはNone(なし)、microbit.uart.ODD(奇パリティ)とmicrobit.uart.EVEN(偶パリティ)があり、奇パリティで話を進めると、送信したデータのHIGHが奇数であれば 0 、偶数であれば 1 となります。


今回の00110000はHIGH(1)が 2 の偶数であるため、パリティ・ビットは 1 になります。


今回紹介しましたUARTの初期化時のパラメータをいじれば、値の送信時の精度を上げることが可能です。