本記事はArduino Advent Calendar 2020の12月24日分です。
はじめまして! 記事をご覧くださりありがとうございます。
半分NEETのようなフリーランスエンジニアのたつのぶと申します。
今回は、ESP32で奏でる「ぼっちクリスマス」に響くシングルなベル🎄と題して
MQTT(IoT向け軽量メッセージプロトコル)などを使って、ESP32に接続された圧電ブザーを外部ネットワークからボタン一つで鳴らしてみた記事です。ぜひ最後まで読んでくださると幸いです!!
#できたもの
⇒チープな圧電ブザーを使ったので、音が悪いかも...???
#準備するもの - レンタルサーバー - PC: WindowsPC - ESP32-DevKitC - 圧電ブザー - ブレッドボードMQTT(IoT向け軽量メッセージプロトコル)と圧電ブザー制御によるジングルベルの演奏。 pic.twitter.com/vYZtoSYlrK
— 🐑たつのぶ(24)@AI/IoT/Web/App/心理学 (@ryuryudoragon_) December 13, 2020
#システム構成図
#MQTTについて
MQTTは「Message Queue Telemetry Transport」の略でIoT向けの非同期軽量メッセージプロトコルのことを指します!!
MQTTは3つの要素で構成されており、具体的には下記通りです。
①Publisher(メッセージを送信するプログラム)
②Broker(Publisherからメッセージを受け取り、Subscriberに送信する仲介役となるサーバーなど)
③Subscriber(メッセージを受信するプログラム)
※メッセージの送り先を指定し、メッセージを指定して受け取ることができる機能のことを**topic(トピック)**といいます。
※QoS(Quality of Service) とは、データを送信する確実性のことです。
下記のように3つのレベルがあり、サーバの性能に依存します。
★レベル0:最大1回届く
★レベル1:1回以上届く
★レベル2:正確に1回届く
#ブザーイベントsubscribeプログラム(ESP32側)
#include <WiFi.h>
#include "PubSubClient.h"
const char* ssid = "ssid";
const char* password = "pass";
const char* mqttServer = "xxxx.cloudmqtt.com";
const int mqttPort = 12345;
const char* mqttUser = "mqttuser";
const char* mqttPassword = "mqttpass";
WiFiClient espClient;
PubSubClient client(espClient);
const int pin = 27;
const int ch = 1;
//-----------音階定義--------------
//---------------------------------
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
//---------------------------------
//音階の指定→ melody[]
int melody[] = {
NOTE_G4, NOTE_G4 ,NOTE_E5, NOTE_D5, NOTE_C5, NOTE_G4,
NOTE_G4, NOTE_G4, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_A4,
NOTE_A4, NOTE_A4, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_A4,
NOTE_G5, NOTE_G5, NOTE_F5, NOTE_D5, NOTE_E5, NOTE_C5,
NOTE_G4, NOTE_G4, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_G4,
NOTE_G4, NOTE_G4, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_A4,
NOTE_A4, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_G5, NOTE_G5, NOTE_G5, NOTE_G5,
NOTE_A5, NOTE_G5, NOTE_F5, NOTE_D5, NOTE_C5,
NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_G5, NOTE_C5, NOTE_D5, NOTE_E5,
NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_D5, NOTE_D5, NOTE_C5, NOTE_D5, NOTE_G5,
NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_G5, NOTE_C5, NOTE_D5, NOTE_E5,
NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_G5, NOTE_G5, NOTE_F5, NOTE_D5, NOTE_C5};
//音の長さの指定→ duration[]
int duration[] = {
250,250,250,250,250,500,
250,250,250,250,250,500,
250,250,250,250,250,500,
250,250,250,250,250,1500,
250,250,250,250,250,500,
250,250,250,250,250,500,
250,250,250,250,250,250,250,250,
250,250,250,250,500,
250,250,500,250,250,500,
250,250,250,250,500,
250,250,250,250,250,250,250,250,
250,250,250,250,500,500,
250,250,500,250,250,500,
250,250,250,250,500,
250,250,250,250,250,250,250,250,
250,250,250,250,1000};
void musicFunc(int ch,int meloFreq,int meloTime){
ledcWriteTone(ch,meloFreq); //ch freq
delay(meloTime);
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
for(int i=0;i<sizeof melody / sizeof( melody[0]);i++){
musicFunc(ch, melody[i], duration[i]+30);
}
ledcSetup(ch,12000,8); //ch basefreq dutybit
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void setup() {
Serial.begin(115200);
ledcSetup(ch,12000,8); //ch basefreq dutybit
ledcAttachPin(pin,ch); //pin ch
WiFi.begin(ssid, password);
Serial.begin(115200);
ledcSetup(ch,12000,8); //ch basefreq dutybit
ledcAttachPin(pin,ch); //pin ch
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
Serial.println("connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
client.subscribe("esp/buzzer");
}
void loop() {
client.loop();
}
ブザーイベントpublishスクリプト(サーバ側)
<?php
require("./phpMQTT.php");
$username = "mqttuser";
$password = "mqttpass";
$server = "xxxxx.cloudmqtt.com"; // change if necessary
$port = 12345; // change if necessary
$client_id ='ClientID'.rand().'phpMQTT-publisher'; // make sure this is unique for connecting to sever - you could use uniqid()
$mqtt = new Bluerhinos\phpMQTT($server, $port, $client_id);
if ($mqtt->connect(true, NULL, $username, $password)) {
$mqtt->publish('esp/buzzer', 'Hello World! at ' . date('r'), 0, false);
$mqtt->close();
} else {
echo "Time out!\n";
}
?>
#ブザーを鳴らすボタンのあるフロントページ(サーバ側)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>クリスマス</title>
</head>
<body>
<p>サンタの画像をクリックするとジングルベルが流れるよ!</p>
<button type="submit" onclick="btnClick();"><img src="images/cms.png" width="150" height="150" alt="送信" /></button>
<script>
function btnClick() {
let request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
document.body.className = 'ok';
console.log(this.responseText);
} else if (this.response == null && this.status === 0) {
document.body.className = 'error offline';
console.log("The computer appears to be offline.");
} else {
document.body.className = 'error';
}
}
};
request.open("GET", "https://hogehoge.jp/buzzermqtt.php", true);
request.send(null);
alert("メリークリスマス♪♪");
}
</script>
</body>
</html>
#最後に
いかがだったでしょうか?
MQTTをまだ知らない組込み開発者の方へ
MQTTの仕組みとMQTTを使った圧電ブザー制御について、ざっくり理解できたのではないでしょうか?
これを応用して、圧電ブザーを赤外線LEDに変え、遠隔でリモコン操作をしてもいいですし、
アイデア次第でIoT開発の幅をぜひ広げてみてください。面白いですよ!
全国のおひとり様の方々へ
ESP32で奏でる「ぼっちクリスマス」に響くシングルなベル🎄ということで、
ジングルベルが鳴り響くことで、ひとりクリスマスの楽しむ幅が広がったのではないでしょうか?(白目)
ということで、今年もそれぞれの楽しいクリスマス🎅🎄をお過ごしください!!
それでは✋