@@ -7,17 +7,39 @@ Buzzer::Buzzer() {
77 buzzer1Pin = BUZZER_1;
88 buzzer2Pin = BUZZER_2;
99 volume = 100 ; // default max
10+ patternActive = false ;
11+ currentStep = 0 ;
12+ taskHandle = NULL ;
13+ }
14+
15+ void Buzzer::taskWorker (void * _this) {
16+ Buzzer* buzzer = (Buzzer*)_this;
17+ while (true ) {
18+ buzzer->process ();
19+ vTaskDelay (20 / portTICK_PERIOD_MS);
20+ }
1021}
1122
1223void Buzzer::begin () {
1324 pinMode (buzzer1Pin, OUTPUT);
1425 pinMode (buzzer2Pin, OUTPUT);
1526
16- patternActive = false ;
17- currentStep = 0 ;
18- nextStepTime = 0 ;
27+ activeChannels = BUZZER_CH_BOTH;
1928
2029 stop ();
30+
31+ // Create FreeRTOS task for non-blocking execution
32+ if (taskHandle == NULL ) {
33+ xTaskCreatePinnedToCore (
34+ taskWorker, // Function
35+ " BuzzerTask" , // Name
36+ 2048 , // Stack size
37+ this , // Param
38+ 1 , // Priority
39+ &taskHandle, // Handle
40+ 1 // Core (Application Core)
41+ );
42+ }
2143}
2244
2345void Buzzer::setVolume (int vol) {
@@ -26,55 +48,84 @@ void Buzzer::setVolume(int vol) {
2648
2749void Buzzer::drive (uint16_t duration_ms, uint16_t freq) {
2850 if (volume == 0 ) {
29- stop ();
51+ digitalWrite (buzzer1Pin, LOW);
52+ digitalWrite (buzzer2Pin, LOW);
3053 return ;
3154 }
3255
33- // Max loudness: Push-pull (one pin HIGH, one pin LOW)
34- digitalWrite (buzzer1Pin, HIGH);
35- digitalWrite (buzzer2Pin, LOW);
56+ if (activeChannels & BUZZER_CH_1) {
57+ digitalWrite (buzzer1Pin, HIGH);
58+ } else {
59+ digitalWrite (buzzer1Pin, LOW);
60+ }
61+
62+ if (activeChannels & BUZZER_CH_2) {
63+ digitalWrite (buzzer2Pin, HIGH);
64+ } else {
65+ digitalWrite (buzzer2Pin, LOW);
66+ }
3667}
3768
3869void Buzzer::stop () {
70+ patternActive = false ;
71+
3972 digitalWrite (buzzer1Pin, LOW);
4073 digitalWrite (buzzer2Pin, LOW);
4174}
4275
43- void Buzzer::playTone (BuzzerTone tone) {
44- patternActive = true ;
45- patternStartTime = millis ();
76+ void Buzzer::playTone (BuzzerTone tone, uint8_t channels) {
77+ // Stop previous pattern
78+ patternActive = false ;
79+ delay (5 ); // Small delay to ensuring clean state
80+
4681 currentStep = 0 ;
82+ activeChannels = channels;
4783
4884 switch (tone) {
4985 case TONE_CONFIRM: totalSteps = 1 ; break ; // 1 beep
5086 case TONE_WARNING: totalSteps = 3 ; break ; // Beep, Sil, Beep
5187 case TONE_ERROR: totalSteps = 5 ; break ; // Beep, Sil, Beep, Sil, Beep
5288 case TONE_EMERGENCY: totalSteps = 19 ; break ; // Rapid pulses
5389 }
90+
91+ patternStartTime = millis ();
5492 nextStepTime = millis ();
93+ patternActive = true ;
5594}
5695
57- void Buzzer::update () {
96+
97+ void Buzzer::process () {
5898 if (!patternActive) return ;
5999
60100 if (millis () >= nextStepTime) {
101+ // Check if we have completed all steps
102+ if (currentStep >= totalSteps) {
103+ stop ();
104+ return ;
105+ }
106+
61107 // Step logic: Even steps are ON, Odd steps are OFF
62108 if (currentStep % 2 == 0 ) {
63109 drive (0 , 0 ); // Sound ON
64- nextStepTime = millis () + 150 ; // Duration 150ms
110+ nextStepTime = millis () + 400 ; // Duration 400ms
65111 } else {
66- stop (); // Sound OFF
67- nextStepTime = millis () + 100 ; // Gap 100ms
112+ // Turn off sound but keep pattern active
113+ digitalWrite (buzzer1Pin, LOW);
114+ digitalWrite (buzzer2Pin, LOW);
115+
116+ nextStepTime = millis () + 200 ; // Gap 200ms
68117 }
69118
70119 currentStep++;
71- if (currentStep >= totalSteps) {
72- stop ();
73- patternActive = false ;
74- }
75120 }
76121}
77122
123+
124+ // Kept empty to prevent breaking existing code calls.
125+ void Buzzer::update () {
126+ // Logic moved to process() called by taskWorker
127+ }
128+
78129void Buzzer::controlFromFirebase (bool buzzer01ring, bool buzzer02ring, int buzzersound) {
79130 if (buzzersound != lastVolume) {
80131 lastVolume = buzzersound;
@@ -85,22 +136,35 @@ void Buzzer::controlFromFirebase(bool buzzer01ring, bool buzzer02ring, int buzze
85136 Serial.println (" %" );
86137 }
87138
139+ // Handle Buzzer 1 Request (Warning Tone)
88140 if (buzzer01ring) {
89141 if (!buzzer1Active) {
90142 buzzer1Active = true ;
91- playTone (TONE_CONFIRM );
143+ playTone (TONE_WARNING, BUZZER_CH_1 );
92144 }
93145 } else {
94- buzzer1Active = false ;
146+ if (buzzer1Active) {
147+ buzzer1Active = false ;
148+ // Only stop if this was the active channel
149+ if (patternActive && (activeChannels == BUZZER_CH_1)) {
150+ stop ();
151+ }
152+ }
95153 }
96154
155+ // Handle Buzzer 2 Request (Emergency Tone)
97156 if (buzzer02ring) {
98157 if (!buzzer2Active) {
99158 buzzer2Active = true ;
100- playTone (TONE_EMERGENCY);
159+ playTone (TONE_EMERGENCY, BUZZER_CH_2 );
101160 }
102161 } else {
103- buzzer2Active = false ;
162+ if (buzzer2Active) {
163+ buzzer2Active = false ;
164+ if (patternActive && (activeChannels == BUZZER_CH_2)) {
165+ stop ();
166+ }
167+ }
104168 }
105169}
106170
@@ -109,17 +173,21 @@ void Buzzer::singleBeep() {
109173}
110174
111175void Buzzer::doubleBeep () {
112- patternActive = true ;
113- patternStartTime = millis ();
176+ patternActive = false ;
114177 currentStep = 0 ;
115- totalSteps = 3 ; // On, Off, On
178+ activeChannels = BUZZER_CH_BOTH;
179+ totalSteps = 3 ;
116180 nextStepTime = millis ();
181+ patternStartTime = millis ();
182+ patternActive = true ;
117183}
118184
119185void Buzzer::tripleBeep () {
120- patternActive = true ;
121- patternStartTime = millis ();
186+ patternActive = false ;
122187 currentStep = 0 ;
123- totalSteps = 5 ; // On, Off, On, Off, On
188+ activeChannels = BUZZER_CH_BOTH;
189+ totalSteps = 5 ;
124190 nextStepTime = millis ();
191+ patternStartTime = millis ();
192+ patternActive = true ;
125193}
0 commit comments