先日、「M5Stack」で多数(5本)のアナログ入力信号を扱う必要が生じたため、8chのADコンバータ「MCP3008」をM5Stackにつなぐ方法を確認しました(記事は こちら)。
ところで、この作業をしていてふと気付いたのですが、「マイクロビット」にはアナログ入力できる端子が6本あります。
もしも本当に、この6本の端子がアナログ信号をきちんと取得できるなら、マイクロビットとM5Stackをつなぐことで、マイクロビットをあたかも6chのADコンバータのように使えるのではないかと思いつきました。
もちろん、マイクロビットはADコンバータよりも高価格ですが、既に持っているマイクロビットを利用できることや、マイクロビットとM5Stackをつなぐだけで、基板やブレッドボードを使わなくても実現できることから、活用できる用途もあるのではないかと思います。
そんな訳で、早速試してみることにしました。
まずはマイクロビットのプログラムです。
アナログ入力端子のうち「P3」「P4」「P10」はLEDと共用なので、「最初だけ」でLEDを無効にしておきます。
1秒ごとに6つの端子のアナログ値を読み取り、シリアル通信で書き出します。
M5Stackのスケッチはこちらです。
シリアル通信で受信したら、読み込んだ値をLDC画面に表示します。
#include <M5Stack.h>
void setup() {
M5.begin();
Serial2.begin(115200, SERIAL_8N1, 22, 21);
M5.Lcd.setTextSize(2);
}
void loop() {
if(Serial2.available()) {
String values = Serial2.readStringUntil('\n');
int pos1 = values.indexOf(',');
int pos2 = values.indexOf(',', pos1+1);
int pos3 = values.indexOf(',', pos2+1);
int pos4 = values.indexOf(',', pos3+1);
int pos5 = values.indexOf(',', pos4+1);
int pos6 = values.indexOf(' ');
String value0 = values.substring(0, pos1);
String value1 = values.substring(pos1+1, pos2);
String value2 = values.substring(pos2+1, pos3);
String value3 = values.substring(pos3+1, pos4);
String value4 = values.substring(pos4+1, pos5);
String value5 = values.substring(pos5+1, pos6);
int a0 = value0.toInt();
int a1 = value1.toInt();
int a2 = value2.toInt();
int a3 = value3.toInt();
int a4 = value4.toInt();
int a10 = value5.toInt();
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0);
M5.Lcd.printf("[A0] %d\n", a0);
M5.Lcd.printf("[A1] %d\n", a1);
M5.Lcd.printf("[A2] %d\n", a2);
M5.Lcd.printf("[A3] %d\n", a3);
M5.Lcd.printf("[A4] %d\n", a4);
M5.Lcd.printf("[A10] %d\n", a10);
}
}
「M5:bit」というマイクロビット用ソケットを使い、マイクロビットとM5StackをGROVEケーブルでつなぐだけでできあがりです。
M5StackとADコンバータ「MCP3008」をつなぐと以下のようになりますので、これに比べるとかなりスッキリしました。
動作確認のため、ブレッドボードに6個の可変抵抗を並べて6種類の中間電位をつくり、それらをマイクロビットのアナログ入力端子につなぎます。
以下のとおり、M5StackのLCD画面に各端子のアナログ値が表示されます。
これで、マイクロビットのアナログ入力端子で取得したアナログ値を、M5Stackで活用できることが確認できました。
つづいて、マイクロビットで取得したアナログ値が精度的に問題ないか、確認してみます。
可変抵抗で中間電位をつくり、それをマイクロビットの6本のアナログ入力端子、およびMCP3008の「CH0」の、計7箇所につなぎます。
それぞれで取得したアナログ値を比較します。
M5Stackのスケッチはこちらです。
シリアル通信でマイクロビットから6つのアナログ値を受信したら、MCP3008でもアナログ値を取得し、合計7つの値をシリアルモニタに出力します。
#include <M5Stack.h>
#include "MCP3004.h"
const int MCP3004_CS = 2;
MCP3004 mcp3004(MCP3004_CS);
void setup() {
M5.begin();
SPI.begin();
mcp3004.begin();
Serial2.begin(115200, SERIAL_8N1, 22, 21);
}
void loop() {
if(Serial2.available()) {
String values = Serial2.readStringUntil('\n');
int pos1 = values.indexOf(',');
int pos2 = values.indexOf(',', pos1+1);
int pos3 = values.indexOf(',', pos2+1);
int pos4 = values.indexOf(',', pos3+1);
int pos5 = values.indexOf(',', pos4+1);
int pos6 = values.indexOf(' ');
String value0 = values.substring(0, pos1);
String value1 = values.substring(pos1+1, pos2);
String value2 = values.substring(pos2+1, pos3);
String value3 = values.substring(pos3+1, pos4);
String value4 = values.substring(pos4+1, pos5);
String value5 = values.substring(pos5+1, pos6);
int a0 = value0.toInt();
int a1 = value1.toInt();
int a2 = value2.toInt();
int a3 = value3.toInt();
int a4 = value4.toInt();
int a10 = value5.toInt();
int mcp0 = mcp3004.read(0);
Serial.printf("%d, %d, %d, %d, %d, %d, %d\n", a0, a1, a2, a3, a4, a10, mcp0);
}
}
シリアルプロッタでグラフ表示した結果はこちらです。
水色の波形がMCP3008の取得値、その他がマイクロビットの6つのアナログ入力端子の取得値です。
マイクロビットの各端子の取得値はほぼ完全に一致しています。また、MCP3008の取得値は波形がガタガタしていますが、マイクロビットの取得値とほぼ一致しています。
ちなみに、M5Stackの3V電源はノイズが大きく、MCP3008の波形がガタガタしているのはそれが原因と想定されます。
一方、マイクロビットへは、M5StackからGROVEケーブルで5Vが供給されており、それを「M5:bit」に搭載されている電源レギュレータで3.3Vに落として利用しています。
よって、マイクロビットの3V電源はノイズが小さく、そのためアナログ値の波形も安定しているのではないかと思われます。
試しに、「M5:bit」で生成した3V電源をMCP3008に供給してみました。
結果は以下のとおりで、マイクロビットの6つのアナログ端子の波形とMCP3008の波形はほとんど同じになりました。
マイクロビットのアナログ入力端子が精度的にも問題ないことが確認できました。
なお、私がM5Stack、M5StickCの使い方を習得するのにあたっては、以下の書籍を参考にさせていただきました。
ごく基本的なところから、かなり複雑なスケッチや、ネットワーク接続など、比較的高度なものまで、つまづかずに読み進めていけるような構成になっており、大変わかりやすい本です。
このサイトで書いている、M5Stackシリーズ(M5Stack、M5StickCなど)に関するブログ記事を、「さとやまノート」という別のブログページに、あらためて整理してまとめました。
他のM5Stackシリーズの記事にも興味のある方は「さとやまノート」をご覧ください。