M5stackのUNITシリーズに「UNIT ANGLE」というポテンショメータがあります。UNIT ANGLEには可変抵抗が内蔵されていて、つまみを回す角度に応じた電圧を出力します。M5STACKのPORT.Bの12bitA/Dで回した量を数値化します。
M5stackのUNITとは
M5stackにはGroveケーブルで接続できる外部ポートを持っており、「UNIT」と呼ばれるセンサやアクチュエータを接続することができます。PORT.AはI2C通信ポート、PORT.BはADC/DACポート、PORT.CはUARTのポートになっています。

M5stackのBASE
M5CORE2本体にはPORT.Aしかありませんが、標準のBASEから「BASE M5GO BOTTOM2」に交換することによりPORT.BおよびPORT.Cを使うことができるようになります。UNIT ANGLEはPORT.Bを使います。

UNIT ANGLEとは
UNIT ANGLEの中身は下記の回路図のようになっており、M5CORE2本体から5Vが供給され、4.7kΩの抵抗を介して10kΩの可変抵抗が接続されています。4.7kと10kで分圧しているのはADC入力の最大電圧が3.3Vのためと思われます。OUT端子はオープンになっています。IN端子の電圧を実測すると0Vから3.4Vまで変化しました。回路から電圧を計算してみると、5V×10k/(10k+4.7k)≒3.4


つまみの角度と信号電圧
つまみを左端から右端いっぱいまで回し、つまみの回転角度とAD値を計測しました。左端が0°でAD値は4095、右端が300°でAD値が0になりました。角度は目分量の値です。左端付近と右端付近、つまり回し始めと終わりの辺りでは値が変化しない領域がありました。それ以外の領域は角度とAD値はリニアに変化しており、いわゆるBカーブの可変抵抗になっているようです。

プログラムは下記です。ArduinoIDEのANGLEというサンプルスケッチを参考にしました。単純にAD値を表示させるだけだとAD値が不安定で落ち着かず、表示値がパラパラ動いてしまうのでヒステリシスがついています。実験しながらいいところの値に設定しました。フル回転角の2%は動かないと値を再表示しないようにしました。12bitで4095なのでAD値としてざっくり80としました。フル回転角300°で6°です。これでだいぶ落ち着きました。
PORT.Bの「IN」のAD入力は、M5CORE2のBUSのG36に接続されていますので、setup()ルーチンの中で関数pinMode()によりG36を入力に設定し、loop()ルーチンの中でanalogRead()にてAD値を取得します。delay()の設定値ですが、用途によるかと思いますが人間がつまみを回して調整する操作であれば100msで十分かと思います。
#include <M5Core2.h>
int G36_adc = 36; //PORT.BはPIN G36に接続されている
int ad = 0; //AD値の初期化
int ad_old = 0; //前回AD値の初期化
void setup() {
M5.begin(); //M5Core2初期化
pinMode(G36_adc, INPUT); //G36のPINモードを入力設定
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(0, 0);
M5.Lcd.print("UNIT ANGLE AD Value:");
}
void loop() {
ad = analogRead(G36_adc); //G36のAD値読み出し
M5.Lcd.setCursor(0, 25);
if (abs(ad - ad_old) > 80) { //ヒステリシス
M5.Lcd.fillRect(0, 25, 100, 25, BLACK);//画面表示値クリア
M5.Lcd.print(ad);
ad_old = ad;//退避
}
delay(100);
}
Code language: C++ (cpp)
まとめ
UNIT ANGLEを使って、つまみの回転角に応じたAD値を取得することができました。取得したAD値により何かアクチュエータをコントロールできるかと思いますので今後何かに使ってみようと思います。

