ESP32 にはホールセンサーが内臓されています。 ホールセンサーとはホール効果を利用して磁場を検出するセンサーで、磁気センサー、電流センサー等として使われています。

ESP32(ESP32-DevKitC)でホールセンサーを使ってみる

 ESP32(ESP32-DevKitC) でホールセンサーを使うのは非常に簡単で、 hallRead() のコマンドだけでホールセンサーの値を取得できます。

 早速試してみました。

 ESP32の開発環境が整ったArduino IDEを使います。 開発環境の構築はこちらで書きました。

void setup() {
  Serial.begin(115200);
}

void loop() {
  // ホールセンサーの値を取得してシリアルモニタに出力
  Serial.println(hallRead());
  delay(1000);
}

 ESP32(ESP32-DevKitC) とPC をUSB でつなぐだけで、他に配線は必要ないです。

 このスケッチを実行するとシリアルモニタにに1 秒毎に数値が出力されます。 この掲示板の情報によると数値はmT 単位らしいです。 地磁気の強さが0.05mT 程なので方位磁石として使うことはできそうにないです。

 数値にかなりバラつきがあるように見えます。

広告

ESP32 ホールセンサーの値をWiFi 経由でEXCELに取得する

 ホールセンサーの値をWiFi 経由でEXCEL に取り込むようにしました。

 WiFi を使ったESP32 とEXCEL の通信方法は過去記事にあります。

スケッチ

 ESP32(ESP32-DevKitC) のスケッチは以下の通りにしました。

#include <WiFi.h>

const char* ssid     = "yourSSID"; //実際のSSIDにする
const char* password = "yourpassword"; //実際のパスワードにする

WiFiServer server(80);

// WiFi経由でコマンドを受信する
String receiveCommand(WiFiClient client) {
  String currentLine = "";  
  while (client.connected()) {
    if (client.available()) { 
      char c = client.read();
      if (c == '\n') {
        return currentLine;
      } else if (c != '\r') {
          currentLine += c;
      }
    }
  }
  return currentLine;
}

// ホールセンサーの値をWiFi経由で送信
void sendData(WiFiClient client) {
  while (client.connected()) {
    double hallData = 0;
    // n回測定の平均を出す
    int n = 100;
    for(int i = 0; i < n; i++) { 
      hallData += hallRead();
    }
    hallData /= n;
    // プログラム開始からの時間(ミリ秒)とホールセンサーの値
    String sData = String(millis()) + " ," + String(hallData);
    client.println(sData);
    Serial.println(sData);
    if (client.available()) { 
      String command = receiveCommand(client);
      Serial.println(command);
      if (command == "END"){ // "END"コマンドを受信したら終了
        break;
      }
    }
  }
}

