Skip to content

Instantly share code, notes, and snippets.

@SimedruF
Last active October 1, 2023 14:00
Show Gist options
  • Save SimedruF/a7bd434bebd5ed3f6031392d47a3ff46 to your computer and use it in GitHub Desktop.
Save SimedruF/a7bd434bebd5ed3f6031392d47a3ff46 to your computer and use it in GitHub Desktop.
ESP32_Piezzo.ino
/*
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