#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 10, 2, 3, 4, 5);
const int freqPotPin = A0;
const int volPotPin = A1;
const int buzzerPin = 11;
const int nextButtonPin = 8;
const int menuButtonPin = 7;
const int saveButtonPin = 6;
const float minFreq = 87.0;
const float maxFreq = 108.0;
const int maxVolume = 255;
const int maxStations = 5;
struct Station {
float frequency;
char name[20];
const char* rdsText;
};
Station stations[maxStations] = {
{88, "Rock Lovers", "Rock Hits"},
{90, "News 24/7", "Breaking News"},
{95, "Electro Vibe", "EDM All Day"},
{100, "Golden Era", "Hits of the 70s"},
{105, "Relax FM", "Calm Music"}
};
int userStationIndex = 0;
int currentStationIndex = 0;
float selectedFrequency = 90.0;
bool inMenu = false;
bool inManualFrequencyMode = false;
enum EQSetting { NORMAL, BASS_BOOST, TREBLE_BOOST };
EQSetting currentEQ = NORMAL;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 300;
int lastButtonState = HIGH;
float lastDisplayedFrequency = -1;
int lastDisplayedVolume = -1;
void setup() {
lcd.begin(20, 4);
lcd.print("Custom Radio");
delay(1000);
lcd.clear();
pinMode(buzzerPin, OUTPUT);
pinMode(nextButtonPin, INPUT_PULLUP);
pinMode(menuButtonPin, INPUT_PULLUP);
pinMode(saveButtonPin, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("Radio ready. Use buttons to switch stations and save new ones.");
}
void loop() {
handleMenuButton();
if (inMenu) {
displayMenu();
return;
}
handleNextStationButton();
if (inManualFrequencyMode) {
selectedFrequency = getSelectedFrequency();
} else {
selectedFrequency = stations[currentStationIndex].frequency;
}
int volume = applyEQ(getVolume());
displayStationOrFrequencyInfo(selectedFrequency, volume);
if (digitalRead(saveButtonPin) == LOW && userStationIndex < maxStations && inManualFrequencyMode) {
saveUserStation(selectedFrequency);
delay(500);
}
analogWrite(buzzerPin, volume);
delay(500);
}
void handleMenuButton() {
int buttonState = digitalRead(menuButtonPin);
if (buttonState != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (buttonState == LOW) {
inMenu = !inMenu;
if (inMenu) {
lcd.clear();
delay(300);
} else {
displayStationOrFrequencyInfo(selectedFrequency, applyEQ(getVolume())); // Обновить информацию при выходе
}
}
}
lastButtonState = buttonState;
}
void handleNextStationButton() {
if (digitalRead(nextButtonPin) == LOW && !inManualFrequencyMode) {
delay(300);
currentStationIndex = (currentStationIndex + 1) % maxStations;
}
}
float getSelectedFrequency() {
int freqValue = analogRead(freqPotPin);
return map(freqValue, 0, 1023, minFreq * 10, maxFreq * 10) / 10.0;
}
int getVolume() {
int volValue = analogRead(volPotPin);
return map(volValue, 0, 1023, 0, maxVolume);
}
void displayStationOrFrequencyInfo(float frequency, int volume) {
if (lastDisplayedFrequency != frequency || lastDisplayedVolume != volume) {
lcd.clear();
bool isStationMatched = false;
for (int i = 0; i < maxStations; i++) {
if (abs(frequency - stations[i].frequency) < 0.1) {
lcd.setCursor(0, 0);
lcd.print("Station: ");
lcd.print(stations[i].name);
lcd.setCursor(0, 1);
lcd.print("RDS: ");
lcd.print(stations[i].rdsText);
lcd.setCursor(0, 2);
lcd.print("Volume: ");
lcd.print(volume * 100 / maxVolume);
isStationMatched = true;
break;
}
}
if (!isStationMatched) {
lcd.setCursor(0, 0);
lcd.print("Freq: ");
lcd.print(frequency);
lcd.print(" MHz");
lcd.setCursor(0, 1);
lcd.print("Volume: ");
lcd.print(volume * 100 / maxVolume);
}
lastDisplayedFrequency = frequency;
lastDisplayedVolume = volume;
}
}
void saveUserStation(float frequency) {
if (userStationIndex >= maxStations) {
Serial.println("Max station limit reached.");
return;
}
Serial.println("Enter name for saved station:");
while (Serial.available() == 0) {}
String stationName = Serial.readStringUntil('\n');
stationName.toCharArray(stations[userStationIndex].name, 20);
stations[userStationIndex].frequency = frequency;
stations[userStationIndex].rdsText = "User Defined";
userStationIndex++;
lcd.setCursor(0, 2);
lcd.print("Station Saved!");
Serial.print("Station Saved: ");
Serial.println(frequency);
}
int applyEQ(int volume) {
switch (currentEQ) {
case BASS_BOOST:
return min(volume + 50, maxVolume);
case TREBLE_BOOST:
return min(volume + 25, maxVolume);
default:
return volume;
}
}
void displayMenu() {
static bool lastMenuState = false;
if (inMenu != lastMenuState) {
lcd.clear();
lastMenuState = inMenu;
}
lcd.setCursor(0, 0);
lcd.print("Mode: ");
lcd.print(inManualFrequencyMode ? "Manual Mode" : "Automatic Mode");
lcd.setCursor(0, 1);
lcd.print("EQ: ");
if (currentEQ == NORMAL) lcd.print("Normal");
else if (currentEQ == BASS_BOOST) lcd.print("Bass Boost");
else if (currentEQ == TREBLE_BOOST) lcd.print("Treble Boost");
lcd.setCursor(0, 2);
lcd.print("Change Mode: Save");
lcd.setCursor(0, 3);
lcd.print("Change EQ: Next");
if (digitalRead(saveButtonPin) == LOW) {
delay(300);
inManualFrequencyMode = !inManualFrequencyMode;
}
if (digitalRead(nextButtonPin) == LOW) {
delay(300);
currentEQ = (EQSetting)((currentEQ + 1) % 3);
}
}