Декодер Морзе

Stardust

✩✩✩✩✩✩✩
18 Ноя 2022
1
0
Проект декодера кода Морзе. Сигнал подаю с сайта (https://calculla.com/morse) 1kHz 5 WPM через детектор и усилитель. Импульсы на входе МК четкие. Сама схема состоит из детектора (который выделяет импульсы с сигнала с компа)-> arduino uno -> и lcd 1602A по шине I2C.
4.jpg
Скетч:
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 символы начинали выводиться во вторую строчку, а через некоторое время они очищались с экрана, чтобы строчки не забивались?
 

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
240
42
Как правильно написать условие, чтобы при заполнении символами первой строчки lcd символы начинали выводиться во вторую строчку,
Считаете длину первой строки, как только индекс переваливает за длину - выводите на вторую строку.
через некоторое время они очищались с экрана, чтобы строчки не забивались?
Проверяете длину всех строк и время очистки (через millis()), если строка заполнилась и время пришло - очищаете экран.