水位計を自作するのは、技術的なスキルを身につけるのに非常に良いプロジェクトです。このブログでは、ESP32と超音波センサを使用して、携帯電話から水位を確認できるシステムの作り方を紹介します。製作に必要なものから、ArduinoとHTMLのプログラムの詳細まで、初心者でも理解しやすいように分かりやすく説明します。
・ESP32と超音波センサを使って水位計を作りたいが、どのように始めれば良いかわからない。
・Arduinoプログラミングの基本的な知識が不足している。
・HTMLとJavaScriptを使用して、データを視覚的に表示する方法がわからない。
・ESP32と超音波センサを使用した水位計の基本的な作り方を理解できる。
・Arduinoの基本的なプログラミングスキルを学べる。
・ブラウザでデータを視覚的に表示するためのHTMLとJavaScriptの使用方法を習得できる。
これらの内容を理解することができます。また、動画でも紹介していますので、興味がありましたらYouTubeをご覧ください。
水の高さに応じた携帯でモニタリングできる水位計を作成することができます。プログラムも全文載せております。
第1章: 必要な材料とツール
1.1 材料リスト
このプロジェクトでは、以下の材料が必要です。これらは電子部品店やオンラインで簡単に入手できます。
ESP32ボード:
Wi-Fi機能を内蔵したマイクロコントローラボード。
このプロジェクトのコアとなる部品で、センサデータの処理とWebサーバの機能を担います。
超音波センサ (HC-SR04など):
水位を測定するためのセンサ。
音波を発してその反射を受け取り、距離を計測します。
ブレッドボードとジャンパワイヤ:
ブレッドボードは、電子部品をはんだ付けせずに接続するためのツールです。
ジャンパワイヤは、ブレッドボード上で部品を接続するために使用します。
パーソナルコンピュータ:
ArduinoのコードをESP32ボードにアップロードするために使用します。
USBケーブ
ESP32ボードをコンピュータに接続し、プログラムをアップロードするために使用します。
ESP32ボード:
Wi-Fi機能を内蔵したマイクロコントローラボード。
このプロジェクトのコアとなる部品で、センサデータの処理とWebサーバの機能を担います。
超音波センサ (HC-SR04など):
水位を測定するためのセンサ。
音波を発してその反射を受け取り、距離を計測します。
ブレッドボードとジャンパワイヤ:
ブレッドボードは、電子部品をはんだ付けせずに接続するためのツールです。
ジャンパワイヤは、ブレッドボード上で部品を接続するために使用します。
パーソナルコンピュータ:
ArduinoのコードをESP32ボードにアップロードするために使用します。
USBケーブ
ESP32ボードをコンピュータに接続し、プログラムをアップロードするために使用します。
下記より購入可能です。
1.2 ツール
このプロジェクトを成功させるためには、以下のツールが必要です。
- Arduino IDE:
- 無料で提供される統合開発環境。
- ESP32にプログラムを書き込む際に使用します。
- ウェブサイトからダウンロード可能で、Windows、Mac、Linuxに対応しています。
- インターネットブラウザ:
- システムのモニタリングとデータの表示に使用します。
- 任意のモダンブラウザ(Google Chrome、Mozilla Firefox、Safariなど)が使用可能です。
第2章: Arduinoプログラム
2.1 Arduinoプログラムの概要
この章では、ESP32と超音波センサを使用して水位計を製作するためのArduinoプログラムについて詳しく説明します。プログラムはセンサからデータを取得し、WiFiを介してこれをWebサーバに送信する機能を持っています。
2.2 プログラムの全文と解説
以下に、Arduinoプログラムの全文とその各部の説明を記します。
// 必要なライブラリのインクルード
#include <WiFi.h>
#include <WebServer.h>
#include <SPIFFS.h>
// ピンの定義
#define trigPin 5 // 超音波センサのトリガーピン
#define echoPin 18 // 超音波センサのエコーピン
// WiFi接続情報
const char* ssid = "Your SSID";
const char* password = "Your Password";
// WebServerオブジェクトの初期化
WebServer server(80);
// セットアップ関数
void setup() {
Serial.begin(115200); // シリアル通信の開始
pinMode(trigPin, OUTPUT); // トリガーピンを出力として設定
pinMode(echoPin, INPUT); // エコーピンを入力として設定
// SPIFFSの初期化
if(!SPIFFS.begin(true)){
Serial.println("SPIFFSのマウントに失敗しました");
return;
}
// WiFi接続
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Webサーバーのルート設定
server.on("/", HTTP_GET, []() {
server.send(200, "text/html", SPIFFS.open("/index.html", "r").readString());
});
// '/distance'で距離を返す設定
server.on("/distance", HTTP_GET, []() {
server.send(200, "text/plain", String(measureDistance()));
});
server.begin(); // サーバーの開始
}
// メインループ
void loop() {
server.handleClient(); // クライアントのリクエストを処理
}
// 距離測定関数
float measureDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
float distance = (duration * 0.0343) / 2;
return distance;
}
コメント付きの解説
- ライブラリのインクルード:
WiFi.h
はESP32のWiFi機能を制御します。WebServer.h
はHTTPリクエストの処理に使用します。SPIFFS.h
はファイルシステム操作に必要です。
- ピンの定義:
trigPin
とechoPin
は超音波センサのトリガーピンとエコーピンに対応します。
- WiFi接続情報:
ssid
とpassword
を自分のWiFiネットワークの情報に設定します。
- セットアップ関数 (
setup
):- シリアル通信の開始、ピンのモード設定、SPIFFSの初期化、WiFi接続を行います。
- Webサーバーのルートと
/distance
パスの設定を行います。
- メインループ (
loop
):- Webサーバーがクライアントからのリクエストを待ち受け、対応します。
- 距離測定関数 (
measureDistance
):- 超音波センサを用いて距離を測定し、その値を返します。
2.3 初心者向けの解説
このプログラムは、以下のステップで動作します:
- セットアップ: ESP32の起動時に一度だけ実行される部分です。ここで、ピンの設定、WiFi接続、Webサーバーの設定が行われます。
- メインループ: ESP32が稼働している間、継続的に実行されます。ここで、Webサーバーがクライアントのリクエストに対応します。
- 関数:
measureDistance
は、センサから距離データを取得するための関数です。このデータは、Webサーバーを通じてユーザーに提供されます。
このプログラムを通じて、マイクロコントローラの基本的な操作、センサデータの取得、WiFiを介したデータの送信など、多くの重要なコンセプトを学ぶことができます。
2.4 measureDistance()
関数の詳細と原理
measureDistance()
関数は、超音波センサを用いて物体までの距離を測定する重要な部分です。この関数の動作原理とコードの解説を行います。
動作原理
超音波センサ(HC-SR04など)は、超音波のパルスを発信し、その反射波(エコー)を受信することで距離を計測します。以下が基本的なステップです:
- パルスの発信:
- センサのトリガーピンに短い高電圧パルス(一般的に10マイクロ秒)を送ると、センサは超音波のパルスを発信します。
- 反射波の受信:
- 発信された超音波が物体に当たり、反射してセンサに戻ってくるのを待ちます。この間の時間を計測します。
- 距離の計算:
- 超音波の速度(空気中で約343メートル/秒)と、超音波が戻ってくるまでの時間から距離を計算します。
コードの解説
float measureDistance() {
// 超音波パルスを初期化
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// エコー信号の持続時間を測定
long duration = pulseIn(echoPin, HIGH);
// 距離を計算(持続時間 * 音速 / 2)
float distance = (duration * 0.0343) / 2;
return distance; // 計算した距離を返す
}
digitalWrite(trigPin, HIGH)
とdigitalWrite(trigPin, LOW)
の間に挟まれたdelayMicroseconds(10)
は、超音波パルスを発信するための信号を生成します。pulseIn(echoPin, HIGH)
関数は、エコーピンがHIGH(反射波を受信)状態になるのにかかった時間(マイクロ秒)を計測します。- 距離は、
duration * 0.0343 / 2
の式で計算されます。ここで、0.0343は音速(343m/s)をマイクロ秒単位とメートル単位に変換した値です。往復の時間を計測しているため、2で割ります。
- 超音波センサの精度は、温度や湿度などの環境要因に影響されることがあります。
- 近すぎるまたは遠すぎる物体は正確に検出できないことがあります。
- 硬い平らな表面からの反射が最も検出しやすいです。
この関数を通じて、ESP32と超音波センサを用いた物体の距離測定技術の基礎を理解することができます。これは、さまざまなセンシングアプリケーションで応用可能な重要な概念です。
2.5 SPIFFSへのindex.htmlの保存方法
ESP32でのWebアプリケーション開発には、SPIFFS(Serial Peripheral Interface Flash File System)が重要な役割を果たします。これは、ESP32の内蔵フラッシュメモリをファイルシステムとして利用するためのものです。ここでは、SPIFFSを使用してindex.html
ファイルをESP32に保存する方法を説明します。
SPIFFSとは
- SPIFFSは、ESP32のフラッシュメモリ上に簡単なファイルシステムを作成します。
- HTMLファイルや画像、スクリプトなどの静的リソースを保存するのに適しています。
index.htmlをSPIFFSにアップロードする手順
- Arduino IDEの準備:
- 最新版のArduino IDEにESP32のボードマネージャをインストールしてください。
- ESP32 SPIFFSプラグインをインストールする必要があります。これは、Arduinoの公式サイトやGitHubから入手できます。下記リンクからインストールします。
- ファイルの作成:
index.html
ファイルを作成し、必要なHTMLとJavaScriptコードを記述します。
- SPIFFSへのアップロード:
- Arduino IDEでSPIFFSアップロードツールを開きます。
index.html
ファイルを含むスケッチファイルが保存されている同じディレクトリに保存します。その後、toolのESP32 Sketch Data uploadを選択。- アップロードが完了すると、
index.html
ファイルはESP32の内蔵フラッシュメモリ上に保存されます。
正しくダウンロードすると下記のようにESP32 Sketch Data uploadが表示されます。
スケッチファイルの保存されているフォルダにdataフォルダを作成し、中にindex.htmlを保存して、ESP32 Sketch Data Uploadを押すとアップロードされます。
第3章: HTMLとJavaScript
HTML/Java scriptの全文がこちらになります。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>水位計</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: Arial, sans-serif;
font-size: 20px;
}
#container {
width: 90%;
height: 50%;
}
.settings {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
}
.settings > div {
margin: 0 10px;
}
.alert {
display: none;
color: red;
text-align: center;
position: absolute;
width: 100%;
bottom: 10%;
}
#title {
display: flex;
justify-content: center;
align-items: center;
font-size: 50px;
}
</style>
</head>
<body>
<div id="title">Water Level monitoring</div>
<div class="settings">
<div>
<label for="minDistance">0% Distance (cm): </label>
<input type="number" id="minDistance" value="2">
</div>
<div>
<label for="maxDistance">100% Distance (cm): </label>
<input type="number" id="maxDistance" value="15">
</div>
</div>
<div id="container"></div>
<div id="alert" class="alert">Alert: The value is below 20%</div>
<script>
var minDistance = parseFloat(document.getElementById('minDistance').value);
var maxDistance = parseFloat(document.getElementById('maxDistance').value);
document.getElementById('minDistance').addEventListener('change', function() {
minDistance = parseFloat(this.value);
updateChart();
});
document.getElementById('maxDistance').addEventListener('change', function() {
maxDistance = parseFloat(this.value);
updateChart();
});
// Highchartsのゲージオプション設定
var gaugeOptions = {
chart: {
type: 'solidgauge',
},
title: null,
pane: {
startAngle: -120,
endAngle: 120,
background: {
backgroundColor: '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
yAxis: {
stops: [
[0.1, '#DF5353'], // 高い値で青系
[0.5, '#DDDF0D'], // 中間値で黄色
[0.9, '#55BF3B'] // 低い値で赤系
],
lineWidth: 0,
minorTickInterval: null,
tickAmount: 2,
min: 0,
max: 100,
title: null,
labels: {
y: 16
}
},
credits: {
enabled: false
},
series: [{
name: 'Distance',
data: [100], // 初期値
dataLabels: {
format: '<div style="text-align:center"><span style="font-size:30px">{y}%</span></div>'
}
}]
};
// Highchartsのゲージを作成
var chart = Highcharts.chart('container', Highcharts.merge(gaugeOptions, {
series: [{
data: [100] // シリーズにも初期値をセット
}]
}));
// ゲージの値を更新する関数
function updateGauge(value) {
// minDistanceとmaxDistanceを使用して値を計算
var newVal = ((maxDistance - value) / (maxDistance - minDistance)) * 100;
// newValが0未満の場合は0に、100を超える場合は100に制限する
newVal = Math.max(0, Math.min(newVal, 100));
newVal = Math.round(newVal); // 小数点以下を四捨五入して整数に
chart.series[0].points[0].update(newVal);
// 値が20以下の場合、アラートを表示
if (newVal <= 20) {
document.getElementById('alert').style.display = 'block';
} else {
document.getElementById('alert').style.display = 'none';
}
}
// ESP32からデータを取得してゲージを更新する
// HTML内のJavaScriptの一部
// HTML内のJavaScriptの一部
setInterval(function () {
fetch('/distance')
.then(response => response.text())
.then(distance => {
var dist = parseFloat(distance);
updateGauge(dist); // ゲージを更新する関数に距離データを渡す
})
.catch(function (error) {
console.error('Error fetching distance:', error);
});
}, 1000); // 1秒ごとに更新
</script>
</body>
</html>
3.1 HTMLの概要
この章では、ESP32と超音波センサによって測定された水位データを表示するためのHTMLとJavaScriptについて詳しく説明します。このHTMLページは、ESP32のWebサーバーから提供され、ブラウザを通してリアルタイムでデータを確認できるように設計されています。
3.2 HTMLの全文と解説
以下にHTMLコードの全文と各セクションの説明を示します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>水位計</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
<style>
/* CSSスタイル設定 */
</style>
</head>
<body>
<div id="title">Water Level Monitoring</div>
<div class="settings">
<!-- 設定コントロール -->
</div>
<div id="container"></div>
<div id="alert" class="alert">Alert: The value is below 20%</div>
<script>
// JavaScriptコード
</script>
</body>
</html>
コメント付きの解説
- ヘッド部分:
- 文書の文字コードやタイトル、ビューポートの設定が含まれています。
Highcharts
ライブラリのスクリプトがインクルードされています。これはゲージの描画に使用されます。
- ボディ部分:
- 水位のモニタリングを表示するためのタイトルとコンテナが設定されています。
- また、水位が一定値以下になった場合に表示されるアラートのための要素も含まれています。
- スタイル:
- CSSでページのスタイルを定義しています。ここではレイアウト、フォント、色などの外観を調整できます。
- JavaScript部分:
- この部分では、ESP32から距離データを取得し、ゲージを更新する機能が実装されています。
fetch
関数を使用して、定期的にESP32のWebサーバーから距離データを取得し、それに基づいてゲージを更新します。
3.3 初心者向けの解説
このHTMLページは、ESP32から提供されるデータをブラウザで視覚的に表示するために重要な役割を果たします。主なポイントは以下の通りです。
- Highchartsの利用:
- このプロジェクトでは、HighchartsというJavaScriptライブラリを使用しています。これにより、動的なゲージを簡単に実装できます。
- ゲージは、水位の変化を直感的に把握するのに役立ちます。
- データのリアルタイム更新:
- JavaScriptの
setInterval
関数を使用して、一定間隔でESP32からデータを取得します。 - 取得したデータは、ゲージの表示を更新するために使用されます。
- JavaScriptの
- ユーザーインターフェイス:
- HTMLとCSSを使用して、ユーザーがデータを見やすい形で確認できるようにデザインされています。
- アラートメッセージは、水位が特定のしきい値以下になったときに表示され、ユーザーに警告します。
3.4 JavaScriptの詳細な説明
このセクションでは、HTML内に組み込まれたJavaScriptのコードについて詳しく説明します。このJavaScriptはESP32からの距離データを取得し、それに基づいてWebページ上のゲージを更新する役割を担います。
// ゲージの設定オプションを定義する変数
var gaugeOptions = {
chart: {
type: 'solidgauge',
},
// その他のゲージ設定
};
// ゲージを作成する関数
var chart = Highcharts.chart('container', Highcharts.merge(gaugeOptions, {
series: [{
data: [100] // シリーズにも初期値をセット
}]
}));
// ゲージの値を更新する関数
function updateGauge(value) {
var newVal = ((maxDistance - value) / (maxDistance - minDistance)) * 100;
newVal = Math.max(0, Math.min(newVal, 100));
newVal = Math.round(newVal);
chart.series[0].points[0].update(newVal);
// アラートの表示判定
}
// ESP32からデータを取得しゲージを更新するための関数
setInterval(function () {
fetch('/distance')
.then(response => response.text())
.then(distance => {
var dist = parseFloat(distance);
updateGauge(dist); // ゲージを更新する関数に距離データを渡す
})
.catch(function (error) {
console.error('Error fetching distance:', error);
});
}, 1000); // 1秒ごとに更新
コードの解説
- ゲージの設定:
gaugeOptions
変数にゲージの設定を定義します。ここでは、solidgauge
タイプのチャートを使用しています。
- ゲージの作成:
Highcharts.chart
関数を用いて、設定に基づいたゲージをページに描画します。
- ゲージ更新関数 (
updateGauge
):- 測定された距離をパーセンテージ値に変換し、ゲージに反映します。
- 値が特定の範囲外(例: 0未満または100を超える)にならないように制限します。
- データ取得とゲージ更新のループ:
setInterval
関数を使用して、1秒ごとにESP32から距離データを取得します。fetch
関数で/distance
パスからデータを取得し、その結果をupdateGauge
関数に渡してゲージを更新します。
- エラー処理:
- データ取得時にエラーが発生した場合、コンソールにエラーメッセージが表示されます。
このJavaScriptコードによって、ESP32からのリアルタイムデータをWebページ上で視覚的に表示することができます。ゲージは水位の変化を分かりやすく示し、ユーザーが状況を迅速に理解できるようにします。また、1秒ごとの定期的なデータ更新により、水位の変動をリアルタイムで追跡することが可能です。
このHTMLとJavaScriptの組み合わせにより、ユーザーはブラウザを通じてESP32からのデータをリアルタイムで視覚的に確認することができます。これは、WebベースのIoTアプリケーションを作成する際の基本的な方法です。
第4章: 組み立てとテスト
4.1 組み立て手順
この章では、ESP32と超音波センサを使用した水位計の組み立てプロセスを詳細に説明します。組み立ては比較的シンプルですが、正確な手順を踏むことで問題を避けることができます。
回路は下記のように接続ください。実際にはブレッドボード使用しているため、同様に接続してください。
4.1.1 部品の準備
- ESP32ボード
- 超音波センサ (HC-SR04など)
- ブレッドボード
- ジャンパワイヤ
- 9Vバッテリ
4.1.2 接続手順
- ブレッドボードの準備: まずブレッドボードにESP32ボードを配置します。
- 超音波センサの接続:
- 超音波センサのVCCピンを9Vのバッテリと接続します。
- GNDピンをESP32のGNDに接続します。
- TrigピンをESP32の定義したトリガーピン(ここでは5番ピン)に、Echoピンをエコーピン(18番ピン)に接続します。
- ジャンパワイヤの使用: ジャンパワイヤを使って、これらの接続を確実に行います。
4.2 テストとデバッグ
組み立てが完了したら、システムのテストとデバッグを行います。これにより、正しく機能していることを確認し、問題があれば修正します。
4.2.1 プログラムのアップロード
- Arduino IDEを開きます。
- ESP32ボードをコンピュータにUSBケーブルで接続します。
- 第2章で提供されたArduinoプログラムをArduino IDEにコピーします。
- 正しいボードとポートを選択し、プログラムをアップロードします。はじめにdataフォルダに保存した、index.htmlをESP32 Sketch data upload で保存します。その後、プログラムをESP32に書き込みます。
4.2.2 機能テスト
- シリアルモニタの確認:
- Arduino IDEのシリアルモニタを開き、ESP32がWiFiに接続し、IPアドレスが表示されることを確認します。
- ブラウザからのアクセス:
- コンピュータまたはスマートフォンのブラウザからESP32のIPアドレスにアクセスします。
- 正しく水位が表示されるかを確認します。
4.2.3 デバッグ
- 問題が発生した場合:
- 接続が正しく行われているか、ジャンパワイヤがしっかりと接続されているかを確認します。
- Arduinoプログラムのコードに誤りがないか再確認します。
- シリアルモニタの出力を確認し、エラーメッセージがないかをチェックします。
今回のプログラムを実行すると、SPIFFSの便利さと、html/Java scriptを使用することで、かなり自由度の高い水位計が作成できると思います。