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

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


banddecoder_code

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
banddecoder_code [2026/01/16 22:56] eu8tbanddecoder_code [2026/01/23 08:04] (текущий) eu8t
Строка 1: Строка 1:
-IP 192.168.0.240+IP 192.168.0.240 (можно сменить через настройки)
  
-v0.50+v0.81 (примерно) 
 + 
 +{{:clip2net_menu_260117214628.jpeg?800|}} 
 + 
 +{{:clip2net_menu_260117214613.jpeg?800|}}
  
-{{:clip2net_menu_260110231520.jpeg|}} 
  
  
Строка 12: Строка 15:
 #include <Wire.h> #include <Wire.h>
 #include <LiquidCrystal_I2C.h> #include <LiquidCrystal_I2C.h>
 +#include <EEPROM.h>
  
-const float VERSION 0.60; +// ====================================================
-LiquidCrystal_I2C lcd(0x27, 16, 2);+// === CONFIG: все константы устройства в одном месте === 
 +// =====================================================
  
-byte mac[] { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }+// --- EEPROM --- 
-IPAddress ip(192, 168, 0, 240)+const byte EEPROM_MAGIC      0x42
-unsigned int localPort 12060;+const int  EEPROM_ADDR_MAGIC = 0; 
 +const int  EEPROM_ADDR_IP    1  // 1..4
  
-EthernetUDP Udp;+// --- Версия прошивки --- 
 +const float VERSION = 0.81;
  
 +// --- CAT / сеть ---
 const unsigned long CAT_TIMEOUT = 7000; const unsigned long CAT_TIMEOUT = 7000;
 const unsigned long NET_TIMEOUT = 5000; const unsigned long NET_TIMEOUT = 5000;
  
 +// --- Пины энкодера ---
 const int ENC_A   = 8; const int ENC_A   = 8;
 const int ENC_B   = A1; const int ENC_B   = A1;
 const int ENC_BTN = 3; const int ENC_BTN = 3;
  
 +// --- Пины реле ---
 const int RELAYS[] = {4, 5, 6, 7}; const int RELAYS[] = {4, 5, 6, 7};
 const int RELAY_COUNT = 4; const int RELAY_COUNT = 4;
  
-enum Mode { AUTO, MANUAL }+// --- Кнопка --- 
-Mode mode AUTO;+const unsigned long SHORT_PRESS = 100; 
 +const unsigned long LONG_PRESS  = 3000
 +const unsigned long HOLD_TIME   700;
  
-bool manualForced false+// --- Редактор IP --- 
-bool autoFallback = false;+const unsigned long EDITOR_CLICK_GUARD 200; 
 + 
 +// --- Анимация CAT --- 
 +const int CAT_ANIM_STEPS = 5; 
 + 
 + 
 +// ===================================================== 
 +// === ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ (состояние устройства) === 
 +// ===================================================== 
 + 
 +// --- IP редактор --- 
 +bool ipEditMode = false
 +byte ipEdit[4]; 
 +int ipOctetIndex = 0; 
 + 
 +// --- LCD --- 
 +LiquidCrystal_I2C lcd(0x27, 16, 2); 
 + 
 +// --- Ethernet --- 
 +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
 +IPAddress ip(192, 168, 0, 240); 
 +unsigned int localPort = 12060; 
 +IPAddress effectiveIP = ip; 
 +EthernetUDP Udp;
  
 +// --- CAT состояние ---
 unsigned long lastCatTime = 0; unsigned long lastCatTime = 0;
 bool catActive = false; bool catActive = false;
- 
 unsigned long lastPacketTime = 0; unsigned long lastPacketTime = 0;
- 
 long lastFreq = 0; long lastFreq = 0;
 bool freqReceived = false; bool freqReceived = false;
 +byte catAnimPos = 0;
 +int catPacketCounter = 0;
  
 +byte catDot[8] = {
 +  0b00000,
 +  0b00100,
 +  0b01110,
 +  0b01110,
 +  0b01110,
 +  0b00100,
 +  0b00000,
 +  0b00000
 +};
  
