Инструменты пользователя

Инструменты сайта


banddecoder_code

Это старая версия документа!


IP 192.168.0.240

v0.44

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.1768119282.txt.gz · Последнее изменение: eu8t