По-другому. Например, битовые маски хранить.
Для меня- это что-то из фантастики))
А для меня это
что-то из психиатрии.
Вот массив, символ(1 байт) и его Морзе код, тоже 1 байт
const TMorze MorzeArray[] PROGMEM = {
{ 'A',0b101 },
{ 'B',0b11000 },
{ 'C',0b11010 },
{ 'D',0b1100 },
{ 'E',0b10 },
и т.д.
Самая левая единица в Морзе-коде - флаг того, что дальше будут точки-тире, 1-тире, 0-точка.
Я пересмотрел кучу проектов. Это подходит для моих задач. В написании кода я -0. Пишу об этом сотый раз. Может Ваше сообщение меня и не касается и адресовано автору кода, но про быдлокод я слышу уже не первый раз. Но, код работает.
Тогда не трогай, пусь работает, тока сюда не выкладывай, код вызывает идиосинкразию и кроффь из глаз. КГ/АМ, как говорится.
надеюсь не ко мне.
Пока буду рисовать корпус устройства, а код, может кто-то и добьет по моим хотелкам. Если нет, то что получится, то и получится)
Дык, это ж “специалист в предметной области” посоветовал. И долго потом правильность такого кода отстаивал, объясняя, кто тут “экстремист”, а кто - “д’Артаньян” ![]()
Аналогично, только ограничитель справа. И для алфавита и цифр позиционная таблица.
это не настоящая азбука морзе))) я вот че узнал…
#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_GND = 8;
const int PIN_CE = 9;
const int PIN_CSN = 10;
// Временные константы (в миллисекундах)
const unsigned long DASH_MIN_TIME = 150;
const unsigned long SYMBOL_TIMEOUT = 500;
const unsigned long SCREEN_TIMEOUT = 60000;
const unsigned long DEBOUNCE_DELAY = 20;
const unsigned long CYCLE_CHECK_INTERVAL = 10;
// Специальные команды
enum SpecialCommands {
CMD_UNKNOWN = 40,
CMD_SPACE = 41,
CMD_COUNT = 42
};
// ========================================
// ============== СТРУКТУРА ДАННЫХ ==============
struct MorseSymbol {
const char* morse;
const char* symbol;
const char* description;
bool isSpecial;
};
const MorseSymbol morseTable[] = {
// Буквы A-Z (0-25)
{".-", "A", "A", false},
{"-...", "B", "B", false},
{"-.-.", "C", "C", false},
{"-..", "D", "D", false},
{".", "E", "E", false},
{"..-.", "F", "F", false},
{"--.", "G", "G", false},
{"....", "H", "H", false},
{"..", "I", "I", false},
{".---", "J", "J", false},
{"-.-", "K", "K", false},
{".-..", "L", "L", false},
{"--", "M", "M", false},
{"-.", "N", "N", false},
{"---", "O", "O", false},
{".--.", "P", "P", false},
{"--.-", "Q", "Q", false},
{".-.", "R", "R", false},
{"...", "S", "S", false},
{"-", "T", "T", false},
{"..-", "U", "U", false},
{"...-", "V", "V", false},
{".--", "W", "W", false},
{"-..-", "X", "X", false},
{"-.--", "Y", "Y", false},
{"--..", "Z", "Z", false},
// Цифры 0-9 (26-35)
{".----", "1", "1", false},
{"..---", "2", "2", false},
{"...--", "3", "3", false},
{"....-", "4", "4", false},
{".....", "5", "5", false},
{"-....", "6", "6", false},
{"--...", "7", "7", false},
{"---..", "8", "8", false},
{"----.", "9", "9", false},
{"-----", "0", "0", false},
// Знаки препинания (36-39)
{".-.-.-", ".", "точка", false},
{"--..--", ",", "запятая", false},
{"..--..", "?", "вопрос", false},
{"-.-.--", "!", "восклицание", false},
// Специальные символы (40-41)
{"......", "�", "неизвестно", true},
{".......", " ", "пробел", true}
};
const int MORSE_COUNT = sizeof(morseTable) / sizeof(morseTable[0]);
// ===============================================
// ============== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ==============
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS);
RF24 radio(PIN_CE, PIN_CSN);
// Состояние
bool transmitter = true;
bool screen = true;
bool buttonWasUp = false;
bool symbol_end = false;
bool wrong_symbol = false;
// Таймеры
unsigned long buttonPressTime = 0;
unsigned long lastActivityTime = 0;
unsigned long cycleCounter = 0;
unsigned long lastCycleCheck = 0;
// Данные
String currentSymbol = "";
byte cursorX = 0;
byte cursorY = 0;
// ===============================================
// ============== ФУНКЦИИ ПОИСКА ==============
int findMorseCode(String morse) {
for (int i = 0; i < MORSE_COUNT; i++) {
if (morse == morseTable[i].morse) {
return i;
}
}
return -1;
}
const char* getSymbolByIndex(int index) {
if (index >= 0 && index < MORSE_COUNT) {
return morseTable[index].symbol;
}
return "?";
}
// =============================================
// ============== УПРАВЛЕНИЕ ДИСПЛЕЕМ ==============
void displayOn() {
lcd.display();
lcd.backlight();
screen = true;
lastActivityTime = millis();
}
void displayOff() {
lcd.noDisplay();
lcd.noBacklight();
screen = false;
}
void updateDisplay() {
if (!screen) return;
// Проверка на выход за границы
if (cursorX >= LCD_COLS) {
cursorX = 0;
cursorY++;
if (cursorY >= LCD_ROWS) {
cursorY = 0;
lcd.clear();
}
}
}
// =================================================
// ============== СВЕТОДИОДНАЯ ИНДИКАЦИЯ ==============
void updateModeIndicators() {
if (transmitter) {
digitalWrite(PIN_LED_TRANSMIT, HIGH);
digitalWrite(PIN_LED_RECEIVE, LOW);
} else {
digitalWrite(PIN_LED_TRANSMIT, LOW);
digitalWrite(PIN_LED_RECEIVE, HIGH);
}
}
void blinkLED(int pin, int count = 1, int duration = 100) {
for (int i = 0; i < count; i++) {
digitalWrite(pin, HIGH);
delay(duration);
digitalWrite(pin, LOW);
if (i < count - 1) delay(duration);
}
}
// ====================================================
// ============== РЕЖИМ ПЕРЕДАТЧИКА ==============
void processTransmitter() {
bool buttonState = digitalRead(PIN_BUTTON_SYMBOL);
// Кнопка нажата
if (!buttonState) {
if (buttonWasUp) {
buttonPressTime = millis();
buttonWasUp = false;
}
// Воспроизводим звук
tone(PIN_BUZZER, 550);
lastActivityTime = millis();
}
// Кнопка отпущена
else {
if (!buttonWasUp && buttonPressTime > 0) {
noTone(PIN_BUZZER);
unsigned long pressDuration = millis() - buttonPressTime;
// Определяем символ (точка или тире)
if (pressDuration >= DASH_MIN_TIME) {
currentSymbol += "-";
} else {
currentSymbol += ".";
}
buttonWasUp = true;
cycleCounter = 0;
symbol_end = false;
}
// Проверка на завершение символа
if (!symbol_end && currentSymbol.length() > 0) {
cycleCounter += CYCLE_CHECK_INTERVAL;
if (cycleCounter >= SYMBOL_TIMEOUT) {
int index = findMorseCode(currentSymbol);
if (index >= 0) {
// Отправляем найденный символ
radio.write(&index, sizeof(index));
Serial.print("Отправлено: ");
Serial.println(morseTable[index].symbol);
// Визуальная обратная связь
blinkLED(PIN_LED_TRANSMIT, 1, 50);
symbol_end = true;
wrong_symbol = false;
} else {
// Символ не найден
wrong_symbol = true;
}
currentSymbol = "";
cycleCounter = 0;
}
}
// Обработка неизвестного символа
if (wrong_symbol && cycleCounter >= SYMBOL_TIMEOUT * 2) {
byte unknownCmd = CMD_UNKNOWN;
radio.write(&unknownCmd, sizeof(unknownCmd));
Serial.println("Отправлен неизвестный символ");
blinkLED(PIN_LED_TRANSMIT, 2, 100);
wrong_symbol = false;
cycleCounter = 0;
}
}
}
// ================================================
// ============== РЕЖИМ ПРИЁМНИКА ==============
void processReceiver() {
if (radio.available()) {
byte command;
radio.read(&command, sizeof(command));
displayOn();
if (command >= 0 && command < MORSE_COUNT) {
// Выводим символ на дисплей
lcd.setCursor(cursorX, cursorY);
lcd.print(morseTable[command].symbol);
Serial.print("Получено: ");
Serial.print(command);
Serial.print(" -> ");
Serial.println(morseTable[command].symbol);
// Обновляем позицию курсора
cursorX++;
updateDisplay();
// Специальная обработка для некоторых команд
if (morseTable[command].isSpecial) {
if (command == CMD_UNKNOWN) {
blinkLED(PIN_LED_RECEIVE, 2, 150);
} else if (command == CMD_SPACE) {
// Пробел уже вывелся, но можно добавить мигание
blinkLED(PIN_LED_RECEIVE, 1, 30);
}
} else {
blinkLED(PIN_LED_RECEIVE, 1, 50);
}
}
}
// Автовыключение дисплея
if (screen && (millis() - lastActivityTime > SCREEN_TIMEOUT)) {
displayOff();
}
}
// ==============================================
// ============== ОБРАБОТКА РЕЖИМА ==============
void handleModeSwitch() {
static bool lastModeButtonState = HIGH;
static unsigned long lastModeDebounceTime = 0;
bool modeButtonState = digitalRead(PIN_BUTTON_MODE);
if (modeButtonState == LOW && lastModeButtonState == HIGH &&
(millis() - lastModeDebounceTime) > DEBOUNCE_DELAY) {
lastModeDebounceTime = millis();
// Переключаем режим
transmitter = !transmitter;
// Настраиваем радио
if (transmitter) {
radio.stopListening();
displayOff();
} else {
radio.startListening();
displayOn();
cursorX = 0;
cursorY = 0;
lcd.clear();
}
updateModeIndicators();
Serial.print("Режим: ");
Serial.println(transmitter ? "ПЕРЕДАТЧИК" : "ПРИЁМНИК");
// Мигаем светодиодами для подтверждения
blinkLED(PIN_LED_TRANSMIT, 2, 100);
blinkLED(PIN_LED_RECEIVE, 2, 100);
}
lastModeButtonState = modeButtonState;
}
// ==============================================
// ============== SETUP ==============
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);
pinMode(PIN_GND, OUTPUT);
digitalWrite(PIN_GND, LOW);
// Инициализация последовательного порта
Serial.begin(9600);
Serial.println("Запуск системы...");
// Инициализация дисплея
lcd.init();
lcd.backlight();
lcd.print("Morse Radio");
lcd.setCursor(0, 1);
lcd.print("v2.0");
// Инициализация радио
radio.begin();
radio.enableAckPayload();
radio.openWritingPipe(pipe);
radio.openReadingPipe(1, pipe);
// Начальное состояние
displayOn();
updateModeIndicators();
buttonWasUp = true;
// Вывод таблицы Морзе в Serial для отладки
Serial.println("--- Таблица Морзе загружена ---");
Serial.print("Всего символов: ");
Serial.println(MORSE_COUNT);
delay(2000);
lcd.clear();
}
// ===================================
// ============== LOOP ==============
void loop() {
// Обновляем счётчик цикла для проверок таймаута
if (millis() - lastCycleCheck > CYCLE_CHECK_INTERVAL) {
lastCycleCheck = millis();
if (transmitter && !buttonWasUp) {
cycleCounter += CYCLE_CHECK_INTERVAL;
}
}
// Обработка переключения режима
handleModeSwitch();
// Основная логика в зависимости от режима
if (transmitter) {
processTransmitter();
} else {
processReceiver();
}
// Небольшая задержка для стабильности
delay(5);
}
// ===================================
// ============== ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ ==============
// Функция для отладки - отправить тестовый символ
void sendTestSymbol(const char* morse) {
int index = findMorseCode(morse);
if (index >= 0) {
Serial.print("Тест: ");
Serial.print(morse);
Serial.print(" -> ");
Serial.println(morseTable[index].symbol);
} else {
Serial.println("Тест: символ не найден");
}
}
// Функция для очистки дисплея
void clearDisplay() {
lcd.clear();
cursorX = 0;
cursorY = 0;
}
// ====================================================
а вот настоящая! но это не точно…
#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_GND = 8;
const int PIN_CE = 9;
const int PIN_CSN = 10;
// Временные константы (в миллисекундах)
const unsigned long DASH_MIN_TIME = 150; // Минимальное время для тире
const unsigned long SYMBOL_TIMEOUT = 500; // Таймаут между символами
const unsigned long SCREEN_TIMEOUT = 60000; // Таймаут подсветки
const unsigned long DEBOUNCE_DELAY = 20; // Антидребезг
const unsigned long CYCLE_CHECK_INTERVAL = 10; // Интервал проверки цикла
const unsigned long SPACE_PAUSE = 2000; // Пауза для пробела (между словами)
const unsigned long LETTER_PAUSE = 500; // Пауза между буквами
// Специальные команды
enum SpecialCommands {
CMD_UNKNOWN = 52, // Индекс для ошибки (последний элемент)
CMD_COUNT = 53 // Общее количество команд
};
// ========================================
// ============== СТРУКТУРА ДАННЫХ ==============
struct MorseSymbol {
const char* morse; // код Морзе
const char* symbol; // отображаемый символ
const char* description; // описание
};
// ПРАВИЛЬНАЯ таблица символов Морзе (без дубликатов)
const MorseSymbol morseTable[] = {
// Буквы A-Z (0-25)
{".-", "A", "буква А"},
{"-...", "B", "буква B"},
{"-.-.", "C", "буква C"},
{"-..", "D", "буква D"},
{".", "E", "буква E"},
{"..-.", "F", "буква F"},
{"--.", "G", "буква G"},
{"....", "H", "буква H"},
{"..", "I", "буква I"},
{".---", "J", "буква J"},
{"-.-", "K", "буква K"},
{".-..", "L", "буква L"},
{"--", "M", "буква M"},
{"-.", "N", "буква N"},
{"---", "O", "буква O"},
{".--.", "P", "буква P"},
{"--.-", "Q", "буква Q"},
{".-.", "R", "буква R"},
{"...", "S", "буква S"},
{"-", "T", "буква T"},
{"..-", "U", "буква U"},
{"...-", "V", "буква V"},
{".--", "W", "буква W"},
{"-..-", "X", "буква X"},
{"-.--", "Y", "буква Y"},
{"--..", "Z", "буква Z"},
// Цифры (26-35)
{".----", "1", "цифра 1"},
{"..---", "2", "цифра 2"},
{"...--", "3", "цифра 3"},
{"....-", "4", "цифра 4"},
{".....", "5", "цифра 5"},
{"-....", "6", "цифра 6"},
{"--...", "7", "цифра 7"},
{"---..", "8", "цифра 8"},
{"----.", "9", "цифра 9"},
{"-----", "0", "цифра 0"},
// Знаки препинания (36-51)
{".-.-.-", ".", "точка"},
{"--..--", ",", "запятая"},
{"..--..", "?", "вопросительный знак"},
{"-.-.--", "!", "восклицательный знак"},
{"---...", ":", "двоеточие"},
{"-.-.-.", ";", "точка с запятой"},
{"-...-", "=", "равно"},
{".-...", "&", "амперсанд"},
{"..--.-", "_", "подчеркивание"},
{".-..-.", "\"", "кавычки"},
{"-.--.", "(", "открывающая скобка"},
{"-.--.-", ")", "закрывающая скобка"},
{".-.-.", "+", "плюс"},
{"-....-", "-", "дефис"},
{"/", "/", "косая черта"},
{"..--.", "@", "собака"},
// Специальные (52)
{"........", "#", "ошибка/неизвестный символ"}
};
// Пробел обрабатывается отдельно через паузу, а не через код Морзе!
const int MORSE_COUNT = sizeof(morseTable) / sizeof(morseTable[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;
bool symbol_end = false;
bool wrong_symbol = false;
bool waitingForSpace = false;
unsigned long spacePauseStart = 0;
// Таймеры
unsigned long buttonPressTime = 0;
unsigned long lastActivityTime = 0;
unsigned long cycleCounter = 0;
unsigned long lastCycleCheck = 0;
unsigned long lastSymbolTime = 0;
// Данные
String currentSymbol = "";
byte cursorX = 0;
byte cursorY = 0;
// Статистика
int symbolsSent = 0;
int symbolsReceived = 0;
// ===============================================
// ============== ФУНКЦИИ ПОИСКА ==============
int findMorseCode(String morse) {
for (int i = 0; i < MORSE_COUNT; i++) {
if (morse == morseTable[i].morse) {
return i;
}
}
return -1;
}
const char* getSymbolByIndex(int index) {
if (index >= 0 && index < MORSE_COUNT) {
return morseTable[index].symbol;
}
return "?";
}
void printMorseTable() {
Serial.println("=== ТАБЛИЦА МОРЗЕ ===");
for (int i = 0; i < MORSE_COUNT; i++) {
Serial.print(i);
Serial.print(": ");
Serial.print(morseTable[i].morse);
Serial.print(" -> ");
Serial.print(morseTable[i].symbol);
Serial.print(" (");
Serial.print(morseTable[i].description);
Serial.println(")");
}
Serial.print("Всего символов: ");
Serial.println(MORSE_COUNT);
}
// =============================================
// ============== УПРАВЛЕНИЕ ДИСПЛЕЕМ ==============
void displayOn() {
lcd.display();
lcd.backlight();
screen = true;
lastActivityTime = millis();
}
void displayOff() {
lcd.noDisplay();
lcd.noBacklight();
screen = false;
}
void updateCursor() {
if (cursorX >= LCD_COLS) {
cursorX = 0;
cursorY++;
if (cursorY >= LCD_ROWS) {
cursorY = 0;
lcd.clear();
}
}
}
void addCharToDisplay(char c) {
lcd.setCursor(cursorX, cursorY);
lcd.print(c);
cursorX++;
updateCursor();
}
void addStringToDisplay(const char* str) {
lcd.setCursor(cursorX, cursorY);
lcd.print(str);
cursorX += strlen(str);
updateCursor();
}
// =================================================
// ============== СВЕТОДИОДНАЯ ИНДИКАЦИЯ ==============
void updateModeIndicators() {
if (transmitter) {
digitalWrite(PIN_LED_TRANSMIT, HIGH);
digitalWrite(PIN_LED_RECEIVE, LOW);
} else {
digitalWrite(PIN_LED_TRANSMIT, LOW);
digitalWrite(PIN_LED_RECEIVE, HIGH);
}
}
void blinkLED(int pin, int count = 1, int duration = 100) {
for (int i = 0; i < count; i++) {
digitalWrite(pin, HIGH);
delay(duration);
digitalWrite(pin, LOW);
if (i < count - 1) delay(duration);
}
}
void indicateSuccess() {
blinkLED(PIN_LED_TRANSMIT, 1, 50);
}
void indicateError() {
blinkLED(PIN_LED_TRANSMIT, 3, 100);
}
void indicateReceive() {
blinkLED(PIN_LED_RECEIVE, 1, 50);
}
// ====================================================
// ============== РАДИО ФУНКЦИИ ==============
bool sendCommand(byte cmd) {
bool result = radio.write(&cmd, sizeof(cmd));
if (result) {
symbolsSent++;
Serial.print("Отправлено [");
Serial.print(symbolsSent);
Serial.print("]: ");
Serial.print(cmd);
Serial.print(" -> ");
Serial.println(getSymbolByIndex(cmd));
}
return result;
}
bool receiveCommand(byte &cmd) {
if (radio.available()) {
radio.read(&cmd, sizeof(cmd));
symbolsReceived++;
return true;
}
return false;
}
// ============================================
// ============== РЕЖИМ ПЕРЕДАТЧИКА ==============
void processTransmitter() {
bool buttonState = digitalRead(PIN_BUTTON_SYMBOL);
// Обработка пробела (длинное нажатие)
if (waitingForSpace) {
if (millis() - spacePauseStart > SPACE_PAUSE) {
// Отправляем пробел как специальную команду
// В реальной азбуке Морзе пробел - это пауза, но для простоты
// мы можем отправить специальный код
byte spaceCmd = CMD_UNKNOWN - 1; // Используем предпоследний индекс для пробела
sendCommand(spaceCmd);
waitingForSpace = false;
indicateSuccess();
}
return;
}
// Кнопка нажата
if (!buttonState) {
if (buttonWasUp) {
buttonPressTime = millis();
buttonWasUp = false;
noTone(PIN_BUZZER); // Сначала выключаем, потом включим
}
// Воспроизводим звук
tone(PIN_BUZZER, 550);
lastActivityTime = millis();
lastSymbolTime = millis();
}
// Кнопка отпущена
else {
if (!buttonWasUp && buttonPressTime > 0) {
noTone(PIN_BUZZER);
unsigned long pressDuration = millis() - buttonPressTime;
// Определяем символ (точка или тире)
if (pressDuration >= DASH_MIN_TIME) {
currentSymbol += "-";
Serial.println("Добавлено тире");
} else {
currentSymbol += ".";
Serial.println("Добавлена точка");
}
buttonWasUp = true;
cycleCounter = 0;
symbol_end = false;
}
// Проверка на завершение символа
if (!symbol_end && currentSymbol.length() > 0) {
if (millis() - lastSymbolTime > SYMBOL_TIMEOUT) {
int index = findMorseCode(currentSymbol);
if (index >= 0) {
// Отправляем найденный символ
if (sendCommand(index)) {
// Добавляем символ на локальный дисплей
addStringToDisplay(morseTable[index].symbol);
symbol_end = true;
wrong_symbol = false;
indicateSuccess();
}
} else {
// Символ не найден
Serial.print("Неизвестный код: ");
Serial.println(currentSymbol);
wrong_symbol = true;
}
currentSymbol = "";
lastSymbolTime = millis();
}
}
// Обработка неизвестного символа
if (wrong_symbol && millis() - lastSymbolTime > SYMBOL_TIMEOUT * 2) {
byte unknownCmd = CMD_UNKNOWN;
if (sendCommand(unknownCmd)) {
addStringToDisplay("?");
Serial.println("Отправлен неизвестный символ");
indicateError();
}
wrong_symbol = false;
lastSymbolTime = millis();
}
}
// Проверка на пробел (длинная пауза)
if (buttonWasUp && !waitingForSpace && currentSymbol.length() == 0) {
if (millis() - lastSymbolTime > SPACE_PAUSE && lastSymbolTime > 0) {
waitingForSpace = true;
spacePauseStart = millis();
Serial.println("Пауза для пробела...");
}
}
}
// ================================================
// ============== РЕЖИМ ПРИЁМНИКА ==============
void processReceiver() {
byte command;
if (receiveCommand(command)) {
displayOn();
if (command >= 0 && command < MORSE_COUNT) {
// Обычный символ
addStringToDisplay(morseTable[command].symbol);
Serial.print("Получено [");
Serial.print(symbolsReceived);
Serial.print("]: ");
Serial.print(command);
Serial.print(" -> ");
Serial.print(morseTable[command].symbol);
Serial.print(" (");
Serial.print(morseTable[command].description);
Serial.println(")");
indicateReceive();
} else if (command == CMD_UNKNOWN) {
// Неизвестный символ
addStringToDisplay("?");
Serial.println("Получен неизвестный символ");
blinkLED(PIN_LED_RECEIVE, 2, 150);
} else if (command == CMD_UNKNOWN - 1) {
// Пробел
addStringToDisplay(" ");
Serial.println("Получен пробел");
blinkLED(PIN_LED_RECEIVE, 1, 30);
}
lastActivityTime = millis();
}
// Автовыключение дисплея
if (screen && (millis() - lastActivityTime > SCREEN_TIMEOUT)) {
displayOff();
Serial.println("Дисплей выключен");
}
}
// ==============================================
// ============== ОБРАБОТКА РЕЖИМА ==============
void handleModeSwitch() {
static bool lastModeButtonState = HIGH;
static unsigned long lastModeDebounceTime = 0;
bool modeButtonState = digitalRead(PIN_BUTTON_MODE);
if (modeButtonState == LOW && lastModeButtonState == HIGH &&
(millis() - lastModeDebounceTime) > DEBOUNCE_DELAY) {
lastModeDebounceTime = millis();
// Переключаем режим
transmitter = !transmitter;
// Сбрасываем состояние
currentSymbol = "";
buttonWasUp = true;
waitingForSpace = false;
lastSymbolTime = millis();
// Настраиваем радио
if (transmitter) {
radio.stopListening();
displayOff();
Serial.println("РЕЖИМ: ПЕРЕДАТЧИК");
} else {
radio.startListening();
displayOn();
cursorX = 0;
cursorY = 0;
lcd.clear();
lcd.print("RECEIVING...");
Serial.println("РЕЖИМ: ПРИЁМНИК");
}
updateModeIndicators();
// Мигаем светодиодами для подтверждения
blinkLED(PIN_LED_TRANSMIT, 2, 100);
blinkLED(PIN_LED_RECEIVE, 2, 100);
}
lastModeButtonState = modeButtonState;
}
// ==============================================
// ============== СТАТИСТИКА ==============
void printStats() {
Serial.println("=== СТАТИСТИКА ===");
Serial.print("Отправлено символов: ");
Serial.println(symbolsSent);
Serial.print("Получено символов: ");
Serial.println(symbolsReceived);
Serial.print("Режим: ");
Serial.println(transmitter ? "Передатчик" : "Приёмник");
Serial.println("=================");
}
// =======================================
// ============== SETUP ==============
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);
pinMode(PIN_GND, OUTPUT);
digitalWrite(PIN_GND, LOW);
// Инициализация последовательного порта
Serial.begin(9600);
Serial.println("=================================");
Serial.println(" МОРЗЕ РАДИО v2.0");
Serial.println("=================================");
// Инициализация дисплея
lcd.init();
lcd.backlight();
lcd.print("Morse Radio");
lcd.setCursor(0, 1);
lcd.print("v2.0");
// Инициализация радио
radio.begin();
radio.enableAckPayload();
radio.openWritingPipe(pipe);
radio.openReadingPipe(1, pipe);
// Начальное состояние
displayOn();
updateModeIndicators();
// Вывод таблицы Морзе
printMorseTable();
Serial.println("Система готова к работе!");
Serial.println("Кнопка 3 - ввод Морзе");
Serial.println("Кнопка 4 - смена режима");
Serial.println("=================================");
delay(2000);
lcd.clear();
}
// ===================================
// ============== LOOP ==============
void loop() {
// Обработка переключения режима
handleModeSwitch();
// Основная логика в зависимости от режима
if (transmitter) {
processTransmitter();
} else {
processReceiver();
}
// Вывод статистики каждые 10 секунд (для отладки)
static unsigned long lastStatsTime = 0;
if (millis() - lastStatsTime > 10000) {
lastStatsTime = millis();
printStats();
}
// Небольшая задержка для стабильности
delay(5);
}
// ===================================
Скетч использует 12926 байт (42%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 2663 байт (130%) динамической памяти, оставляя -615 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти; прочитайте https://support.arduino.cc/hc/en-us/articles/360013825179
раздел данных превышает доступное пространство на плате
Compilation error: раздел данных превышает доступное пространство на плате
А Вы, простите, чего ожидали от кодов “специалистов в предметной области”, типа таких?
Я Вам тут уже цитировал:
«Тролли же с удовольствием дают исходники, радостно наблюдая как стремительно фалломорфируют просящие (да и кто обещал рабочие исходники?)»
ой все, значит не судьба))) надо собирать вникать, и делать))) а я быстро, может кто за основу возьмет…
Нет тот случай! Никто за основу ничего не взьмёт! Будьте любезны – готовый код в подарочной упаковке! А то, ишь, взяли моду – “за основу”. Это что ж, белому человеку после таких “помощников” ещё и самому допиливать? Совсем, блин, берега попутали ![]()
Удивительно, правда?
ну обленился я немного, не проверил,))) и все делаю как правило на esp32, и вот там можно развернуться…
а за основу можно взять все символы!))) зато как понятно теперь?! можно сказать из 0 и 1 сделано…
вот и надо было им так на памяти экономить… эээх
Пусть ИИ теперь под УНО адаптирует вариант скетча.
В PROGMEM “закатайте” и делов - то)))
а если ии все поломает ? особенно с PROGMEM…
вот если автор сам обратится к нему, и будет понимать что он делает…
тогда можно наверное, а то добавишь и неизвестно где искать проблему потом…)))
Как сказал бы мой покойный сосед - А если нет?