DTMF Kode :
const
int dtmfPins[4]
= {2, 3,
4, 5};
const
int stdPin = 6;
const
int relay1 = 8;
const
int relay2 = 9;
const
int buzzer = 7;
unsigned
long debounceDelay = 300;
int
lastTone = -1;
unsigned
long lastValidTime = 0;
enum
DTMFState { IDLE,
READ_1, READ_2,
READ_3 };
DTMFState dtmfState = IDLE;
int
t1 = -1, t2 = -1,
t3 = -1;
unsigned
long dtmfTimestamp = 0;
const
unsigned long
dtmfInterval = 40;
// waktu antar baca DTMF
// Status nada startup
bool
isPlayingStartup = false;
int
startupStep = 0;
unsigned
long startupStepStart =
0;
const
int startupFreqs[] = {1000,
1200, 1500};
const
unsigned long
startupDurations[] = {150,
150, 300};
const
unsigned long
startupIntervals[] = {200,
200, 400};
const
int startupStepsCount = 3;
// Struktur queue nada buzzer
#define
BUZZER_QUEUE_SIZE
5
struct
BuzzerNote {
unsigned
int freq;
unsigned
long duration;
};
BuzzerNote buzzerQueue[BUZZER_QUEUE_SIZE];
int
buzzerHead = 0;
int
buzzerTail = 0;
unsigned
long buzzerStartTime = 0;
bool
buzzerPlaying = false;
void
setup()
{
Serial.begin(9600);
for
(int
i = 0; i < 4;
i++) pinMode(dtmfPins[i],
INPUT);
pinMode(stdPin,
INPUT);
pinMode(relay1,
OUTPUT);
pinMode(relay2,
OUTPUT);
pinMode(buzzer,
OUTPUT);
digitalWrite(relay1,
HIGH);
digitalWrite(relay2,
HIGH);
playStartupTune();
}
void
loop()
{
handleBuzzer();
handleDTMF();
}
void
handleDTMF()
{
unsigned
long now = millis();
// Jangan baca DTMF saat nada
startup diputar
if
(isPlayingStartup)
return;
switch
(dtmfState)
{
case
IDLE:
if
(digitalRead(stdPin)
== HIGH) {
dtmfTimestamp = now;
dtmfState
= READ_1;
}
break;
case
READ_1:
if
(now - dtmfTimestamp >=
dtmfInterval) {
t1 = readDTMF();
dtmfTimestamp = now;
dtmfState
= READ_2;
}
break;
case
READ_2:
if
(now - dtmfTimestamp >=
dtmfInterval) {
t2 = readDTMF();
dtmfTimestamp = now;
dtmfState
= READ_3;
}
break;
case
READ_3:
if
(now - dtmfTimestamp >=
dtmfInterval) {
t3 = readDTMF();
dtmfState
= IDLE;
if
(t1 == t2 && t2 == t3
&& t1 != -1)
{
if
((t1 != lastTone)
|| (now - lastValidTime >
debounceDelay)) {
lastTone = t1;
lastValidTime = now;
handleTone(t1);
}
}
}
break;
}
}
int
readDTMF()
{
int
val = 0;
for
(int
i = 0; i < 4;
i++) {
val |= (digitalRead(dtmfPins[i])
<< i);
}
return
val;
}
void
handleTone(int
tone) {
Serial.print("DTMF
Valid: ");
Serial.println(tone);
switch
(tone)
{
case
1:
setRelay(relay1,
true);
playBuzzerNote(1000,
150);
break;
case
2:
setRelay(relay2,
true);
playBuzzerNote(1000,
150);
break;
case
3:
setRelay(relay1,
false);
playBuzzerNote(600,
300);
break;
case
4:
setRelay(relay2,
false);
playBuzzerNote(600,
300);
break;
default:
Serial.println("DTMF
tidak dikenali");
break;
}
}
void
setRelay(int
relayPin, bool
on) {
digitalWrite(relayPin,
on ? LOW : HIGH);
Serial.print("Relay
");
Serial.print(relayPin);
Serial.print(on
? " ON\n"
: " OFF\n");
}
// --- Buzzer handling ---
void
playStartupTune()
{
isPlayingStartup = true;
startupStep = 0;
startupStepStart = millis();
playBuzzerNote(startupFreqs[startupStep],
startupDurations[startupStep]);
}
void
handleBuzzer()
{
unsigned
long now = millis();
// Tangani nada startup
if
(isPlayingStartup)
{
if
(!buzzerPlaying && (now
- startupStepStart >= startupIntervals[startupStep]))
{
startupStep++;
if
(startupStep >= startupStepsCount)
{
isPlayingStartup = false;
noTone(buzzer);
return;
}
playBuzzerNote(startupFreqs[startupStep],
startupDurations[startupStep]);
startupStepStart
= now;
}
return;
// Prioritas nada startup
}
// Jika buzzer sedang main
nada, cek durasi
if
(buzzerPlaying)
{
if
(now - buzzerStartTime >= buzzerQueue[buzzerHead].duration)
{
noTone(buzzer);
buzzerPlaying = false;
buzzerHead = (buzzerHead
+ 1) %
BUZZER_QUEUE_SIZE;
}
else {
return;
// masih main nada
}
}
// Jika tidak main nada, cek
antrian nada berikutnya
if
(buzzerHead != buzzerTail)
{
BuzzerNote note = buzzerQueue[buzzerHead];
tone(buzzer,
note.freq);
buzzerPlaying = true;
buzzerStartTime = now;
}
}
void
playBuzzerNote(unsigned
int freq,
unsigned long
dur) {
int
nextTail = (buzzerTail + 1)
% BUZZER_QUEUE_SIZE;
if
(nextTail == buzzerHead)
{
// Queue penuh, nada
baru diabaikan supaya tidak nge-block
Serial.println("Buzzer
queue penuh, nada diabaikan");
return;
}
buzzerQueue[buzzerTail].freq
= freq;
buzzerQueue[buzzerTail].duration
= dur;
buzzerTail = nextTail;
}