void setup()
{
    Serial.begin(115200);
    delay(10);
    // WiFi接続
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("WiFi connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();
}

void loop(){
 WiFiClient client = server.available();

  if (client) {
    Serial.println("New Client.");
    while (client.connected()){
      String command = receiveCommand(client);
      Serial.println(command);
      if (command == "MEAS"){ // "MEAS"コマンドを受信したら測定開始
        sendData(client);
        client.stop();
        Serial.println("Client Disconnected.");
        break;
      }
    }
  }
}

 ”MEAS” コマンドを受け取るとホールセンサーの値を連続して送信し、”END” コマンドで停止するスケッチです。

 測定の値にバラつきがあるようなので何回かの測定値の平均を出すようにしました(29 行目から)。

VBAプログラムの作成

 ”EXCEL開発タブの表示”から”参照設定”まで以前の記事を参考に行います。

 この記事で書いた通りに、ユーザーフォームを追加し、以下のコード書きます。

Private Sub CommandButton1_Click()
    StopMeas = True
    Me.Hide
End Sub

 標準モジュールに次のコードを記述します。

Private Declare Sub Sleep Lib "KERNEL32.dll" (ByVal dwMilliseconds As Long) '32bit版EXCEL
'Private Declare PtrSafe Sub Sleep Lib "KERNEL32.dll" (ByVal dwMilliseconds As Long) '64bit版EXCEL
Public StopMeas As Boolean

Sub GetHallData()
    ' VISA COMオブジェクトを作成し接続を設定
    Dim RM As New VisaComLib.ResourceManager
    Dim ESP As New VisaComLib.FormattedIO488
    '変数宣言
    Dim HallData As Variant
    Dim i As Long
    'シートをクリア
    Worksheets("Sheet1").Range(Cells(2, 1), Cells(Rows.Count, 3)).Clear
    
    '接続
    Set ESP.IO = RM.Open("TCPIP0::192.168.0.0::80::SOCKET") ' ESP32と接続 VISAアドレス"TCPIP0::192.168.000.000::80::SOCKET"はConnection Expert で確認
    ESP.IO.Timeout = 5000
    
    StopMeas = False
    UserForm1.Show vbModeless ' ユーザーフォームをモードレスで表示
    
    '終端文字を識別し読み込みを終了させる
    ESP.IO.TerminationCharacter = 10
    ESP.IO.TerminationCharacterEnabled = True
    
    ' ESP32に"MEAS"コードを送る。
    ESP.WriteString "MEAS"
        
    ' データを取得する
    On Error GoTo onErr '読み込みエラー時
    i = 2
        Do
            DoEvents
            HallData = Split(Replace(ESP.ReadString(), vbCrLf, ""), ",")
            Cells(i, 1) = HallData(0) ' 時間(ミリ秒)
            Cells(i, 2) = HallData(1) ' センサー値
            If StopMeas = True Then
                ESP.WriteString "END"
                Exit Do
            End If
            i = i + 1
        Loop
    ESP.IO.Close
    Set ESP = Nothing
    Set RM = Nothing
    Exit Sub
    
'読み込みエラー時
onErr:
    ESP.IO.Close
    Set ESP = Nothing
    Set RM = Nothing
    MsgBox "Error"

End Sub

測定

 Excel にホールセンサーの値を取り込んで、色々試してみました。

平均化せずにデータ取得

 測定データを平均化せず(スケッチの29行目 int n = 1; )データを取り込んでみました。

 1,000 点取り込んでグラフにすると大きなノイズが乗っていました。 何点か毎に平均化したほうがよさそうです。

平均化の回数を変えてデータを取得

 平均化回数(スケッチの29行目 int n = 〇〇; ) を1 、100、1000 と変えてそれぞれ 10,000 点取得し、統計を取りました。

 1 点のデータを取得するのにそれぞれ1、100、1000 回ホールセンサーの値を取得しているので測定にかかる時間は異なります。

平均化無し100回1,000回
測定数10,00010,00010,000
平均値15.3215.0014.63
標準偏差3.551.861.46
最小値-3011.7112.16
最大値4320.8220.02
かかった時間13.86 秒63.3 秒529 秒

 それぞれの10,000 点のデータを順にプロットしたグラフです。 平均化することでデータのスパイクが無くなっています。

 平均化回数を1,000 回にすると10,000 点測定するのに約9 分間かかりました。

器差について

 手元にはESP32(ESP32-DevKitC)が4 つあります。

  平均化無し、各10,000点で、それぞれ出来るだけ同じ条件でデータを取りました。

ESP32①ESP32②ESP32③ESP32④
測定数10,00010,00010,00010,000
平均値19.4128.19-6.8417.76
標準偏差3.263.272.803.08
最小値-11-12-32-22
最大値55541868
かかった時間12.1412.3412.2512.14

 機器によって平均値がかなり変わりました。

磁石を近づけてみる

 手持ちのネオジム磁石を近づけてみました。かなり強力です。うっかり手を挟むととても痛い。

 上面からN 極を近づけると負の値、S 極を近づけると正の値に振りました。

 単位がmT だとすると100 ~150 mT ということになります。

 ネオジム磁石の間にESP32 を挟んでみました。

 磁石の間にがっちり挟まれています。

 値は-300 と +200 になりました。

 何故か負方向の値が1.5 倍に。

広告

Bluetooth でホールセンサーの値を取得する

 Bluetooth 経由でホールセンサーの値を取得する方法も記載しておきます。
 Bluetooth でデータをExcelに取り込む方法は以前の記事に書きました。

 Bluetooth 経由でもWiFi と同様にデータ取得できました。

スケッチ

 ESP32(ESP32-DevKitC) のスケッチは以下の通りにしました。

#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;

// ホールセンサーの値をBluetooth経由で送信
void sendData() {
  while (1) {
    double hallData = 0;
    // n回測定の平均を出す
    int n = 100;
    for(int i = 0; i < n; i++) { 
      hallData += hallRead();
    }
    hallData /= n;
    // プログラム開始からの時間(ミリ秒)とホールセンサーの値
    String sData = String(millis()) + " ," + String(hallData);
    SerialBT.println(sData);
    Serial.println(sData);
    if (SerialBT.available()) {
      String command = SerialBT.readStringUntil(0x0a);
      if (command == "END"){ // "END"コマンドを受信したら終了
        break;
      }
    }
  }
}

void setup()
{
    Serial.begin(115200);
    delay(10);
    // Bluetooth接続
    SerialBT.begin("ESP32test"); //Bluetooth device name
    Serial.println("The device started, now you can pair it with bluetooth!");
}

void loop(){
 if (SerialBT.available()) {
    String command = SerialBT.readStringUntil(0x0a);
    Serial.println(command);
    if(command == "MEAS"){ // "MEAS"コマンドを受信したら測定開始
      Serial.println(command);
      sendData();
    }
 }
}

VBAプログラム

 ユーザーフォーム
Private Sub CommandButton1_Click()
    StopMeas = True
    Me.Hide
End Sub
 標準モジュール
Private Declare Sub Sleep Lib "KERNEL32.dll" (ByVal dwMilliseconds As Long) '32bit版EXCEL
'Private Declare PtrSafe Sub Sleep Lib "KERNEL32.dll" (ByVal dwMilliseconds As Long) '64bit版EXCEL
Public StopMeas As Boolean

Sub GetHallDataBT()
    ' VISA COMオブジェクトを作成し接続を設定
    Dim RM As New VisaComLib.ResourceManager
    Dim ESP As New VisaComLib.FormattedIO488
    ' 変数の宣言
    Dim HallData As Variant
    Dim i As Long
    'シートをクリア
    Worksheets("Sheet1").Range(Cells(2, 1), Cells(Rows.Count, 3)).Clear
    
    '接続
    Set ESP.IO = RM.Open("ASRL5::INSTR") ' Arduinoと接続 VISAアドレス"ASRL5::INSTR"はConnection Expert で確認
    ESP.IO.Timeout = 5000

    UserForm1.Show vbModeless ' ユーザーフォームをモードレスで表示
    
    ' ESP32に"MEAS"コードを送る。
    ESP.WriteString "MEAS"
    
    ' データを取得する
    On Error GoTo onErr '読み込みエラー時
    i = 2
        Do
            DoEvents
            HallData = Split(Replace(ESP.ReadString(), vbCrLf, ""), ",")
            Cells(i, 1) = HallData(0) ' 時間(ミリ秒)
            Cells(i, 2) = HallData(1) ' センサー値
            'If StopMeas = True Then
            If i > 109 Then
                ESP.WriteString "END"
                Exit Do
            End If
            i = i + 1
        Loop
        
    Debug.Print "End"
    ESP.IO.Close
    Set ESP = Nothing
    Set RM = Nothing
    Exit Sub

'読み込みエラー時
onErr:
    ESP.IO.Close
    Set ESP = Nothing
    Set RM = Nothing
    MsgBox "Error"
End Sub