banddecoder_code
Это старая версия документа!
IP 192.168.0.240
v0.44
NEW CODE
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
/* ================= НАСТРОЙКИ ================= */
const float VERSION = 0.46; // Версия изменена
LiquidCrystal_I2C lcd(0x27, 16, 2);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 240);
unsigned int localPort = 12060;
EthernetUDP Udp;
const unsigned long CAT_TIMEOUT = 7000; // переключение в MANUAL
const unsigned long NET_TIMEOUT = 5000; // только надпись WAIT CAT DATA
const int ENC_A = 10;
const int ENC_B = 3;
const int ENC_BTN = 2;
// Используем 4 реле (A,B,C,D) + 5-й провод - земля
const int RELAYS[] = {4, 5, 6, 7}; // Реле A,B,C,D
const int RELAY_COUNT = 4; // Теперь точно 4 реле
/* ================= СОСТОЯНИЯ ================= */
enum Mode { AUTO, MANUAL };
Mode mode = AUTO;
bool manualForced = false;
bool autoFallback = false;
unsigned long lastCatTime = 0;
bool catActive = false;
unsigned long lastPacketTime = 0;
long lastFreq = 0;
int currentBand = -1;
int manualBandIndex = 0;
/* ================= ДИАПАЗОНЫ ================= */
struct Band {
const char* name;
long from;
long to;
byte abcdCode; // Код ABCD для этого диапазона
};
// Коды ABCD согласно вашей схеме:
// 4 реле: A(бит0), B(бит1), C(бит2), D(бит3)
// 160M = 0001 (A=1, B=0, C=0, D=0)
// 80M = 0010 (A=0, B=1, C=0, D=0)
// 40M = 0011 (A=1, B=1, C=0, D=0)
// 20M = 0101 (A=1, B=0, C=1, D=0)
// 15M = 0111 (A=1, B=1, C=1, D=0)
// 10M = 1001 (A=1, B=0, C=0, D=1)
Band bands[] = {
{"160M", 1800000, 2000000, 0b00000001}, // 0001
{"80M", 3500000, 3800000, 0b00000010}, // 0010
{"40M", 7000000, 7350000, 0b00000011}, // 0011
{"20M", 14000000, 14350000, 0b00000101}, // 0101
{"15M", 21000000, 21450000, 0b00000111}, // 0111
{"10M", 28000000, 29700000, 0b00001001} // 1001
};
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;
}
// Устанавливаем реле согласно коду ABCD
void setRelaysByABCD(byte abcdCode) {
Serial.print("Setting ABCD code: 0b");
for (int i = 3; i >= 0; i--) {
Serial.print((abcdCode >> i) & 1);
}
Serial.print(" (0x");
if (abcdCode < 0x10) Serial.print("0");
Serial.print(abcdCode, HEX);
Serial.println(")");
for (int i = 0; i < RELAY_COUNT; i++) {
// Проверяем соответствующий бит в коде ABCD
// i=0 -> бит0 (A), i=1 -> бит1 (B), i=2 -> бит2 (C), i=3 -> бит3 (D)
bool state = (abcdCode >> i) & 1;
digitalWrite(RELAYS[i], state ? HIGH : LOW);
Serial.print(" Relay ");
Serial.print((char)('A' + i));
Serial.print(" (pin ");
Serial.print(RELAYS[i]);
Serial.print("): ");
Serial.println(state ? "HIGH" : "LOW");
}
Serial.println();
}
// Установить реле для конкретного диапазона
void setRelaysByBand(int bandIndex) {
if (bandIndex >= 0 && bandIndex < BAND_COUNT) {
Serial.print("Setting band: ");
Serial.print(bands[bandIndex].name);
Serial.print(" [");
Serial.print(bandIndex);
Serial.println("]");
setRelaysByABCD(bands[bandIndex].abcdCode);
} else {
// Неизвестный диапазон - выключаем все реле
Serial.println("Unknown band - disabling all relays");
setRelaysByABCD(0b00000000);
}
}
// Выключить все реле
void disableAllRelays() {
Serial.println("Disabling all relays");
setRelaysByABCD(0b00000000);
}
void printFreqCompact(long f) {
int MHz = f / 1000000;
int kHz = (f / 1000) % 1000;
int hundred = (f / 100) % 10;
int tens = (f / 10) % 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);
lcd.print(tens);
}
/* ================= ЭКРАН ================= */
Mode lastMode = AUTO;
int lastBandIndex = -1;
long lastDisplayedFreq = 0;
bool forceDisplayUpdate = false;
void updateLCDIfNeeded() {
bool changed = false;
if (lastMode != mode) {
changed = true;
Serial.print("Mode changed: ");
Serial.println(mode == AUTO ? "AUTO" : "MANUAL");
}
if (mode != AUTO && lastBandIndex != manualBandIndex) {
changed = true;
Serial.print("Manual band changed to: ");
Serial.println(manualBandIndex);
}
if (mode == AUTO && lastBandIndex != currentBand) {
changed = true;
Serial.print("Auto band changed to: ");
Serial.println(currentBand);
}
if (mode == AUTO && lastDisplayedFreq != lastFreq) {
changed = true;
}
if (forceDisplayUpdate) {
changed = true;
forceDisplayUpdate = false;
}
if (!changed) return;
lcd.setCursor(0,0);
lcd.print("IP:");
lcd.print(ip);
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
if (mode == AUTO) {
lcd.print("[A] ");
if (currentBand >= 0) {
lcd.print(bands[currentBand].name);
} else {
lcd.print("--");
}
lcd.print(" ");
if (catActive) {
printFreqCompact(lastFreq);
} else {
lcd.print("NO CAT");
}
lastBandIndex = currentBand;
lastDisplayedFreq = lastFreq;
} else {
lcd.print("[M] ");
lcd.print(bands[manualBandIndex].name);
lcd.print(" ABCD:");
for (int i = 3; i >= 0; i--) {
lcd.print((bands[manualBandIndex].abcdCode >> i) & 1);
}
lastBandIndex = manualBandIndex;
}
lastMode = mode;
}
/* ================= СТАРТОВЫЙ ЭКРАН ================= */
void splashScreen() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("EW8ZO ver ");
lcd.print(VERSION, 2);
lcd.setCursor(0,1);
lcd.print("ABCD Decoder");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("ABCD Codes:");
lcd.setCursor(0,1);
for (int i = 0; i < min(6, BAND_COUNT); i++) {
lcd.print((char)('0' + (bands[i].abcdCode & 0x0F)));
}
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;
lastPacketTime = millis();
char* f = strstr(buf, "<Freq>");
if (!f) return;
f += 6;
lastFreq = atol(f) * 10;
Serial.print("Received freq: ");
Serial.print(lastFreq);
Serial.print(" Hz (");
int b = detectBand(lastFreq);
Serial.print("Band detection: ");
Serial.print(b);
Serial.println(")");
if (b >= 0) currentBand = b;
catActive = true;
lastCatTime = millis();
if (mode == MANUAL && autoFallback) {
Serial.println("Auto-fallback to AUTO mode");
mode = AUTO;
autoFallback = false;
manualForced = false;
setRelaysByBand(currentBand);
}
if (mode == AUTO) {
setRelaysByBand(currentBand);
}
updateLCDIfNeeded();
}
/* ================= КНОПКА ================= */
void handleButton() {
static bool pressed = false;
static unsigned long lastPress = 0;
const unsigned long DEBOUNCE_DELAY = 50;
if (!digitalRead(ENC_BTN)) {
if (!pressed && (millis() - lastPress > DEBOUNCE_DELAY)) {
pressed = true;
lastPress = millis();
Serial.println("Button pressed - toggling mode");
if (mode == AUTO) {
mode = MANUAL;
manualForced = true;
autoFallback = false;
Serial.println("Switching to MANUAL mode");
disableAllRelays(); // Выключаем все реле при ручном режиме
} else {
mode = AUTO;
manualForced = false;
autoFallback = false;
Serial.println("Switching to AUTO mode");
setRelaysByBand(currentBand); // Включаем реле для текущего диапазона
}
forceDisplayUpdate = true;
updateLCDIfNeeded();
}
} else {
pressed = false;
}
}
/* ================= ЭНКОДЕР ================= */
void handleEncoder() {
static int lastA = HIGH;
static unsigned long lastTurn = 0;
const unsigned long TURN_DEBOUNCE = 100;
if (mode == AUTO) return; // В автоматическом режиме энкодер не активен
int A = digitalRead(ENC_A);
if (A != lastA && A == LOW && (millis() - lastTurn > TURN_DEBOUNCE)) {
lastTurn = millis();
bool clockwise = digitalRead(ENC_B);
if (clockwise) {
manualBandIndex = (manualBandIndex + 1) % BAND_COUNT;
Serial.print("Encoder CW -> Band: ");
} else {
manualBandIndex = (manualBandIndex - 1 + BAND_COUNT) % BAND_COUNT;
Serial.print("Encoder CCW -> Band: ");
}
Serial.print(manualBandIndex);
Serial.print(" (");
Serial.print(bands[manualBandIndex].name);
Serial.println(")");
// Устанавливаем реле согласно выбранному диапазону в ручном режиме
setRelaysByBand(manualBandIndex);
forceDisplayUpdate = true;
updateLCDIfNeeded();
}
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;
Serial.println("CAT timeout - switching to MANUAL mode");
disableAllRelays(); // Выключаем все реле при переходе в ручной режим
forceDisplayUpdate = true;
updateLCDIfNeeded();
}
}
// Тестовая функция для проверки всех диапазонов
void testAllBands() {
Serial.println("\n=== TESTING ALL BANDS ===");
for (int i = 0; i < BAND_COUNT; i++) {
Serial.print("Testing ");
Serial.print(bands[i].name);
Serial.print(": ABCD=");
for (int j = 3; j >= 0; j--) {
Serial.print((bands[i].abcdCode >> j) & 1);
}
Serial.println();
setRelaysByBand(i);
delay(1000);
}
Serial.println("Test complete - disabling all relays");
disableAllRelays();
}
/* ================= SETUP ================= */
void setup() {
Serial.begin(115200);
Serial.println("\n=== Band Decoder ABCD Setup ===");
Serial.print("Version: ");
Serial.println(VERSION, 2);
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(ENC_BTN, INPUT_PULLUP);
// Инициализируем 4 реле
for (int i = 0; i < RELAY_COUNT; i++) {
pinMode(RELAYS[i], OUTPUT);
digitalWrite(RELAYS[i], LOW); // Гарантируем выключенное состояние
}
disableAllRelays(); // Выключаем все реле при старте
lcd.begin();
lcd.backlight();
splashScreen();
Ethernet.begin(mac, ip);
Serial.print("Assigned IP: ");
Serial.println(Ethernet.localIP());
Udp.begin(localPort);
Serial.print("UDP started on port ");
Serial.println(localPort);
// Выводим таблицу кодов ABCD при старте
Serial.println("\n=== BAND CONFIGURATION ===");
Serial.println("Band Freq Range ABCD Binary Hex");
Serial.println("--------------------------------------------");
for (int i = 0; i < BAND_COUNT; i++) {
Serial.print(bands[i].name);
Serial.print("\t");
Serial.print(bands[i].from);
Serial.print("-");
Serial.print(bands[i].to);
Serial.print("\t");
// Показываем ABCD код
Serial.print("ABCD=");
for (int j = 3; j >= 0; j--) {
Serial.print((bands[i].abcdCode >> j) & 1);
}
Serial.print(" (0b");
for (int j = 3; j >= 0; j--) {
Serial.print((bands[i].abcdCode >> j) & 1);
}
Serial.print(")");
Serial.print(" 0x");
if (bands[i].abcdCode < 0x10) Serial.print("0");
Serial.println(bands[i].abcdCode, HEX);
}
Serial.println("\n=== PIN CONFIGURATION ===");
Serial.println("Relay Pin Bit");
Serial.println("----------------");
for (int i = 0; i < RELAY_COUNT; i++) {
Serial.print("Relay ");
Serial.print((char)('A' + i));
Serial.print(": ");
Serial.print(RELAYS[i]);
Serial.print(" ");
Serial.print(i);
Serial.print(" (");
Serial.print("Bit ");
Serial.print(i);
Serial.println(")");
}
Serial.println("\n=== CONTROL ===");
Serial.println("- Button: Toggle AUTO/MANUAL");
Serial.println("- Encoder: Change band in MANUAL mode");
Serial.println("- CAT Timeout: ");
Serial.print(CAT_TIMEOUT);
Serial.println(" ms");
Serial.println("- Network Timeout: ");
Serial.print(NET_TIMEOUT);
Serial.println(" ms");
// Запускаем тест всех диапазонов
Serial.println("\n=== STARTUP RELAY TEST ===");
testAllBands();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("IP:");
lcd.print(ip);
lcd.setCursor(0,1);
lcd.print("READY");
Serial.println("\n=== Setup complete ===");
Serial.println("System READY");
Serial.println("==============================\n");
}
/* ================= LOOP ================= */
void loop() {
readUDP();
handleEncoder();
handleButton();
checkCatTimeout();
// Периодическое обновление дисплея
static unsigned long lastDisplayUpdate = 0;
if (millis() - lastDisplayUpdate > 1000) {
lastDisplayUpdate = millis();
updateLCDIfNeeded();
}
// Отображение статуса сети
if (millis() - lastPacketTime > NET_TIMEOUT && mode == AUTO && !catActive) {
static unsigned long lastStatusUpdate = 0;
if (millis() - lastStatusUpdate > 1000) {
lastStatusUpdate = millis();
lcd.setCursor(0,0);
lcd.print("IP:");
lcd.print(ip);
lcd.setCursor(0,1);
lcd.print("NO CAT SIGNAL ");
}
}
// Небольшая задержка для стабильности
delay(10);
}
OLD CODE
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
/* ================= НАСТРОЙКИ ================= */
const float VERSION = 0.44;
LiquidCrystal_I2C lcd(0x27, 16, 2);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 240);
unsigned int localPort = 12060;
EthernetUDP Udp;
const unsigned long CAT_TIMEOUT = 7000; // переключение в MANUAL
const unsigned long NET_TIMEOUT = 5000; // только надпись WAIT CAT DATA
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;
bool manualForced = false;
bool autoFallback = false;
unsigned long lastCatTime = 0;
bool catActive = false;
unsigned long lastPacketTime = 0;
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);
}
void printFreqCompact(long f) {
int MHz = f / 1000000;
int kHz = (f / 1000) % 1000;
int hundred = (f / 100) % 10;
int tens = (f / 10) % 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);
lcd.print(tens);
}
/* ================= ЭКРАН ================= */
Mode lastMode = AUTO;
int lastBandIndex = -1;
long lastDisplayedFreq = 0;
void updateLCDIfNeeded() {
bool changed = false;
if (lastMode != mode) changed = true;
if (mode != AUTO && lastBandIndex != manualBandIndex) changed = true;
if (mode == AUTO && lastBandIndex != currentBand) changed = true;
if (mode == AUTO && lastDisplayedFreq != lastFreq) changed = true;
if (!changed) return;
lcd.setCursor(0,0);
lcd.print("IP:");
lcd.print(ip);
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
if (mode == AUTO) {
lcd.print("[A]");
if (currentBand >= 0) lcd.print(bands[currentBand].name);
else lcd.print("--");
lcd.print(" ");
if (catActive) printFreqCompact(lastFreq);
else lcd.print("WAIT CAT DATA");
lastBandIndex = currentBand;
lastDisplayedFreq = lastFreq;
} else {
lcd.print("MANUAL ");
lcd.print(bands[manualBandIndex].name);
lastBandIndex = manualBandIndex;
}
lastMode = mode;
}
/* ================= СТАРТОВЫЙ ЭКРАН ================= */
void splashScreen() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("EW8ZO ver ");
lcd.print(VERSION, 2);
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;
lastPacketTime = millis();
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();
if (mode == MANUAL && autoFallback) {
mode = AUTO;
autoFallback = false;
manualForced = false;
setRelays(currentBand);
}
if (mode == AUTO) setRelays(currentBand);
updateLCDIfNeeded();
}
/* ================= КНОПКА ================= */
void handleButton() {
static bool pressed = false;
if (!digitalRead(ENC_BTN)) {
pressed = true;
} else {
if (pressed) {
if (mode == AUTO) {
mode = MANUAL;
manualForced = true;
autoFallback = false;
setRelays(-1);
} else {
mode = AUTO;
manualForced = false;
autoFallback = false;
setRelays(currentBand);
}
updateLCDIfNeeded();
}
pressed = false;
}
}
/* ================= ЭНКОДЕР ================= */
void handleEncoder() {
static int lastA = HIGH;
int A = digitalRead(ENC_A);
if (A != lastA && A == LOW && mode != AUTO) {
if (digitalRead(ENC_B))
manualBandIndex = (manualBandIndex + 1) % BAND_COUNT;
else
manualBandIndex = (manualBandIndex - 1 + BAND_COUNT) % BAND_COUNT;
updateLCDIfNeeded();
}
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);
updateLCDIfNeeded();
}
}
/* ================= SETUP ================= */
void setup() {
Serial.begin(115200);
Serial.println("=== Setup start ===");
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);
Serial.print("Assigned IP: ");
Serial.println(Ethernet.localIP());
Udp.begin(localPort);
Serial.println("UDP started");
lcd.clear();
lcd.setCursor(0,0);
lcd.print("IP:");
lcd.print(ip);
lcd.setCursor(0,1);
lcd.print("WAIT CAT DATA");
Serial.println("=== Setup end ===");
}
/* ================= LOOP ================= */
void loop() {
readUDP();
handleEncoder();
handleButton();
checkCatTimeout(); // переключение в MANUAL при CAT_TIMEOUT
// только надпись при NET_TIMEOUT
if (millis() - lastPacketTime > NET_TIMEOUT && mode == AUTO) {
lcd.setCursor(0,0);
lcd.print("IP:");
lcd.print(ip);
lcd.setCursor(0,1);
lcd.print("WAIT CAT DATA ");
}
}
banddecoder_code.1768297988.txt.gz · Последнее изменение: — eu8t

