TVZ2022 / Mbed OS Pavetic_BozicnePjesme

Dependencies:   Pavetic_BuzzerLib Pavetic_MusicLib

Files at this revision

API Documentation at this revision

Comitter:
dpavetic
Date:
Sun Nov 27 13:01:54 2022 +0000
Commit message:
Program koji simulira bozicni ugodaj reprodukcijom zvucnih signala na temelju odabira putem tipkala.

Changed in this revision

.gitignore Show annotated file Show diff for this revision Revisions of this file
CONTRIBUTING.md Show annotated file Show diff for this revision Revisions of this file
Pavetic_BuzzerLib.lib Show annotated file Show diff for this revision Revisions of this file
Pavetic_MusicLib.lib Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
resources/official_armmbed_example_badge.png Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Sun Nov 27 13:01:54 2022 +0000
@@ -0,0 +1,4 @@
+.build
+.mbed
+projectfiles
+*.py*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CONTRIBUTING.md	Sun Nov 27 13:01:54 2022 +0000
@@ -0,0 +1,5 @@
+# Contributing to Mbed OS
+
+Mbed OS is an open-source, device software platform for the Internet of Things. Contributions are an important part of the platform, and our goal is to make it as simple as possible to become a contributor.
+
+To encourage productive collaboration, as well as robust, consistent and maintainable code, we have a set of guidelines for [contributing to Mbed OS](https://os.mbed.com/docs/mbed-os/latest/contributing/index.html).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pavetic_BuzzerLib.lib	Sun Nov 27 13:01:54 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/TVZ2022/code/Pavetic_BuzzerLib/#f867aece57de
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pavetic_MusicLib.lib	Sun Nov 27 13:01:54 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/TVZ2022/code/Pavetic_MusicLib/#430445550a2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Sun Nov 27 13:01:54 2022 +0000
@@ -0,0 +1,66 @@
+Program koji simulira božični ugođaj reprodukcijom
+zvučnih signala na temelju odabira putem tipkala.
+
+# Komponente
+## Hardware na proto board-u
+- Gumb - Mijenja melodiju na klik (1...n) - Hardware interrupt
+- Potenciometar - Mjerenje vrijednosti na ulazu (0.0-1.0) - Potrebno za mjerenje vremena promjene pjesme
+- Zvučnik - Reprodukcija melodije
+- Zuta LED - Signalizacija da traje melodija jingle bells
+- Crvena LED - Signalizacija da traje melodija We wish you a merry christmas
+- Zelena LED - Signalizacija da traje melodija Silent night
+
+## Interni hardware
+- Ticker - Automatsko mijenjanje melodije u vremenu ovisnom o potenciometru (samo u modu `MODE_AUTO`)
+    - *0V = 5s*
+    - *1V = 25s*
+    - *`f(x) = 5 + 20*x [s]`* - Skaliranje funkcije pomaknute za 5s (min = 5s, max = 25s)
+- Timer #1 - Mjerenje vremena trajanja melodije
+- Timer #2 - Debounce efekt za gumb
+
+## Software
+### Melodije
+
+Postoje 3 melodije: 
+- Jingle bells
+- We wish you
+- Silent night. 
+Ovisno o trenutnoj melodiji, svijetli pripadajuca LEDica.
+
+### Modovi rada
+Postoje 3 moda rada:
+- `MODE_OFF` - Sustav je ugašen - Buzzer ugašen kao i sve LEDice
+- `MODE_SONG` - Repetetivno ponavljanje odabrane melodije - Buzzer svira, te svijetli jedna od pripadajucih LEDica za trenutnu melodiju
+- `MODE_AUTO` - Automatsko mijenjanje melodije u vremenskom razmaku odabranom putem potenciometra - Buzzer svira, te svijetli jedna od pripadajucih LEDica za trenutnu melodiju
+
+### Buzzer i reprodukcija
+Reprodukcija zvukova izvedena je kroz [Buzzer library](https://os.mbed.com/teams/TVZ2022/code/Pavetic_BuzzerLib/) koji sadrži programski kod potreban za inicijalizaciju PWM izlaza za buzzer i slanje pripadajucih signala na navedeni izlaz.
+
+### Pjesme
+Inicijalizacija zvukova i sama struktura nota (pwm period + delay) napravljena je kroz [Music library](https://os.mbed.com/teams/TVZ2022/code/Pavetic_MusicLib/).
+
+# Opis rada programa:
+Na početku programa postavljen je mod `MODE_OFF` te je sustav ugašen.
+Pritiskom na gumb u modu `MODE_OFF` (prvi pritisak gumba), mijenja se mod u
+`MODE_SONG` te počinje svirati prva od ponudenih melodija. Nakon sto melodija
+zavrsi, ukoliko nije došlo do promjene melodije ili prekida, ponovno se
+započinje sa reprodukcijom iste melodije. Ukoliko tijekom reprodukcije dođe
+do promjene moda ili melodije, trenutna melodija prekida sa reprodukcijom te
+počinje reprodukcija sljedeće melodije, ili se sustav gasi ukoliko je došlo
+do promjene moda u `MODE_OFF`.
+
+Program je u modu `MODE_SONG` te svira prva pjesma i upaljena je zuta LEDica.
+Drugim pritiskom gumba, mode ostaje isti, no mijenja se melodija te svira
+druga melodija i svijetli crvena LEDica. Trećim pritiskom gumba, mod i dalje
+ostaje isti i svira treca melodija uz upaljenu zelenu LEDicu.
+
+Cetvrtim pritiskom gumba mijenja se mod u `MODE_OFF` te se resetira ciklus
+melodija i započinje reprodukcija prve melodije. Melodija se reproducira
+ovisno o vremenu izračunatom iz vrijednosti na potenciometru prema određenoj
+formuli koja je navedena na vrhu. Nakon isteka vremena, mijenja se melodija i
+započinje reprodukcija sljedeće melodije, te tako u krug sa svim melodijama.
+ - Vrijednost potenciometra očitava se cijelo vrijeme na zasebnom Threadu.
+ - Vrijeme reprodukcije melodije u modu `MODE_OFF` izračunava se kod dolaska u taj mode.
+
+Petim pritiskom gumba, prekida se reprodukcija melodije te se mod mijenja u
+`MODE_OFF` i program nastavlja ispočetka.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Nov 27 13:01:54 2022 +0000
@@ -0,0 +1,282 @@
+// Program koji simulira božične lampice //
+
+// Gumb - Mijenja melodiju na klik (1...n) - Hardverski interrupt
+// Potenciometar - Mjerenje vrijednosti na ulazu (0.0-1.0) - Potrebno za
+// mjerenje vremena promjene pjesme Zvučnik - Reprodukcija melodije Zuta LED -
+// Signalizacija da traje melodija jingle bells Crvena LED - Signalizacija da
+// traje melodija We wish you a merry christmas Zelena LED - Signalizacija da
+// traje melodija Silent night
+
+// Ticker - Automatsko mijenjanje melodije u vremenu ovisnom o potenciometru
+// (samo u modu MODE_AUTO)
+//  --> 0V = 5s
+//  --> 1V = 25s
+//  --> f(x) = 5 + 20*x [s] - Skaliranje funkcije pomaknute za 5s (min =
+// 5s, max = 25s)
+// Timer #1 - Mjerenje vremena trajanja melodije
+// Timer #2 - Debounce efekt za gumb
+
+// Opis rada programa:
+// Postoje 3 moda rada:
+//      --> MODE_OFF - Sustav je ugašen - Buzzer ugašen kao i sve LEDice
+//      --> MODE_SONG - Repetetivno ponavljanje odabrane melodije - Buzzer
+// svira, te svijetli jedna od pripadajucih LEDica za trenutnu melodiju
+//      --> MODE_AUTO - Automatsko mijenjanje melodije u vremenskom
+//razmaku odabranom putem potenciometra - Buzzer svira, te svijetli jedna od
+//pripadajucih LEDica za trenutnu melodiju
+//
+// Postoje 3 melodije: Jingle bells, We wish you, Silent night. Ovisno o
+// trenutnoj melodiji, svijetli pripadajuca LEDica.
+//
+// Na početku programa postavljen je mod MODE_OFF te je sustav ugašen.
+// Pritiskom na gumb u modu MODE_OFF (prvi pritisak gumba), mijenja se mod u
+// MODE_SONG te počinje svirati prva od ponudenih melodija. Nakon sto melodija
+// zavrsi, ukoliko nije došlo do promjene melodije ili prekida, ponovno se
+// započinje sa reprodukcijom iste melodije. Ukoliko tijekom reprodukcije dođe
+// do promjene moda ili melodije, trenutna melodija prekida sa reprodukcijom te
+// počinje reprodukcija sljedeće melodije, ili se sustav gasi ukoliko je došlo
+// do promjene moda u MODE_OFF.
+//
+// Program je u modu MODE_SONG te svira prva pjesma i upaljena je zuta LEDica.
+// Drugim pritiskom gumba, mode ostaje isti, no mijenja se melodija te svira
+// druga melodija i svijetli crvena LEDica. Trećim pritiskom gumba, mod i dalje
+// ostaje isti i svira treca melodija uz upaljenu zelenu LEDicu.
+//
+// Cetvrtim pritiskom gumba mijenja se mod u MODE_OFF te se resetira ciklus
+// melodija i započinje reprodukcija prve melodije. Melodija se reproducira
+// ovisno o vremenu izračunatom iz vrijednosti na potenciometru prema određenoj
+// formuli koja je navedena na vrhu. Nakon isteka vremena, mijenja se melodija i
+// započinje reprodukcija sljedeće melodije, te tako u krug sa svim melodijama.
+//  - Vrijednost potenciometra očitava se cijelo vrijeme na zasebnom
+// Threadu.
+//  - Vrijeme reprodukcije melodije u modu MODE_OFF izračunava se kod
+// dolaska u taj mode.
+//
+// Petim pritiskom gumba, prekida se reprodukcija melodije te se mod mijenja u
+// MODE_OFF i program nastavlja ispočetka.
+
+#include "DigitalOut.h"
+#include "Music.h"
+#include "PinNameAliases.h"
+#include "PinNames.h"
+#include "ThisThread.h"
+#include "Thread.h"
+#include "Buzzer.h"
+#include "mbed.h"
+#include "mbed_rtc_time.h"
+#include "mbed_thread.h"
+#include "rtos.h"
+#include <chrono>
+#include <cmath>
+#include <cstdio>
+#include <cstring>
+
+#define SONG_COUNT 3
+
+#define MODE_OFF 0
+#define MODE_SONG 1
+#define MODE_AUTO 2
+
+#define JINGLE_BELLS 1
+#define WISH 2
+#define SILENT_NIGHT 3
+
+DigitalOut jingleBellsLed(PA_10); // Yellow
+DigitalOut wishLed(PB_5);         // Red
+DigitalOut silentNightLed(PA_9);  // Green
+
+// -- START Sounds and music -- //
+Timer songMeasure; // Measuring how long did song play
+// PwmOut buzzer(D5);
+Buzzer buzzer(D5);
+
+void playMusic(int array[], float rithm[], int size);
+// -- END Sounds and music -- //
+
+// -- START Mode changing -- //
+InterruptIn button(D7); // Button for changing melodies
+Timer debounce;         // Debounce timer for the button
+void onButtonPress();
+// -- END Mode changing -- //
+
+// -- START Main variables -- //
+int currentMode = MODE_OFF;       // Mode that is currently selected
+int currentMelody = JINGLE_BELLS; // Melody that is currently being played
+int songStartedOnMode = -1;       // Variable ensuring mode change is detected
+int songStartedOnMelody = -1;     // Vriable ensuring melody change is detected
+// -- END Main variables -- //
+
+// -- START Auto changing transitions -- //
+AnalogIn potenciometer(
+    A0); // Analog input for potenciometer - detecting song change speed
+
+Ticker changeSongTicker; // Ticker for changing song every x time - depends on
+                         // measuredVoltage
+Thread analogMeasureThread(osPriorityNormal, 300, nullptr, nullptr);
+float measuredVoltage = 0; // Currently measured voltage on potenciometer - For
+                           // determining time between transitions
+void readValue();
+// -- END Auto changing transitions -- //
+
+// -- START Common functions -- //
+void changeMode();
+void changeSong();
+void toggleLeds(int song);
+// -- END Common functions -- //
+
+int main() {
+  debounce.start();
+  button.mode(PullUp); // Required - otherwise button does not work properly
+  button.rise(&onButtonPress);
+
+  analogMeasureThread.start(readValue);
+
+  while (true) {
+    toggleLeds(currentMelody);
+
+    // If MODE_OFF, turn off buzzer and skip the code
+    if (currentMode == MODE_OFF) {
+      buzzer.silence();
+      continue;
+    }
+
+    songStartedOnMode = currentMode;
+    songStartedOnMelody = currentMelody;
+
+    switch (currentMelody) {
+    case JINGLE_BELLS: {
+      int size = (unsigned int)sizeof jingle_bells_melody /
+                 sizeof jingle_bells_melody[0];
+      playMusic(jingle_bells_melody, jingle_bells_note_durations, size);
+      break;
+    }
+
+    case WISH: {
+      int size = (unsigned int)sizeof wish_melody / sizeof wish_melody[0];
+      playMusic(wish_melody, wish_note_durations, size);
+      break;
+    }
+
+    case SILENT_NIGHT: {
+      int size = (unsigned int)sizeof silent_night_melody /
+                 sizeof silent_night_melody[0];
+      playMusic(silent_night_melody, silent_night_note_durations, size);
+      break;
+    }
+    }
+  }
+}
+
+void playMusic(int array[], float rithm[], int size) {
+  songMeasure.start();
+
+  int i = 0;
+  for (i = 0; i < size; i++) {
+    // Stop executing if mode or song change in the meantime
+    // Otherwise song would remain playing after mode or song is changed
+    if (currentMode != songStartedOnMode ||
+        currentMelody != songStartedOnMelody)
+      break;
+    printf("Entering iteration %d for song %d. Measured voltage: %f\n", i,
+           currentMelody, measuredVoltage);
+    buzzer.buzz(array[i], rithm[i]);
+  }
+
+  // Printing how long did song played in seconds
+  int elapsedTime_sec =
+      duration_cast<std::chrono::seconds>(songMeasure.elapsed_time()).count();
+  printf("Song played for %d seconds\n", elapsedTime_sec);
+  songMeasure.stop();
+  songMeasure.reset();
+
+  // Pause for 1 second after song has finished WITHOUT interruption - Silent
+  // transition Otherwise, move straight to the next song
+  buzzer.silence();
+  if (i == size)
+    ThisThread::sleep_for(1s);
+}
+
+// Callback executed when button is pressed - initiated by the Interrupt.
+// Uses debounce effect of 200ms and if button really pressed following code is
+// executed.
+// 1. If any song is currently playing in MODE_SONG AND it is not last song,
+// change song.
+// 2. Otherwise, if any other mode, or it is last song - Change mode.
+void onButtonPress() {
+  if (debounce.elapsed_time() > 200ms) {
+    if (currentMode == MODE_SONG && currentMelody < SONG_COUNT)
+      changeSong();
+    else
+      changeMode();
+    debounce.reset();
+  }
+}
+
+void changeMode() {
+  // Reset melody because mode has changed - Initial melody should be played
+  // (Melody cycle reset)
+  currentMelody = JINGLE_BELLS;
+
+  // Temp var used to prevent multiple mode changes at once because new mode
+  // could be unknown.
+  int newMode = currentMode + 1; // Increase temp mode variable
+  switch (newMode) {
+  case MODE_AUTO: {
+    // Calculate time base on potenciometer reading and attach Ticker
+    // 0V = 5s
+    // 1V = 25s
+    // f(x) = 5 + 20*x [s] - Skaliranje funkcije pomaknute za 5s (min = 5s,
+    // max = 25s)
+    int changeTime_sec = 5 + (20 * measuredVoltage);
+    changeSongTicker.attach_us(&changeSong, changeTime_sec * 1000000);
+    break;
+  }
+
+  case MODE_SONG:
+  case MODE_OFF:
+    // Detach timer to prevent song change after time expires
+    changeSongTicker.detach();
+    break;
+
+  default:
+    // Unrecognised mode - Turn off + detach timer to prevent song change
+    changeSongTicker.detach();
+    newMode = MODE_OFF;
+  }
+
+  // Change source of truth mode
+  currentMode = newMode;
+}
+
+// Changes current song.
+// If current melody is the last melody, reset the cyle of the songs and
+// play the first song.
+void changeSong() {
+  int newMelody = currentMelody + 1;
+  if (newMelody > SILENT_NIGHT)
+    newMelody = 1;
+  currentMelody = newMelody;
+}
+
+// Constantly reads the analog input value in separate thread.
+void readValue() {
+  while (true) {
+    measuredVoltage = potenciometer.read();
+  }
+}
+
+// Toggles LEDs based on the current song.
+// If MODE_OFF, turn off all LEDs.
+// Only 1 LED can be turned on at the same time.
+void toggleLeds(int song) {
+  if (currentMode == MODE_OFF) {
+    jingleBellsLed.write(false);
+    wishLed.write(false);
+    silentNightLed.write(false);
+    return;
+  }
+
+  jingleBellsLed.write(song == JINGLE_BELLS);
+  wishLed.write(song == WISH);
+  silentNightLed.write(song == SILENT_NIGHT);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Sun Nov 27 13:01:54 2022 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#cf4f12a123c05fcae83fc56d76442015cb8a39e9
Binary file resources/official_armmbed_example_badge.png has changed