Логично.
Тем более,что я просто пошутил, и код в целом не смотрел)
Ради интереса, скормил ИИ последний “настоящий морзе” от BABOS ![]()
С задачей поправить ошибки и загнать массив символов в Progmem.
И вот что мне выдали:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
// ============== НАСТРОЙКИ ==============
const uint64_t pipe = 0xE8E8F0F0E1LL;
const int LCD_ADDR = 0x27;
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
// Пины
const int PIN_BUZZER = 2;
const int PIN_BUTTON_SYMBOL = 3;
const int PIN_BUTTON_MODE = 4;
const int PIN_LED_TRANSMIT = 5;
const int PIN_LED_RECEIVE = 6;
const int PIN_CE = 9;
const int PIN_CSN = 10;
// Константы времени
const unsigned long DASH_MIN_TIME = 150;
const unsigned long SYMBOL_TIMEOUT = 600;
const unsigned long SCREEN_TIMEOUT = 30000;
const unsigned long DEBOUNCE_DELAY = 50;
// ============== ТАБЛИЦА МОРЗЕ (PROGMEM) ==============
// Формат: "СИМВОЛ|КОД"
const char morseRaw[] PROGMEM =
"A|.- B|-... C|-.-. D|-.. E|. F|..-. G|--. H|.... I|.. J|.--- K|-.- L|.-.. M|-- "
"N|-. O|--- P|.--. Q|--.- R|.-. S|... T|- U|..- V|...- W|.-- X|-..- Y|-.-- Z|--.. "
"1|.---- 2|..--- 3|...-- 4|....- 5|..... 6|-.... 7|--... 8|---.. 9|----. 0|----- "
".|.-.-.- ,|--..-- ?|..--.. !|-.-.-- :|---... ;|-.-.-. =|-...- +|.-.-. -|-....- /|-..-. @|.--.-.";
// ============== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ==============
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS);
RF24 radio(PIN_CE, PIN_CSN);
bool transmitter = true;
bool screen = true;
bool buttonWasUp = true;
unsigned long buttonPressTime = 0;
unsigned long lastActivityTime = 0;
unsigned long lastSymbolTime = 0;
String currentMorse = "";
byte cursorX = 0, cursorY = 0;
byte idx;
// ============== ФУНКЦИИ ПОИСКА ==============
// Ищет символ по коду Морзе во флеш-памяти
char findCharByMorse(String code) {
char buffer[60];
strcpy_P(buffer, morseRaw);
char* token = strtok(buffer, " ");
while (token != NULL) {
String t = String(token);
int sep = t.indexOf('|');
if (t.substring(sep + 1) == code) return t[0];
token = strtok(NULL, " ");
}
return '?';
}
// Ищет индекс (для радио) или символ для дисплея
String getMorseByIndex(int idx) {
char buffer[60];
strcpy_P(buffer, morseRaw);
char* token = strtok(buffer, " ");
int count = 0;
while (token != NULL) {
if (count == idx) return String(token);
token = strtok(NULL, " ");
count++;
}
return "";
}
// ============== ЛОГИКА ДИСПЛЕЯ ==============
void displayOn() { lcd.display(); lcd.backlight(); screen = true; lastActivityTime = millis(); }
void displayOff() { lcd.noDisplay(); lcd.noBacklight(); screen = false; }
void addCharToDisplay(char c) {
displayOn();
lcd.setCursor(cursorX, cursorY);
lcd.print(c);
cursorX++;
if (cursorX >= LCD_COLS) { cursorX = 0; cursorY++; }
if (cursorY >= LCD_ROWS) { cursorY = 0; cursorX = 0; lcd.clear(); }
}
// ============== РАДИО ==============
void sendMorse(String code) {
char buffer[60];
strcpy_P(buffer, morseRaw);
char* token = strtok(buffer, " ");
byte idx = 0;
while (token != NULL) {
String t = String(token);
if (t.substring(t.indexOf('|') + 1) == code) {
radio.stopListening();
radio.write(&idx, sizeof(idx));
if (!transmitter) radio.startListening();
return;
}
token = strtok(NULL, " ");
idx++;
}
}
// ============== ОСНОВНЫЕ ЦИКЛЫ ==============
void processTX() {
bool btn = digitalRead(PIN_BUTTON_SYMBOL);
if (!btn) { // Нажата
if (buttonWasUp) { buttonPressTime = millis(); buttonWasUp = false; }
tone(PIN_BUZZER, 600);
lastSymbolTime = millis();
displayOn();
} else { // Отпущена
if (!buttonWasUp) {
noTone(PIN_BUZZER);
unsigned long duration = millis() - buttonPressTime;
currentMorse += (duration > DASH_MIN_TIME) ? "-" : ".";
buttonWasUp = true;
}
}
// Если долго не нажимали — парсим символ
if (currentMorse.length() > 0 && (millis() - lastSymbolTime > SYMBOL_TIMEOUT)) {
char found = findCharByMorse(currentMorse);
addCharToDisplay(found);
sendMorse(currentMorse);
currentMorse = "";
blinkLED(PIN_LED_TRANSMIT);
}
}
void processRX() {
if (radio.available()) {
// byte idx;
radio.read(&idx, sizeof(idx));
String res = getMorseByIndex(idx);
if (res != "") addCharToDisplay(res[0]);
blinkLED(PIN_LED_RECEIVE);
}
}
void blinkLED(int pin) {
digitalWrite(pin, HIGH); delay(50); digitalWrite(pin, LOW);
}
void setup() {
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_BUTTON_SYMBOL, INPUT_PULLUP);
pinMode(PIN_BUTTON_MODE, INPUT_PULLUP);
pinMode(PIN_LED_TRANSMIT, OUTPUT);
pinMode(PIN_LED_RECEIVE, OUTPUT);
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.print(F("Morse Radio v2"));
radio.begin();
radio.setPALevel(RF24_PA_LOW);
radio.openWritingPipe(pipe);
radio.openReadingPipe(1, pipe);
radio.startListening();
delay(1500);
lcd.clear();
}
void loop() {
// Переключение режима (TX/RX)
if (digitalRead(PIN_BUTTON_MODE) == LOW) {
transmitter = !transmitter;
lcd.clear();
lcd.print(transmitter ? F("MODE: TX") : F("MODE: RX"));
if (transmitter) radio.stopListening(); else radio.startListening();
delay(1000);
lcd.clear();
}
if (transmitter) processTX(); else processRX();
// Сон дисплея
if (screen && (millis() - lastActivityTime > SCREEN_TIMEOUT)) displayOff();
}
Результат компиляции просто поразил.
P.S. Насчёт “рабочести” код не проверял. Сегодня лениво что-то, но вероятно, попробую запустить. Когда-нибудь. ![]()
P.P.S. Только сейчас заметил, что ИИ почему-то выкинул из кода все Serial.print.
Пойду спрошу, что это он так. ![]()
вооо, а говорили не пригодится))) даешь отдельные теоретические ветви решения! главное не запутаться…
Закомментировал все, что касается вывода в порт. Работает частично, но, с ошибками. Постоянно передает ”@” и принимается тоже самое в паузах
Не работает. После вывода на экран приветственной надписи- зависает напрочь. Режимы работы не переключаются.
это в какой версии кода ?)))
char buffer[60]; // 60 байт - ЭТО СЛИШКОМ МАЛО!
strcpy_P(buffer, morseRaw); // morseRaw намного больше 60 символов
В processRX() переменная idx закомментирована, используется глобальная — это приводит к конфликтам.
если у него будет время может поправит)))
Резиновый?
Да, ладно! Печально!
Это уже я накосячил.. ![]()
Компилятор ругнул " warning: ‘idx’ may be used uninitialized in this function [-Wmaybe-uninitialized]
String res = getMorseByIndex(idx);"
Вот я и повёлся, запулил глобально не подумавши..
Гм.. А вот тут интересно.
Когда я кинул предъяву ИИ, насчёт того, куда он дел Serial.print, он выдал мне новый код, где buffer уже 128 !
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
// ============== НАСТРОЙКИ ==============
const uint64_t pipe = 0xE8E8F0F0E1LL;
const int LCD_ADDR = 0x27;
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
const int PIN_BUZZER = 2;
const int PIN_BUTTON_SYMBOL = 3;
const int PIN_BUTTON_MODE = 4;
const int PIN_LED_TRANSMIT = 5;
const int PIN_LED_RECEIVE = 6;
const int PIN_CE = 9;
const int PIN_CSN = 10;
const unsigned long DASH_MIN_TIME = 150;
const unsigned long SYMBOL_TIMEOUT = 600;
const unsigned long SCREEN_TIMEOUT = 30000;
// ============== ТАБЛИЦА МОРЗЕ В PROGMEM ==============
const char morseRaw[] PROGMEM =
"A|.- B|-... C|-.-. D|-.. E|. F|..-. G|--. H|.... I|.. J|.--- K|-.- L|.-.. M|-- "
"N|-. O|--- P|.--. Q|--.- R|.-. S|... T|- U|..- V|...- W|.-- X|-..- Y|-.-- Z|--.. "
"1|.---- 2|..--- 3|...-- 4|....- 5|..... 6|-.... 7|--... 8|---.. 9|----. 0|----- "
".|.-.-.- ,|--..-- ?|..--.. !|-.-.-- :|---... ;|-.-.-. =|-...- +|.-.-. -|-....- /|-..-. @|.--.-.";
// ============== ПЕРЕМЕННЫЕ ==============
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS);
RF24 radio(PIN_CE, PIN_CSN);
bool transmitter = true;
bool screen = true;
bool buttonWasUp = true;
unsigned long buttonPressTime = 0;
unsigned long lastActivityTime = 0;
unsigned long lastSymbolTime = 0;
String currentMorse = "";
byte cursorX = 0, cursorY = 0;
// ============== ФУНКЦИИ ПОИСКА ==============
char findCharByMorse(String code) {
char buffer[128]; // Временный буфер для парсинга части строки
strcpy_P(buffer, morseRaw);
char* token = strtok(buffer, " ");
while (token != NULL) {
String t = String(token);
int sep = t.indexOf('|');
if (t.substring(sep + 1) == code) return t[0];
token = strtok(NULL, " ");
}
return '?';
}
String getMorseByIndex(int idx) {
char buffer[128];
strcpy_P(buffer, morseRaw);
char* token = strtok(buffer, " ");
int count = 0;
while (token != NULL) {
if (count == idx) {
String t = String(token);
return t.substring(0, t.indexOf('|'));
}
token = strtok(NULL, " ");
count++;
}
return "?";
}
// ============== ЛОГИКА ==============
void addCharToDisplay(char c) {
displayOn();
lcd.setCursor(cursorX, cursorY);
lcd.print(c);
Serial.print(F("Вывод на LCD: ")); Serial.println(c);
cursorX++;
if (cursorX >= LCD_COLS) { cursorX = 0; cursorY++; }
if (cursorY >= LCD_ROWS) { cursorY = 0; cursorX = 0; lcd.clear(); }
}
void sendMorse(String code) {
char buffer[128];
strcpy_P(buffer, morseRaw);
char* token = strtok(buffer, " ");
byte idx = 0;
while (token != NULL) {
String t = String(token);
if (t.substring(t.indexOf('|') + 1) == code) {
radio.stopListening();
bool ok = radio.write(&idx, sizeof(idx));
Serial.print(F("Радио -> Отправка индекса ")); Serial.print(idx);
Serial.println(ok ? F(" [OK]") : F(" [ОШИБКА]"));
if (!transmitter) radio.startListening();
return;
}
token = strtok(NULL, " ");
idx++;
}
}
void displayOn() { lcd.display(); lcd.backlight(); screen = true; lastActivityTime = millis(); }
void displayOff() { lcd.noDisplay(); lcd.noBacklight(); screen = false; Serial.println(F("LCD: Спящий режим")); }
void setup() {
Serial.begin(9600);
while (!Serial); // Ждем открытия порта
Serial.println(F("--- Morse Radio Nano v3 (PROGMEM) ---"));
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_BUTTON_SYMBOL, INPUT_PULLUP);
pinMode(PIN_BUTTON_MODE, INPUT_PULLUP);
pinMode(PIN_LED_TRANSMIT, OUTPUT);
pinMode(PIN_LED_RECEIVE, OUTPUT);
lcd.init();
lcd.backlight();
lcd.print(F("Morse Radio v3"));
if (!radio.begin()) {
Serial.println(F("Ошибка: nRF24L01 не найден!"));
lcd.setCursor(0,1); lcd.print(F("RF ERROR!"));
}
radio.setPALevel(RF24_PA_LOW);
radio.openWritingPipe(pipe);
radio.openReadingPipe(1, pipe);
radio.startListening();
Serial.println(F("Система готова. Режим: RX (Прием)"));
transmitter = false; // Начинаем с приема для безопасности
delay(1500);
lcd.clear();
}
void loop() {
// Переключение режима
if (digitalRead(PIN_BUTTON_MODE) == LOW) {
transmitter = !transmitter;
lcd.clear();
Serial.print(F("Смена режима: "));
if (transmitter) {
radio.stopListening();
lcd.print(F("MODE: TX"));
Serial.println(F("ПЕРЕДАЧА"));
} else {
radio.startListening();
lcd.print(F("MODE: RX"));
Serial.println(F("ПРИЕМ"));
}
delay(500);
lcd.clear();
lastActivityTime = millis();
}
// Логика передачи
if (transmitter) {
bool btn = digitalRead(PIN_BUTTON_SYMBOL);
if (!btn) {
if (buttonWasUp) { buttonPressTime = millis(); buttonWasUp = false; }
tone(PIN_BUZZER, 650);
lastSymbolTime = millis();
} else {
if (!buttonWasUp) {
noTone(PIN_BUZZER);
unsigned long duration = millis() - buttonPressTime;
currentMorse += (duration > DASH_MIN_TIME) ? "-" : ".";
buttonWasUp = true;
Serial.print(F("Сигнал: ")); Serial.println(currentMorse);
}
}
if (currentMorse.length() > 0 && (millis() - lastSymbolTime > SYMBOL_TIMEOUT)) {
char found = findCharByMorse(currentMorse);
Serial.print(F("Символ распознан: ")); Serial.println(found);
addCharToDisplay(found);
sendMorse(currentMorse);
currentMorse = "";
digitalWrite(PIN_LED_TRANSMIT, HIGH); delay(50); digitalWrite(PIN_LED_TRANSMIT, LOW);
}
}
// Логика приема
else {
if (radio.available()) {
byte idx = 0;
radio.read(&idx, sizeof(idx));
String res = getMorseByIndex(idx);
Serial.print(F("Принято радио! Индекс: ")); Serial.print(idx);
Serial.print(F(" Символ: ")); Serial.println(res);
if (res != "?") addCharToDisplay(res[0]);
digitalWrite(PIN_LED_RECEIVE, HIGH); delay(50); digitalWrite(PIN_LED_RECEIVE, LOW);
}
}
if (screen && (millis() - lastActivityTime > SCREEN_TIMEOUT)) displayOff();
}
P.S. Вообщем, развлекайтесь дальше без меня, господа!
Мне надо сегодня к паяльнику. И так кучу времени потратил на развлекуху с ИИ.. ![]()
Эти ваши вайбкодинги до добра не доведут…
Впаивать или выпаивать? Или и то и другое?))
а если еще ругнуться вернет все символы ?)))
а то тут кажется их меньше…