-int currentBand = -1+// --- Режимы --- 
-int manualBandIndex 0+enum Mode { AUTO, MANUAL }
-int lastA HIGH; +Mode mode AUTO
 +bool manualForced false;
  
 +// --- Диапазоны ---
 struct Band { struct Band {
   const char* name;   const char* name;
Строка 60: Строка 107:
  
 Band bands[] = { Band bands[] = {
-  {"160M", 1800000, 2000000, 0b00000001}, // BCD 0001 → Output 1 +  {"160M", 1800000, 2000000, 0b00000001}, 
-  {"80M",  3500000, 3800000, 0b00000010}, // BCD 0010 → Output 2 +  {"80M",  3500000, 3800000, 0b00000010}, 
-  {"40M",  7000000, 7350000, 0b00000011}, // BCD 0011 → Output 3 +  {"40M",  7000000, 7350000, 0b00000011}, 
-  {"30M", 10100000, 10150000, 0b00000100}, // BCD 0100 → Output 4 +  {"20M", 14000000, 14350000, 0b00000101}, 
-  {"20M", 14000000, 14350000, 0b00000101}, // BCD 0101 → Output 5 +  {"15M", 21000000, 21450000, 0b00000111}, 
-  {"17M", 18068000, 18168000, 0b00000110}, // BCD 0110 → Output 6 +  {"10M", 28000000, 29700000, 0b00001001}
-  {"15M", 21000000, 21450000, 0b00000111}, // BCD 0111 → Output 7 +
-  {"12M", 24890000, 24990000, 0b00001000}, // BCD 1000 → Output 8 +
-  {"11M", 26900000, 27999000, 0b00001001},  // BCD 1001 → same as 10M +
-  {"10M", 28000000, 29700000, 0b00001001}, // BCD 1001 → Output 9 +
-  {"6M",  50000000, 52000000, 0b00001010} // BCD 1010 → Output 10  +
 }; };
- 
  
 const int BAND_COUNT = sizeof(bands) / sizeof(Band); const int BAND_COUNT = sizeof(bands) / sizeof(Band);
 +
 +// --- Текущее состояние диапазонов ---
 +int currentBand = -1;
 +int manualBandIndex = 0;
 +
 +// --- Энкодер ---
 +int lastA = HIGH;
 +
 +// --- Кнопка ---
 +bool buttonHeld = false;
 +bool pressed = false;
 +unsigned long pressStart = 0;
 +bool ignoreNextEditorClick = false;
 +
 +// --- LCD обновление ---
 +Mode lastMode = AUTO;
 +int lastBandIndex = -1;
 +long lastDisplayedFreq = 0;
 +bool forceDisplayUpdate = false;
  
 int detectBand(long freq) { int detectBand(long freq) {
Строка 101: Строка 161:
   setRelaysByABCD(0);   setRelaysByABCD(0);
 } }
 +
 +void saveIPToEEPROM(IPAddress ipToSave) {
 +  EEPROM.update(EEPROM_ADDR_MAGIC, EEPROM_MAGIC);
 +  for (int i = 0; i < 4; i++)
 +    EEPROM.update(EEPROM_ADDR_IP + i, ipToSave[i]);
 +}
 +
 +bool loadIPFromEEPROM(IPAddress &out) {
 +  if (EEPROM.read(EEPROM_ADDR_MAGIC) != EEPROM_MAGIC) return false;
 +  byte b[4];
 +  for (int i = 0; i < 4; i++)
 +    b[i] = EEPROM.read(EEPROM_ADDR_IP + i);
 +  out = IPAddress(b[0], b[1], b[2], b[3]);
 +  return true;
 +}
 +
 +void enterIpEditMode() {
 +  ipEditMode = true;
 +
 +  for (int i = 0; i < 4; i++)
 +    ipEdit[i] = effectiveIP[i];
 +
 +  ipOctetIndex = 0;
 +  drawIpEditor();
 +  ignoreNextEditorClick = true;
 +}
 +
 +void drawIpEditor() {
 +  lcd.clear();
 +  lcd.setCursor(0,0);
 +  lcd.print("SET IP:");
 +
 +  lcd.setCursor(0,1);
 +
 +  for (int i = 0; i < 4; i++) {
 +
 +    // подчёркивание перед редактируемым октетом
 +    if (i == ipOctetIndex)
 +      lcd.print("_");
 +    else
 +      lcd.print("");   // ← НИЧЕГО НЕ ПЕЧАТАЕМ
 +
 +    // вывод октета с ведущими нулями
 +    int val = ipEdit[i];
 +    if (val < 100) lcd.print("0");
 +    if (val < 10)  lcd.print("0");
 +    lcd.print(val);
 +
 +    if (i < 3) lcd.print(".");
 +  }
 +}
 +
 +
  
 void printFreqCompact(long f) { void printFreqCompact(long f) {
Строка 118: Строка 231:
 } }
  
-Mode lastMode = AUTO+ 
-int lastBandIndex -1; +void runRelayTest() { 
-long lastDisplayedFreq = 0; +  lcd.clear()
-bool forceDisplayUpdate = false;+  lcd.setCursor(0,0); 
 +  lcd.print("TEST RELAYS"); 
 + 
 +  for (int 0; i < BAND_COUNT; i++) { 
 + 
 +    // включаем реле 
 +    setRelaysByBand(i); 
 + 
 +    // выводим комбинацию ABCD 
 +    lcd.setCursor(0,1)
 +    for (int b = 3; b >= 0; b--) 
 +      lcd.print((bands[i].abcdCode >> b) & 1); 
 + 
 +    delay(600); 
 +  } 
 + 
 +  disableAllRelays(); 
 +  delay(300); 
 + 
 +  forceDisplayUpdate = true; 
 +  updateLCDIfNeeded(); 
 +}
  
 void updateLCDIfNeeded() { void updateLCDIfNeeded() {
 +  if (ipEditMode) return;
   bool changed = false;   bool changed = false;
  
Строка 134: Строка 269:
   if (!changed) return;   if (!changed) return;
  
-  lcd.setCursor(0,0); +  updateTopLine(); 
-  lcd.print("IP:"); +  
-  lcd.print(ip); +
   lcd.setCursor(0,1);   lcd.setCursor(0,1);
   lcd.print("                ");   lcd.print("                ");
Строка 165: Строка 298:
   lastMode = mode;   lastMode = mode;
 } }
 +
 +void updateTopLine() {
 +  if (ipEditMode) return;
 +  lcd.setCursor(0,0);
 +  lcd.print("                ");  
 +  lcd.setCursor(0,0);
 +
 +  // === AUTO режим ===
 +  if (mode == AUTO) {
 +    lcd.print("CAT ");
 +
 +    if (catActive) {
 +      // 5-позиционная анимация
 +      for (int i = 0; i < 5; i++) {
 +        if (i == catAnimPos)
 +          lcd.write(byte(0));   // кастомная точка
 +        else
 +          lcd.print(".");
 +      }
 +
 +      lcd.print("   ");
 +
 +      // Показ реле
 +      if (currentBand >= 0) {
 +        for (int i = 3; i >= 0; i--)
 +          lcd.print((bands[currentBand].abcdCode >> i) & 1);
 +      } else {
 +        lcd.print("----");
 +      }
 +
 +    } else {
 +      // CAT пропал
 +      lcd.print(".....   ");
 +      if (currentBand >= 0) {
 +        for (int i = 3; i >= 0; i--)
 +          lcd.print((bands[currentBand].abcdCode >> i) & 1);
 +      } else {
 +        lcd.print("----");
 +      }
 +    }
 +
 +    return;
 +  }
 +
 +  // === MANUAL режим ===
 +  lcd.print("CAT ");
 +  if (catActive) lcd.print("OK");
 +  else lcd.print("--");
 +}
 +
 +
  
 void splashScreen() { void splashScreen() {
Строка 190: Строка 374:
   lastCatTime = millis();   lastCatTime = millis();
   catActive = true;   catActive = true;
 +
 +  // Если MANUAL был включён автоматически (fallback), а CAT снова появился — возвращаемся в AUTO
 +  if (mode == MANUAL && !manualForced) {
 +      mode = AUTO;
 +      
 +  
 +      // Восстанавливаем реле по текущему диапазону
 +      if (currentBand >= 0)
 +          setRelaysByBand(currentBand);
 +  
 +      forceDisplayUpdate = true;
 +      updateLCDIfNeeded();
 +  }
 +
 +  
 +  // Двигаем CAT-анимацию каждые 2 пакета  
 +  catPacketCounter++;
 +  if (catPacketCounter >= 2) {   // ← каждые 2 пакета
 +      catPacketCounter = 0;
 +      catAnimPos = (catAnimPos + 1) % 5;
 +      updateTopLine();
 +  }
 +
  
   // Ищем <Freq>   // Ищем <Freq>
Строка 214: Строка 421:
  
  
 +void handleButtonPress() {
 +    pressed = true;
 +    pressStart = millis();
 +    buttonHeld = false;
 +}
  
-// +void handleButtonHold(unsigned long held) {
-// === КНОПКА С АНТИДРЕБЕЗГОМ И ЗАЩИТОЙ ОТ ЛОЖНЫХ СРАБАТЫВАНИЙ === +
-// +
-void handleButton() { +
-  static bool pressed = false; +
-  static unsigned long pressStart = 0; +
-  static unsigned long lastCheck = 0;+
  
-  const unsigned long SHORT_PRESS 100+    // длинное → вход в редактор 
-  const unsigned long LONG_PRESS  3000;+    if (!ipEditMode && held >LONG_PRESS) { 
 +        enterIpEditMode()
 +        pressed false; 
 +        buttonHeld = false; 
 +        return; 
 +    }
  
-  // антидребезг кнопки +    // жест удержания 
-  if (millis(- lastCheck < 30) return; +    if (!ipEditMode && !buttonHeld && held >= HOLD_TIME{ 
-  lastCheck millis();+        buttonHeld true; 
 +    } 
 +}
  
-  bool btn = !digitalRead(ENC_BTN);+void handleIpEditorClick(unsigned long pressTime
 +    static unsigned long lastEditorClick = 0;
  
-  // начало нажатия +    // игнорируем первый клик после входа в редактор 
-  if (btn && !pressed) { +    if (ignoreNextEditorClick) { 
-    pressed true+        ignoreNextEditorClick false
-    pressStart = millis()+        return
-  }+    }
  
-  // отпускание кнопки +    // длинное → выход без сохранения
-  if (!btn && pressed) { +
-    unsigned long pressTime = millis() - pressStart; +
-    pressed = false; +
- +
-    // === ДЛИННОЕ НАЖАТИЕ: ТЕСТ РЕЛЕ ===+
     if (pressTime >= LONG_PRESS) {     if (pressTime >= LONG_PRESS) {
-      lcd.clear()+        ipEditMode = false
-      lcd.setCursor(0,0)+        forceDisplayUpdate = true
-      lcd.print("TEST RELAYS");+        updateLCDIfNeeded(); 
 +        return; 
 +    }
  
-      for (int i = 0; i BAND_COUNT; i++) { +    // защита от двойного клика 
-        setRelaysByBand(i); +    if (millis() - lastEditorClick 200return
-        delay(500); +    lastEditorClick = millis();
-      }+
  
-      disableAllRelays(); +    // короткое → следующий октет 
-      delay(500);+    if (pressTime >= 50{ 
 +        ipOctetIndex++;
  
-      lcd.clear(); +        if (ipOctetIndex > 3{ 
-      lcd.setCursor(0,0); +            effectiveIP = IPAddress(ipEdit[0]ipEdit[1]ipEdit[2], ipEdit[3]); 
-      lcd.print("ABCD:"); +            saveIPToEEPROM(effectiveIP);
-      lcd.setCursor(0,1); +
-      for (int i = 0; i < BAND_COUNT; i++) { +
-        for (int b = 3; b >= 0; b--) +
-          lcd.print((bands[i].abcdCode >> b) & 1); +
-        lcd.print(" "); +
-      } +
-      delay(1500);+
  
-      // восстановление реле +            lcd.clear(); 
-      if (mode == MANUAL+            lcd.setCursor(0,0); 
-        setRelaysByBand(manualBandIndex); +            lcd.print("IP SAVED"); 
-      else +            lcd.setCursor(0,1); 
-        setRelaysByBand(currentBand);+            lcd.print(effectiveIP); 
 +            delay(1200);
  
-      forceDisplayUpdate = true; +            ipEditMode = false; 
-      updateLCDIfNeeded(); +            forceDisplayUpdate = true; 
-      return;+            updateLCDIfNeeded(); 
 +            return
 +        } 
 + 
 +        drawIpEditor();
     }     }
 +}
  
-    // === КОРОТКОЕ НАЖАТИЕ: ПЕРЕКЛЮЧЕНИЕ РЕЖИМА === +void toggleAutoManual() {
-    if (pressTime >= SHORT_PRESS) {+
  
-      // ПЕРЕХОД AUTO → MANUAL +    if (mode == AUTO) {
-      if (mode == AUTO) {+
         mode = MANUAL;         mode = MANUAL;
         manualForced = true;         manualForced = true;
-        autoFallback = false; +        
- +
-        // ВСЕГДА берём диапазон из AUTO +
-        if (currentBand >= 0) +
-          manualBandIndex = currentBand; +
-        else +
-          manualBandIndex = 0;   // fallback при отсутствии CAT+
  
 +        manualBandIndex = (currentBand >= 0 ? currentBand : 0);
         setRelaysByBand(manualBandIndex);         setRelaysByBand(manualBandIndex);
-      }+    } 
 +    else { 
 +        if (!catActive) { 
 +            lcd.clear(); 
 +            lcd.setCursor(0,0); 
 +            lcd.print("NO CAT LINK"); 
 +            lcd.setCursor(0,1); 
 +            lcd.print("AUTO DISABLED"); 
 +            delay(1200); 
 + 
 +            forceDisplayUpdate = true; 
 +            updateLCDIfNeeded(); 
 +            return; 
 +        }
  
-      // ПЕРЕХОД MANUAL → AUTO 
-      else { 
         mode = AUTO;         mode = AUTO;
         manualForced = false;         manualForced = false;
-        autoFallback = false;+        
  
         if (currentBand >= 0)         if (currentBand >= 0)
-          setRelaysByBand(currentBand);+            setRelaysByBand(currentBand);
         else         else
-          disableAllRelays(); +            disableAllRelays(); 
-      }+    }
  
-      forceDisplayUpdate = true; +    forceDisplayUpdate = true; 
-      updateLCDIfNeeded();+    updateLCDIfNeeded()
 +
 + 
 +void handleButtonRelease(unsigned long pressTime) { 
 + 
 +    // редактор 
 +    if (ipEditMode) { 
 +        handleIpEditorClick(pressTime); 
 +        return;
     }     }
-  }+ 
 +    // длинное → вход в редактор 
 +    if (pressTime >= LONG_PRESS) { 
 +        enterIpEditMode(); 
 +        return; 
 +    } 
 + 
 +    // короткое → AUTO/MANUAL 
 +    if (!buttonHeld && pressTime >= SHORT_PRESS) { 
 +        toggleAutoManual(); 
 +    } 
 + 
 +    buttonHeld = false;
 } }
 +
 +
 +//
 +// === КНОПКА С АНТИДРЕБЕЗГОМ И ЗАЩИТОЙ ОТ ЛОЖНЫХ СРАБАТЫВАНИЙ ===
 +//
 +void handleButton() {
 +    static unsigned long lastCheck = 0;
 +
 +    if (millis() - lastCheck < 30) return;
 +    lastCheck = millis();
 +
 +    bool btn = !digitalRead(ENC_BTN);
 +
 +    // начало нажатия
 +    if (btn && !pressed) {
 +        handleButtonPress();
 +        return;
 +    }
 +
 +    // удержание
 +    if (btn && pressed) {
 +        unsigned long held = millis() - pressStart;
 +        handleButtonHold(held);
 +        return;
 +    }
 +
 +    // отпускание
 +    if (!btn && pressed) {
 +        pressed = false;
 +        unsigned long pressTime = millis() - pressStart;
 +        handleButtonRelease(pressTime);
 +        return;
 +    }
 +}
 +
  
  
Строка 320: Строка 589:
 // //
 void handleEncoder() { void handleEncoder() {
-  if (mode == AUTO) return; 
-  if (!freqReceived) return;   // ← абсолютная защита 
-   
   static unsigned long lastMove = 0;   static unsigned long lastMove = 0;
- 
-  if (millis() - lastMove < 50) return; 
  
   int A = digitalRead(ENC_A);   int A = digitalRead(ENC_A);
-  if (A == lastA) return; +  if (A == lastA) return; 
 + 
 +  // реагируем только на фронт A == LOW
   if (A != lastA && A == LOW) {   if (A != lastA && A == LOW) {
-    lastMove = millis(); 
  
     bool clockwise = digitalRead(ENC_B);     bool clockwise = digitalRead(ENC_B);
  
-    if (clockwise) +    // === УДЕРЖАНИЕ КНОПКИ ПОВОРОТ === 
-      manualBandIndex (manualBandIndex 1) % BAND_COUNT; +    if (buttonHeld && !ipEditMode{
-    else +
-      manualBandIndex = (manualBandIndex - 1 + BAND_COUNT% BAND_COUNT;+
  
-    setRelaysByBand(manualBandIndex); +      if (clockwise) { 
-    forceDisplayUpdate = true; +        runRelayTest(); 
-    updateLCDIfNeeded();+      } else { 
 +        // резерв 
 +      } 
 + 
 +      buttonHeld = false; 
 +      lastA = A; 
 +      return; 
 +    } 
 + 
 +    // === РЕЖИМ IP-РЕДАКТОРА === 
 +    if (ipEditMode) { 
 + 
 +      if (millis() - lastMove < 80) { 
 +        lastA = A; 
 +        return; 
 +      } 
 +      lastMove = millis(); 
 + 
 +      int val = ipEdit[ipOctetIndex]; 
 +      if (clockwise) val++; 
 +      else val--; 
 + 
 +      if (val < 0) val = 255; 
 +      if (val > 255) val = 0; 
 + 
 +      ipEdit[ipOctetIndex] = val; 
 +      drawIpEditor(); 
 + 
 +      lastA = A; 
 +      return; 
 +    } 
 + 
 +    // === MANUAL режим === 
 +    if (mode == MANUAL) { 
 + 
 +      if (millis() - lastMove < 50) { 
 +        lastA = A; 
 +        return; 
 +      } 
 +      lastMove = millis(); 
 + 
 +      if (clockwise) 
 +        manualBandIndex = (manualBandIndex + 1) % BAND_COUNT; 
 +      else 
 +        manualBandIndex = (manualBandIndex - 1 + BAND_COUNT) % BAND_COUNT; 
 + 
 +      setRelaysByBand(manualBandIndex); 
 +      forceDisplayUpdate = true; 
 +      updateLCDIfNeeded(); 
 +    }
   }   }
  
   lastA = A;   lastA = A;
 } }
 +
  
  
Строка 351: Строка 664:
  
 void checkCatTimeout() { void checkCatTimeout() {
-  if (mode != AUTO) return; 
  
 +  // 1) Сбрасываем CAT независимо от режима
   if (catActive && millis() - lastCatTime > CAT_TIMEOUT) {   if (catActive && millis() - lastCatTime > CAT_TIMEOUT) {
-    catActive = false; +      catActive = false; 
-    mode = MANUAL; + 
-    autoFallback = true; +      // ОБНОВЛЯЕМ ПЕРВУЮ СТРОКУ 
-    manualForced = false; +      updateTopLine(); 
-    //manualBandIndex = (currentBand >= 0? currentBand : 0+  } 
-    //setRelaysByBand(manualBandIndex); + 
-    if (currentBand >= 0) { +  // 2) Логика fallback только в AUTO 
-      manualBandIndex = currentBand;+  if (mode == AUTO && !catActive
 +      mode = MANUAL      
 +      manualForced = false; 
 + 
 +      if (currentBand >= 0) { 
 +          manualBandIndex = currentBand; 
 +      }
       setRelaysByBand(manualBandIndex);       setRelaysByBand(manualBandIndex);
-    } else { 
-        // CAT пропал, но диапазон неизвестен — оставляем реле как есть 
-    } 
  
-    forceDisplayUpdate = true; +      forceDisplayUpdate = true; 
-    updateLCDIfNeeded();+      updateLCDIfNeeded();
   }   }
 } }
  
-void setup() { + 
-   + 
-  //Serial.begin(115200); delay(500); Serial.println("START DECODER"); + 
-  +void setup() {   
 +  //Serial.begin(115200); delay(500); Serial.println("START DECODER");   
 + 
 +  // --- Пины энкодера ---
   pinMode(ENC_A, INPUT_PULLUP);   pinMode(ENC_A, INPUT_PULLUP);
   pinMode(ENC_B, INPUT_PULLUP);   pinMode(ENC_B, INPUT_PULLUP);
   pinMode(ENC_BTN, INPUT_PULLUP);   pinMode(ENC_BTN, INPUT_PULLUP);
  
 +  // --- Пины реле ---
   for (int i = 0; i < RELAY_COUNT; i++) {   for (int i = 0; i < RELAY_COUNT; i++) {
     pinMode(RELAYS[i], OUTPUT);     pinMode(RELAYS[i], OUTPUT);
Строка 386: Строка 706:
  
   disableAllRelays();   disableAllRelays();
 +
 +  // --- LCD ---
   lcd.begin();   lcd.begin();
   lcd.backlight();   lcd.backlight();
 +
 +  // если есть сохранённый — подхватим
 +  effectiveIP = ip; 
 +  loadIPFromEEPROM(effectiveIP); 
 +
 +  // Регистрируем кастомный символ CAT‑точки
 +  lcd.createChar(0, catDot);
 +
 +  // Splash screen
   splashScreen();   splashScreen();
  
-  Ethernet.begin(mac, ip);+  // --- Ethernet --- 
 +  Ethernet.begin(mac, effectiveIP);
   Udp.begin(localPort);   Udp.begin(localPort);
  
 +  // Первичное отображение IP (потом будет перерисовано updateTopLine)
   lcd.clear();   lcd.clear();
   lcd.setCursor(0,0);   lcd.setCursor(0,0);
   lcd.print("IP:");   lcd.print("IP:");
-  lcd.print(ip);+  lcd.print(effectiveIP);
   lcd.setCursor(0,1);   lcd.setCursor(0,1);
   lcd.print("READY");   lcd.print("READY");
  
 +  // --- Начальные значения логики ---
   currentBand = -1;   currentBand = -1;
   catActive = false;   catActive = false;
Строка 405: Строка 739:
   lastFreq = 0;     lastFreq = 0;  
   lastPacketTime = millis();   lastPacketTime = millis();
 +
   disableAllRelays();   disableAllRelays();
 +
 +  // Обновляем дисплей по новой логике
   forceDisplayUpdate = true;     forceDisplayUpdate = true;  
   updateLCDIfNeeded();   updateLCDIfNeeded();
 +
 +  // Инициализация энкодера (важно!)
   lastA = digitalRead(ENC_A);   lastA = digitalRead(ENC_A);
 } }
 +
  
 void loop() {   void loop() {  
 +  // === Всегда читаем UDP ===
   readUDP();   readUDP();
 +
 +  // === Обработка энкодера и кнопки ===
   handleEncoder();   handleEncoder();
   handleButton();   handleButton();
 +
 +  // === Проверка таймаута CAT ===
   checkCatTimeout();   checkCatTimeout();
  
 +  // === Периодическое обновление дисплея ===
   static unsigned long lastDisplayUpdate = 0;   static unsigned long lastDisplayUpdate = 0;
-  if (millis() - lastDisplayUpdate > 1000) {+  if (!ipEditMode && millis() - lastDisplayUpdate > 1000) {
     lastDisplayUpdate = millis();     lastDisplayUpdate = millis();
     updateLCDIfNeeded();     updateLCDIfNeeded();
-  }+  }   
 +  delay(10); 
 +
 + 
 + 
 + 
 + 
 + 
 + 
 + 
  
-  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("WAIT CAT DATA "); 
-    } 
-  } 
  
-  delay(10);  
-} 
 </code> </code>
banddecoder_code.1768593399.txt.gz · Последнее изменение: eu8t