banddecoder_code
Это старая версия документа!
v0.42
CODE
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
/* ================= НАСТРОЙКИ ================= */
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 240); // IP декодера
unsigned int localPort = 12060;
// CAT timeout
const unsigned long CAT_TIMEOUT = 7000;
// Энкодер (проверенные пины)
const int ENC_A = 10;
const int ENC_B = 3;
const int ENC_BTN = 2;
// Реле
const int RELAYS[] = {4, 5, 6, 7, 8, 9};
const int RELAY_COUNT = sizeof(RELAYS) / sizeof(int);
/* ================= СОСТОЯНИЯ ================= */
enum Mode { AUTO, MANUAL };
Mode mode = AUTO;
// Причины MANUAL
bool manualForced = false; // пользователь
bool autoFallback = false; // потеря CAT
EthernetUDP Udp;
unsigned long lastCatTime = 0;
bool catActive = false;
long lastFreq = 0;
int currentBand = -1;
int manualBandIndex = 0;
/* ================= ДИАПАЗОНЫ ================= */
struct Band {
const char* name;
long from;
long to;
};
Band bands[] = {
{"160M", 1800000, 2000000},
{"80M", 3500000, 3800000},
{"40M", 7000000, 7350000},
{"20M", 14000000, 14350000},
{"15M", 21000000, 21450000},
{"10M", 28000000, 29700000}
};
const int BAND_COUNT = sizeof(bands) / sizeof(Band);
/* ================= СЛУЖЕБНЫЕ ================= */
int detectBand(long freq) {
for (int i = 0; i < BAND_COUNT; i++) {
if (freq >= bands[i].from && freq <= bands[i].to)
return i;
}
return -1;
}
void setRelays(int bandIndex) {
for (int i = 0; i < RELAY_COUNT; i++)
digitalWrite(RELAYS[i], (i == bandIndex) ? HIGH : LOW);
if (bandIndex < 0)
for (int i = 0; i < RELAY_COUNT; i++)
digitalWrite(RELAYS[i], LOW);
}
// Формат: 7.165.7
void printFreqCompact(long f) {
int MHz = f / 1000000;
int kHz = (f / 1000) % 1000;
int hundred = (f / 100) % 10;
lcd.print(MHz);
lcd.print(".");
if (kHz < 100) lcd.print("0");
if (kHz < 10) lcd.print("0");
lcd.print(kHz);
lcd.print(".");
lcd.print(hundred);
}
/* ================= ЭКРАН ================= */
void drawScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("IP:");
lcd.print(ip);
lcd.setCursor(0, 1);
if (mode == AUTO) {
lcd.print("AUTO:");
if (currentBand >= 0) lcd.print(bands[currentBand].name);
else lcd.print("--");
lcd.print(" ");
if (catActive) printFreqCompact(lastFreq);
else lcd.print("NO CAT");
} else {
lcd.print("MANUAL:");
lcd.print(bands[manualBandIndex].name);
}
}
/* ================= СТАРТ ================= */
void splashScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("EW8ZO ver 0.33");
lcd.setCursor(0, 1);
lcd.print("Band Decoder");
delay(2000);
}
/* ================= UDP ================= */
void readUDP() {
int packetSize = Udp.parsePacket();
if (!packetSize) return;
char buf[400];
int len = Udp.read(buf, sizeof(buf) - 1);
if (len <= 0) return;
buf[len] = 0;
char* f = strstr(buf, "<Freq>");
if (!f) return;
f += 6;
lastFreq = atol(f) * 10;
int b = detectBand(lastFreq);
if (b >= 0) currentBand = b;
catActive = true;
lastCatTime = millis();
// 🔁 возврат из auto-fallback
if (mode == MANUAL && autoFallback) {
mode = AUTO;
autoFallback = false;
manualForced = false;
}
if (mode == AUTO) setRelays(currentBand);
drawScreen();
}
/* ================= КНОПКА ================= */
void handleButton() {
static unsigned long pressTime = 0;
static bool pressed = false;
if (!digitalRead(ENC_BTN)) {
if (!pressed) {
pressed = true;
pressTime = millis();
}
} else {
if (pressed && millis() - pressTime > 800) {
if (mode == AUTO) {
mode = MANUAL;
manualForced = true;
autoFallback = false;
setRelays(-1);
} else {
mode = AUTO;
manualForced = false;
autoFallback = false;
setRelays(currentBand);
}
drawScreen();
}
pressed = false;
}
}
/* ================= ЭНКОДЕР ================= */
void handleEncoder() {
static int lastA = HIGH;
int A = digitalRead(ENC_A);
if (A != lastA && A == LOW && mode == MANUAL) {
if (digitalRead(ENC_B))
manualBandIndex = (manualBandIndex + 1) % BAND_COUNT;
else
manualBandIndex = (manualBandIndex - 1 + BAND_COUNT) % BAND_COUNT;
drawScreen();
}
lastA = A;
}
/* ================= TIMEOUT ================= */
void checkCatTimeout() {
if (mode != AUTO) return;
if (catActive && millis() - lastCatTime > CAT_TIMEOUT) {
catActive = false;
mode = MANUAL;
autoFallback = true;
manualForced = false;
manualBandIndex = (currentBand >= 0) ? currentBand : 0;
setRelays(-1);
drawScreen();
}
}
/* ================= SETUP ================= */
void setup() {
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(ENC_BTN, INPUT_PULLUP);
for (int i = 0; i < RELAY_COUNT; i++)
pinMode(RELAYS[i], OUTPUT);
setRelays(-1);
lcd.begin();
lcd.backlight();
splashScreen();
Ethernet.begin(mac, ip);
Udp.begin(localPort);
drawScreen();
}
/* ================= LOOP ================= */
void loop() {
readUDP();
handleEncoder();
handleButton();
checkCatTimeout();
}
banddecoder_code.1768119237.txt.gz · Последнее изменение: — eu8t

