Last active
October 1, 2023 14:00
-
-
Save SimedruF/a7bd434bebd5ed3f6031392d47a3ff46 to your computer and use it in GitHub Desktop.
ESP32_Piezzo.ino
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Florin Simedru | |
Complete project details at https://blog.automatic-house.ro | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files. | |
The above copyright notice and this permission notice shall be included in all | |
copies or substantial portions of the Software. | |
*/ | |
/* | |
; PlatformIO Project Configuration File | |
; | |
; Build options: build flags, source filter | |
; Upload options: custom upload port, speed and extra flags | |
; Library options: dependencies, extra library storages | |
; Advanced options: extra scripting | |
; | |
; Please visit documentation for the other options and examples | |
; https://docs.platformio.org/page/projectconf.html | |
;ottowinter/ESPAsyncWebServer-esphome@^3.0.0 | |
[env:esp32doit-devkit-v1] | |
platform = espressif32 | |
board = esp32doit-devkit-v1 | |
framework = arduino | |
upload_port = COM9 | |
monitor_port = COM9 | |
monitor_speed = 115200 | |
lib_deps = | |
lbernstone/Tone32@^1.0.0 | |
*/ | |
#include <Arduino.h> | |
#include <WiFi.h> | |
#include <WifiServer.h> | |
#include <Tone32.h> | |
#include "pitches.h" | |
#define BUZZER_CHANNEL 0 | |
#define BUZZER_PIN 14 | |
#define SOUND_PWM_CHANNEL 0 | |
#define SOUND_RESOLUTION 8 // 8 bit resolution | |
#define SOUND_ON (1 << (SOUND_RESOLUTION - 1)) // 50% duty cycle | |
#define SOUND_OFF 60000 // 0% duty cycle | |
void beep(int note, int duration); | |
void firstSection(); | |
void secondSection(); | |
void starwars(); | |
void my_tone(int pin, int frequency, int duration, int channel); | |
void my_noTone(uint8_t pin, uint8_t channel); | |
void PWM_Test(); | |
void PlayJingleBells(); | |
void PlayMerryChristmas(); | |
void PlayHappyBirthday(); | |
void PlayMaryHadaLittleLamb(); | |
void PlayTwinkleTwinkleLittleStar(); | |
void PlayPoliceSiren(); | |
String SendHTML(); | |
int freq = 10000; | |
int channel = BUZZER_CHANNEL; | |
int resolution = SOUND_RESOLUTION; | |
int counter = 0; | |
const int c = 261; | |
const int d = 294; | |
const int e = 329; | |
const int f = 349; | |
const int g = 391; | |
const int gS = 415; | |
const int a = 440; | |
const int aS = 455; | |
const int b = 466; | |
const int cH = 523; | |
const int cSH = 554; | |
const int dH = 587; | |
const int dSH = 622; | |
const int eH = 659; | |
const int fH = 698; | |
const int fSH = 740; | |
const int gH = 784; | |
const int gSH = 830; | |
const int aH = 880; | |
const char *ssid = ""; // Enter SSID here | |
const char *password = ""; // Enter Password here | |
String WifiHostname = "ESP32_Buzzer_server"; | |
WiFiServer server(80); | |
WiFiClient client; | |
/* A String to capture the incoming HTTP GET Request */ | |
String request; | |
String header; | |
String outputBuzzerStateStr = ""; | |
int buzzerSong = 0; | |
void setup() | |
{ | |
Serial.begin(115200); | |
ledcSetup(channel, freq, resolution); | |
ledcAttachPin(BUZZER_PIN, channel); | |
my_noTone(BUZZER_PIN, channel); | |
// Connect to Wi-Fi network with SSID and password | |
Serial.print("Connecting to "); | |
Serial.println(ssid); | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) | |
{ | |
delay(500); | |
Serial.print("."); | |
} | |
WiFi.setHostname(WifiHostname.c_str()); | |
// Print local IP address and start web server | |
Serial.println(""); | |
Serial.println("WiFi connected."); | |
Serial.println("IP address: "); | |
Serial.println(WiFi.localIP()); | |
server.begin(); | |
Serial.println("HTTP server started"); | |
} | |
void loop() | |
{ | |
client = server.available(); // Listen for incoming clients | |
boolean currentLineIsBlank = true; | |
if (client) | |
{ // If a new client connects, | |
Serial.println("New Client."); // print a message out in the serial port | |
String currentLine = ""; // make a String to hold incoming data from the client | |
request = ""; | |
while (client.connected()) | |
{ // loop while the client's connected | |
if (client.available()) | |
{ // if there's bytes to read from the client, | |
char c = client.read(); // read a byte, then | |
Serial.write(c); // print it out the serial monitor | |
request += c; | |
if (c == '\n' && currentLineIsBlank) | |
{ // if the byte is a newline character | |
// if the current line is blank, you got two newline characters in a row. | |
// that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) | |
if (request.indexOf("/26/on") != -1) | |
{ | |
Serial.println("StarWars theme is ON"); | |
outputBuzzerStateStr = "StarWars theme is ON"; | |
buzzerSong = 26; | |
} | |
if (request.indexOf("/26/off") != -1) | |
{ | |
Serial.println("StarWars theme is OFF"); | |
outputBuzzerStateStr = "StarWars theme is OFF"; | |
buzzerSong = 0; | |
} | |
if (request.indexOf("/1/on") != -1) | |
{ | |
Serial.println("PWM test is ON"); | |
outputBuzzerStateStr = "PWM test is ON"; | |
buzzerSong = 1; | |
} | |
if (request.indexOf("/2/on") != -1) | |
{ | |
Serial.println("Melody"); | |
outputBuzzerStateStr = "Melody"; | |
buzzerSong = 2; | |
} | |
if (request.indexOf("/3/on") != -1) | |
{ | |
Serial.println("Merry Christmas"); | |
outputBuzzerStateStr = "Merry Christmas"; | |
buzzerSong = 3; | |
} | |
if (request.indexOf("/4/on") != -1) | |
{ | |
Serial.println("Happy Birthday!"); | |
outputBuzzerStateStr = "Happy Birthday!"; | |
buzzerSong = 4; | |
} | |
if (request.indexOf("/5/on") != -1) | |
{ | |
Serial.println("Mary Had a Little Lamb!"); | |
outputBuzzerStateStr = "Mary Had a Little Lamb!"; | |
buzzerSong = 5; | |
} | |
if (request.indexOf("/6/on") != -1) | |
{ | |
Serial.println("Twinkle Twinkle Little Star!"); | |
outputBuzzerStateStr = "Twinkle Twinkle Little Star!"; | |
buzzerSong = 6; | |
} | |
if (request.indexOf("/7/on") != -1) | |
{ | |
Serial.println("Police siren"); | |
outputBuzzerStateStr = "Police siren"; | |
buzzerSong = 7; | |
} | |
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) | |
// and a content-type so the client knows what's coming, then a blank line: | |
client.println("HTTP/1.1 200 OK"); | |
client.println("Content-type:text/html"); | |
client.println("Connection: close"); | |
client.println(); // IMPORTANT | |
client.println(SendHTML()); | |
break; | |
} | |
if (c == '\n') | |
{ | |
currentLineIsBlank = true; | |
} | |
else if (c != '\r') | |
{ | |
currentLineIsBlank = false; | |
} | |
} | |
} | |
} | |
delay(1); | |
request = ""; | |
client.stop(); | |
switch (buzzerSong) | |
{ | |
case 0: | |
// Stop tone on buzzerPin | |
buzzerSong = 0; | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 1: | |
// PWM test | |
PWM_Test(); | |
buzzerSong = 0; | |
// Stop tone on buzzerPin | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 2: | |
// PlayJingleBells | |
PlayJingleBells(); | |
buzzerSong = 0; | |
// Stop tone on buzzerPin | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 3: | |
// Play Merry Christmas | |
PlayMerryChristmas(); | |
buzzerSong = 0; | |
// Stop tone on buzzerPin | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 4: | |
// Play Happy Birthday | |
PlayHappyBirthday(); | |
buzzerSong = 0; | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 5: | |
// Play Mary Had a Little Lamb | |
PlayMaryHadaLittleLamb(); | |
buzzerSong = 0; | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 6: | |
// Twinkle Twinkle Little Star | |
PlayTwinkleTwinkleLittleStar(); | |
buzzerSong = 0; | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 7: | |
// Police Siren | |
PlayPoliceSiren(); | |
buzzerSong = 0; | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
case 26: | |
// play starwars theme song | |
starwars(); | |
buzzerSong = 0; | |
// Stop tone on buzzerPin | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
default: | |
// Stop tone on buzzerPin | |
my_noTone(BUZZER_PIN, channel); | |
break; | |
} | |
// Stop tone on buzzerPin | |
my_noTone(BUZZER_PIN, channel); | |
} | |
String SendHTML() | |
{ | |
String ptr = "<!DOCTYPE html> <html>\n"; | |
ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; | |
ptr += "<title>ESP32 buzzer controller</title>\n"; | |
ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; | |
ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; | |
ptr += ".button {display: block;width: 180px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 15px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"; | |
ptr += ".button-on {background-color: #3498db;}\n"; | |
ptr += ".button-on:active {background-color: #2980b9;}\n"; | |
ptr += ".button-off {background-color: #34495e;}\n"; | |
ptr += ".button-off:active {background-color: #2c3e50;}\n"; | |
ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n"; | |
ptr += "text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}"; | |
ptr += "</style>\n"; | |
ptr += "</head>\n"; | |
ptr += "<body>\n"; | |
ptr += "<h1>ESP32 buzzer controller</h1>\n"; | |
ptr += " <p> Buzzer State " + outputBuzzerStateStr + " </p> \n"; | |
ptr += "<p><a href ='/26/on'><button class='button'>Play star wars theme </button></a></p>"; | |
ptr += "<p><a href ='/4/on'><button class='button'>Play Happy Birthday </button></a></p>"; | |
ptr += "<p><a href ='/1/on'><button class='button'>PWM test </button></a></p>"; | |
ptr += "<p><a href ='/2/on'><button class='button'>Jingle Bells </button></a></p>"; | |
ptr += "<p><a href ='/3/on'><button class='button'>Merry Christmas </button></a></p>"; | |
ptr += "<p><a href ='/5/on'><button class='button'>Play Mary Had a Little Lamb</button></a></p>"; | |
ptr += "<p><a href ='/6/on'><button class='button'>Twinkle Twinkle Little Star</button></a></p>"; | |
ptr += "<p><a href ='/7/on'><button class='button'>Police siren</button></a></p>"; | |
ptr += "</body>\n"; | |
ptr += "</html>\n"; | |
return ptr; | |
} | |
void starwars() | |
{ | |
// Play first section | |
firstSection(); | |
// Play second section | |
secondSection(); | |
// Variant 1 | |
beep(f, 250); | |
beep(gS, 500); | |
beep(f, 350); | |
beep(a, 125); | |
beep(cH, 500); | |
beep(a, 375); | |
beep(cH, 125); | |
beep(eH, 650); | |
delay(500); | |
// Repeat second section | |
secondSection(); | |
// Variant 2 | |
beep(f, 250); | |
beep(gS, 500); | |
beep(f, 375); | |
beep(cH, 125); | |
beep(a, 500); | |
beep(f, 375); | |
beep(cH, 125); | |
beep(a, 650); | |
delay(650); | |
my_noTone(BUZZER_PIN, BUZZER_CHANNEL); | |
} | |
void beep(int note, int duration) | |
{ | |
// Play tone on buzzerPin | |
my_tone(BUZZER_PIN, note, duration, channel); | |
// Stop tone on buzzerPin | |
my_noTone(BUZZER_PIN, channel); | |
delay(50); | |
} | |
void firstSection() | |
{ | |
beep(a, 500); | |
beep(a, 500); | |
beep(a, 500); | |
beep(f, 350); | |
beep(cH, 150); | |
beep(a, 500); | |
beep(f, 350); | |
beep(cH, 150); | |
beep(a, 650); | |
delay(500); | |
beep(eH, 500); | |
beep(eH, 500); | |
beep(eH, 500); | |
beep(fH, 350); | |
beep(cH, 150); | |
beep(gS, 500); | |
beep(f, 350); | |
beep(cH, 150); | |
beep(a, 650); | |
delay(500); | |
} | |
void secondSection() | |
{ | |
beep(aH, 500); | |
beep(a, 300); | |
beep(a, 150); | |
beep(aH, 500); | |
beep(gSH, 325); | |
beep(gH, 175); | |
beep(fSH, 125); | |
beep(fH, 125); | |
beep(fSH, 250); | |
delay(325); | |
beep(aS, 250); | |
beep(dSH, 500); | |
beep(dH, 325); | |
beep(cSH, 175); | |
beep(cH, 125); | |
beep(b, 125); | |
beep(cH, 250); | |
delay(350); | |
} | |
void my_tone(int pin, int frequency, int duration, int channel) | |
{ | |
ledcSetup(channel, frequency, SOUND_RESOLUTION); // Set up PWM channel | |
ledcAttachPin(pin, channel); // Attach channel to pin | |
ledcWriteTone(channel, frequency); | |
ledcWrite(channel, SOUND_ON); | |
delay(duration); | |
ledcWrite(channel, SOUND_OFF); | |
} | |
void my_noTone(uint8_t pin, uint8_t channel) | |
{ | |
ledcWrite(channel, SOUND_OFF); | |
ledcWriteTone(channel, 60000); | |
} | |
void PWM_Test() | |
{ | |
ledcWriteTone(channel, 1000); | |
for (int dutyCycle = 0; dutyCycle <= 255; dutyCycle = dutyCycle + 10) | |
{ | |
Serial.println(dutyCycle); | |
ledcWrite(channel, dutyCycle); | |
delay(1000); | |
} | |
ledcWrite(channel, 125); | |
for (int freq = 255; freq < 10000; freq = freq + 250) | |
{ | |
Serial.println(freq); | |
ledcWriteTone(channel, freq); | |
delay(1000); | |
} | |
ledcWrite(channel, 0); | |
} | |
void PlayJingleBells() | |
{ | |
// Jingle Bells melody | |
// Notes in the melody: E4, E4, E4, C4, E4, G4, C4, G4 | |
//int melody[] = {659, 659, 659, 523, 659, 784, 523, 784}; | |
// Note durations: 4 = quarter note, 8 = eighth note, etc. | |
//int noteDurations[] = {4, 8, 8, 4, 4, 4, 4, 4}; | |
// Notes in the melody: | |
int melody[] = {NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4}; | |
// Note durations: 4 = quarter note, 8 = eighth note, etc.: | |
int noteDurations[] = {4, 8, 8, 4, 4, 4, 4, 4}; | |
for (int i = 0; i < 8; i++) | |
{ | |
int note = melody[i]; | |
int duration = 1000 / noteDurations[i]; | |
my_tone(BUZZER_PIN, note, duration,channel); | |
delay(duration * 1.30); | |
my_noTone(BUZZER_PIN, channel); | |
} | |
} | |
void PlayMerryChristmas() | |
{ | |
// notes in the melody: | |
int melody[] = { | |
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_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, | |
NOTE_E5, NOTE_D5, NOTE_D5, NOTE_E5, | |
NOTE_D5, NOTE_G5}; | |
// note durations: 4 = quarter note, 8 = eighth note, etc, also called tempo: | |
int noteDurations[] = { | |
8, 8, 4, | |
8, 8, 4, | |
8, 8, 8, 8, | |
2, | |
8, 8, 8, 8, | |
8, 8, 8, 16, 16, | |
8, 8, 8, 8, | |
4, 4}; | |
for (int i = 0; i < 26; i++) | |
{ | |
int note = melody[i]; | |
int duration = 1000 / noteDurations[i]; | |
my_tone(BUZZER_PIN, note, duration, channel); | |
delay(duration * 1.30); | |
my_noTone(BUZZER_PIN, channel); | |
} | |
} | |
void PlayHappyBirthday() | |
{ | |
// Notes in the melody: | |
int melody[] = {NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4, NOTE_F4, NOTE_E4, NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4, NOTE_G4, NOTE_F4, | |
NOTE_C4, NOTE_C4, NOTE_C5, NOTE_A4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_AS4, NOTE_A4, | |
NOTE_G4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_C4, | |
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4, NOTE_F4, NOTE_E4, NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4, NOTE_G4, NOTE_F4}; | |
// Note durations: 4 = quarter note, 8 = eighth note, etc.: | |
int noteDurations[] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; | |
// Set the tempo | |
int tempo = 120; | |
// Iterate over the notes of the melody: | |
for (int i = 0; i < 38; i++) | |
{ | |
// To calculate the note duration, take one second | |
// divided by the note type. | |
// e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. | |
// to distinguish the notes, set a minimum time between them. | |
// the note's duration + 30% seems to work well for delay | |
int note = melody[i]; | |
int duration = 1000 / noteDurations[i]; | |
my_tone(BUZZER_PIN, note, duration, channel); | |
delay(duration * 1.20); | |
my_noTone(BUZZER_PIN, channel); | |
} | |
} | |
void PlayMaryHadaLittleLamb() | |
{ | |
// Notes in the melody: | |
int melody[] = {NOTE_E4, NOTE_D4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_G4, NOTE_G4, | |
NOTE_E4, NOTE_D4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_D4, NOTE_C4}; | |
// Note durations: 4 = quarter note, 8 = eighth note, etc.: | |
int noteDurations[] = {4, 4, 4, 4, 4, 4, 2, 4, 4, 2, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; | |
// Set the tempo | |
int tempo = 120; | |
// Iterate over the notes of the melody: | |
for (int i = 0; i < 26; i++) | |
{ | |
// To calculate the note duration, take one second | |
// divided by the note type. | |
// e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. | |
// to distinguish the notes, set a minimum time between them. | |
// the note's duration + 30% seems to work well for delay | |
int note = melody[i]; | |
int duration = 1000 / noteDurations[i]; | |
my_tone(BUZZER_PIN, note, duration, channel); | |
delay(duration * 1.20); | |
my_noTone(BUZZER_PIN, channel); | |
} | |
} | |
void PlayTwinkleTwinkleLittleStar() | |
{ | |
// Notes in the melody: | |
int melody[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4, NOTE_G4, | |
NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_C4, | |
NOTE_G4, NOTE_G4, NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4, | |
NOTE_G4, NOTE_G4, NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4}; | |
// Note durations: 4 = quarter note, 8 = eighth note, etc.: | |
int noteDurations[] = {4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 2}; | |
// Set the tempo | |
int tempo = 120; | |
// Iterate over the notes of the melody: | |
for (int i = 0; i < 28; i++) | |
{ | |
// To calculate the note duration, take one second | |
// divided by the note type. | |
// e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. | |
// to distinguish the notes, set a minimum time between them. | |
// the note's duration + 30% seems to work well for delay | |
int note = melody[i]; | |
int duration = 1000 / noteDurations[i]; | |
my_tone(BUZZER_PIN, note, duration, channel); | |
delay(duration * 1.20); | |
my_noTone(BUZZER_PIN, channel); | |
} | |
} | |
void PlayPoliceSiren() | |
{ | |
int frequency = 2000; // Starting frequency of the siren | |
int change = 200; // How much the frequency changes each time | |
int pause = 30; // The duration of the pause between frequency changes | |
int play = 0; | |
// Loop to play the siren | |
while (play<40) | |
{ | |
// Make a sound | |
my_tone(BUZZER_PIN, frequency,500, channel); | |
delay(pause); | |
// Stop the sound | |
my_noTone(BUZZER_PIN,channel); | |
delay(pause); | |
// Change the frequency for the next sound | |
frequency += change; | |
// Reverse the direction of the frequency change | |
change = -change; | |
play++; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment