Проект декодера кода Морзе. Сигнал подаю с сайта (https://calculla.com/morse) 1kHz 5 WPM через детектор и усилитель. Импульсы на входе МК четкие. Сама схема состоит из детектора (который выделяет импульсы с сигнала с компа)-> arduino uno -> и lcd 1602A по шине I2C.
Скетч:
Как правильно написать условие, чтобы при заполнении символами первой строчки lcd символы начинали выводиться во вторую строчку, а через некоторое время они очищались с экрана, чтобы строчки не забивались?
Скетч:
C++:
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // lcd c интерфейсом I2C
LiquidCrystal_I2C lcd(0x27,16,2); // параметры lcd
const uint8_t pinSensor = A3; // входной сигнал
const uint16_t varlevel = 300; // уровень сигнала
const uint32_t tmrSignal = 250; // длительности сигнала (если сигнал короче - точка, если сигнал длиннее - тире)
const uint32_t tmrPause = 900; // длительность паузы (если пауза между сигналами дольше, значит начинается новое слово)
uint32_t tmrSeparator; // определения граничного времени для сигналов и пауз
uint8_t varLetter; // переменная для хранения принятых точек и тире одного символа (бит 0 - точка, бит 1 - тире)
uint8_t lenLetter; // переменная для хранения количества точек и тире в принятом символе
bool flgSignal; // флаг указывающий на то что была принята хотя бы одна точка или тире
bool flgLetter; // флаг указывающий на то что был принят символ
char chrMorze[] = {'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', '.', ';', ',', ':', '?', '!', '-', ' ', '\n', '\r'};
uint8_t lenMorze[] = { 2, 4, 4, 3, 1, 4, 3, 4, 2, 4, 3, 4, 2, 2, 3, 4, 4, 3, 3, 1, 3, 4, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5};
uint8_t varMorze[] = {0x1, 0x8, 0xA, 0x4, 0x0, 0x2, 0x6, 0x0, 0x0, 0x7, 0x5, 0x4, 0x3, 0x2, 0x7, 0x6, 0xD, 0x2, 0x0, 0x1, 0x1, 0x1, 0x3, 0x9, 0xB, 0xC, 0xF, 0x7, 0x3, 0x1, 0x0, 0x10, 0x18, 0x1C, 0x1E, 0x1F, 0x0, 0x2A, 0x15, 0x38, 0x0C, 0x33, 0x21, 0x11, 0x15, 0x0A};
// Массивы: chrMorze - содержит символы, lenMorze - количество точек и тире в символе, varMorze - комбинация точек и тире (бит 0 - точка, бит 1 - тире)
void setup(){ //
lcd.init(); // инициация работы LCD дисплея
lcd.backlight(); // подсветку дисплея
lcd.setCursor(0, 0); // установка курсора в позицию (0 столбец, 0 строка)
lcd.print(" Decoder Morze"); // вывод текста " Decoder Morze"
delay(2000); // делей 2 сек
lcd.clear(); // очистка экрана
lcd.setCursor(0, 0); // установка курсора в позицию (0 столбец, 0 строка)
flgLetter=varLetter=lenLetter=0; // сброс флагов и переменных относящихся к принятому символу
}
void loop(){
// если зафиксирован сигнал:
if(analogRead(pinSensor) > varlevel){ // если уровень считанный со входа pinSensor превышает значение varlevel
flgSignal=true; // установка флага указывающего на наличие сигнала
lenLetter++; // увеличение счетчика количества точек и тире в принятом символе
tmrSeparator = millis()+tmrSignal; // определение граничного времени сигнала (если сигнал пропадёт до этого времени - значит принята точка, иначе принято тире)
while(analogRead(pinSensor) > varlevel){delay(2);} // время ожидания пропадания сигнала
varLetter<<=1; varLetter|=tmrSeparator<millis(); // сдвиг всех битов переменной varLetter (она хранит принятые точки и тире символа) и записываем в последний бит этой переменной «0» или «1» (зависит от длительности сигнала)
// если зафиксирована пауза: //
}else{ // если уровень сигнала считанный со входа pinSensor меньше или равен значению varlevel (считается что это пауза)
tmrSeparator = millis()+tmrPause; // определение граничного времени паузы (если пауза пропадёт до этого времени - значит мы продолжаем принимать символ, иначе символ полностью принят)
while(analogRead(pinSensor) < varlevel && tmrSeparator>millis()){delay(2);} // ожидание пропадания паузы, но не дольше чем время указанное в tmrSeparator
if(tmrSeparator<millis()){flgLetter=flgSignal; flgSignal=false;} // если пауза длилась дольше чем указано в tmrSeparator, то устанавливаем флаг flgLetter, но только если установлен флаг flgSignal указывающий что ранее был принят хотя бы один сигнал
}
// если принят символ:
if(flgLetter){ // если установлен флаг flgLetter значит символ полностью принят, его нужно сравнить и вывести
for(uint8_t i=0; i<46; i++){ // считывание всех 46 символов массивов
if(varLetter==varMorze[i] && lenLetter==lenMorze[i]){ // если комбинация точек и тире в varLetter совпала с varMorze[i] и количество точек и тире совпало с lenMorze[i], то...
if(i==44 || i==45) {lcd.clear(); lcd.setCursor(0, 0);} // если найденный символ является символом начала '\n' или конца '\r' строки, то чистим экран и устанавливаем курсор в начало
else {lcd.print(chrMorze[i]);} // если найденный символ не является символом начала '\n' или конца '\r' строки, то просто его выводим на экран (позиция символа на экране смещается автоматически)
}} flgLetter=varLetter=lenLetter=0; // сброс флагов и переменных относящихся к принятому символу, так как символ уже выведен
}
}
Как правильно написать условие, чтобы при заполнении символами первой строчки lcd символы начинали выводиться во вторую строчку, а через некоторое время они очищались с экрана, чтобы строчки не забивались?