КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Урок 40. Дешифратор азбуки Морзе с выводом на принтер, дисплей, последовательный порт

В этом уроке мы создадим дешифратор азбуки Морзе. Датчик звука преобразует звуковой сигнал в электрический и отправит его в Arduino. Arduino дешифрует принятые данные и отправит их, либо в монитор последовательного порта, либо на символьный дисплей LCD1602 I2C, либо в термопринтер UART. В Arduino нужно загрузить один из трёх скетчей, в зависимости от собранного устройства.

Нам понадобится:

В зависимости от собираемой схемы понадобится одно из устройств вывода информации и библиотека:

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE. Более подробно о работе с LCD дисплеем и термопринтером можно ознакомиться на страницах: WiKi - работа с символьными ЖК дисплеями и Wiki - работа с термопринтерами.

Видео:


Схемы подключения:

Схема подключения зависит от используемого устройства вывода данных.

Вывод данных в LCD дисплей:

Декодер азбуки Морзе на Arduino UNO с выводом данных в LCD дисплей по шине I2C

Трема датчик звука подключается в аналоговому выводу A3 (номер хранится в константе pinSensor - его можно изменить). LCD дисплей подключается к аппаратной шине I2C.

Вывод данных в термопринтер:

Декодер азбуки Морзе на Arduino UNO с выводом данных в термопринтер

Трема датчик звука подключается в аналоговому выводу A3 (номер хранится в константе pinSensor - его можно изменить). Термопринтер подключается по программной шине UART с назначенными в скетче выводами TX и RX. Номера выводов указываются при объявлении объекта mySerial(RX, TX) библиотеки SoftwareSerial, которая входит в стандартный набор Arduino IDE. В скетче RX объявлен как 5 вывод Arduino (он подключается к зелёному TX выводу принтера), а TX объявлен как 6 вывод Arduino (он подключается к синему RX выводу принтера). Жёлтый вывод (DTR) принтера не используется. Термопринтер запитывается от отдельного источника питания от 5 до 9 В постоянного тока, при этом красный провод подключается к + питания, а черный к - и к выводу GND Arduino.

Вывод данных в монитор последовательного порта:

Дешифратор азбуки Морзе на Arduino с выводом данных в монитор последовательного порта

Трема датчик звука подключается в аналоговому выводу A3 (номер хранится в константе pinSensor - его можно изменить). Дополнительные устройства не подключаются.

Алгоритм работы:

Часть скетча отвечающая за дешифрование сигнала одинакова для каждого устройства:

  • В начале создаются три массива:
    • chrMorze - содержит символы;
    • lenMorze - содержит количество точек или тире для символа;
    • varMorze - содержит комбинацию точек и тире для символа (точка = 0, тире = 1);
    Пример: возьмем второй элемент каждого массива - из массива chrMorze понятно что это символ «В», из массива lenMorze понятно что он состоит из 4 точек или тире, а из массива varMorze понятно, что комбинация равна значению 0x8 = 0b00001000. Берем последние 4 бита - 1000, точка = 0, тире = 1, значит в азбуке Морзе это « – • • • ».
    Пример: возьмем седьмой элемент каждого массива - из массива chrMorze понятно что это символ «G», из массива lenMorze понятно что он состоит из 3 точек или тире, а из массива varMorze понятно, что комбинация равна значению 0x6 = 0b00000110. Берем последние 3 бита - 110, точка = 0, тире = 1, значит в азбуке Морзе это « – – • ».
  • Так же создаются константы:
    • pinSensor - хранит номер вывода к которому подключён датчик звука;
    • varVolume - хранит уровень громкости на который требуется реагировать. Чем ниже уровень, тем чувствительнее датчик звука;
    • tmrSignal - хранит время в миллисекундах для определения точек и тире (если сигнал был длиннее этого времени - значит это тире, а если короче - значит это точка);
    • tmrPause - хранит время в миллисекундах для определения окончания приёма символа (если пауза между сигналами была длиннее этого времени - значит передача символа закончена, а если короче - значит символ еще принимается).
  • Декодирование осуществляется в коде loop и состоит из 3 частей: фиксация звука, фиксация паузы, вывод символа.
  • Если в первой части зафиксирован звук, то устанавливаем флаг наличия принятого сигнала flgSignal, увеличиваем счетчик точек/тире lenLetter, сохраняем время его фиксациии и входим в цикл while пока звук не исчезнет. После исчезновения звука определяем его длительность вычитая текущее время из ранее сохранённого.
  • Если во второй части зафиксирована пауза, то сохраняем время её фиксации и входим в цикл while пока пауза не исчезнет или не пройдёт время tmrPause означающее об окончании приёма символа. После выхода из цикла проверяется причина выхода из него (закончена пауза или истекло время). Если закончена пауза, то опять начинает выполняться первая часть декодирования, иначе устанавливается флаг flgLetter разрешающий переход в третью часть декодирования.
  • Третья часть часть декодирования заключается в определении принятого символа (по трём массивам: chrMorze, lenMorze, varMorze) и выводе этого символа в устройство вывода.

Код программ:

Код программы зависит от используемого устройства вывода данных.

Вывод данных в LCD дисплей:
#include <Wire.h>                     //  Подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>        //  Подключаем библиотеку для работы с LCD дисплеем по шине I2C
LiquidCrystal_I2C lcd(0x27,16,2);     //  Объявляем  объект библиотеки LiquidCrystal_I2C, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
const uint8_t   pinSensor = A3;       //  Определяем константу с номером вывода к которому подключён датчик звука
const uint16_t  varVolume = 800;      //  Определяем константу с уровнем громкости сигнала      (принимаются только те сигналы, громкость которых выше указанного уровня)
const uint32_t  tmrSignal = 300;      //  Определяем константу с указанием длительности сигнала (если сигнал короче - точка, если сигнал длиннее - тире)
const uint32_t  tmrPause  = 500;      //  Определяем константу с указанием длительности паузы   (если пауза между сигналами дольше, значит начинается новое слово)
      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 дисплея
    lcd.setCursor(0, 0);                                                              // Устанавливаем курсор в позицию (0 столбец, 0 строка)
    lcd.print("Detector Morze");                                                      // Выводим текст "Detector Morze"
    delay(2000);                                                                      // Ждём 2 секунды
    lcd.clear();                                                                      // Чистим экран
    lcd.setCursor(0, 0);                                                              // Устанавливаем курсор в позицию (0 столбец, 0 строка)
    flgLetter=varLetter=lenLetter=0;                                                  // Сбрасываем флаги и переменные относящиеся к принятому символу
}                                                                                     //
                                                                                      //
void loop(){                                                                          //
//  Если зафиксирован звук:                                                           //
    if(analogRead(pinSensor) > varVolume){                                            // Если уровень звука считанный со входа pinSensor превышает значение varVolume
        flgSignal=true;                                                               // Устанавливаем флаг указывающий на наличие сигнала
        lenLetter++;                                                                  // Увеличиваем счетчик количества точек и тире в принятом символе
        tmrSeparator = millis()+tmrSignal;                                            // Определяем граничное время сигнала (если сигнал пропадёт до этого времени - значит принята точка, иначе принято тире)
        while(analogRead(pinSensor) > varVolume){delay(10);}                          // Ждём пока не пропадёт сигнал
        varLetter<<=1; varLetter|=tmrSeparator<millis();                              // Сдвигаем все биты переменной varLetter (она хранит принятые точки и тире символа) и записываем в последний бит этой переменной «0» или «1» (зависит от длительности сигнала)
//  Если зафиксирована пауза:                                                         //
    }else{                                                                            // Если уровень звука считанный со входа pinSensor меньше или равен значению varVolume (считаем что это пауза)
        tmrSeparator = millis()+tmrPause;                                             // Определяем граничное время паузы (если пауза пропадёт до этого времени - значит мы продолжаем принимать символ, иначе символ полностью принят)
        while(analogRead(pinSensor) < varVolume && tmrSeparator>millis()){delay(10);} // Ждём пока не исчезнет пауза, но не дольше чем время указанное в 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;                                          // Сбрасываем флаги и переменные относящиеся к принятому символу, так как мы его уже вывели
    }                                                                                 //
}                                                                                     //
Вывод данных в термопринтер:
#include <SoftwareSerial.h>           //  Подключаем библиотеку для работы по программной шине UART
#include <Adafruit_Thermal.h>         //  Подключаем библиотеку для работы с принтером
SoftwareSerial  mySerial(5, 6);       //  Объявляем объект библиотеки SoftwareSerial, указывая задействованные выводы Arduino (RX=5-зелёный, TX=6-синий)
Adafruit_Thermal printer(&mySerial);  //  Объявляем объект библиотеки Adafruit_Thermal, указывая ссылку на созданный ранее объект библиотеки SoftwareSerial
const uint8_t   pinSensor = A3;       //  Определяем константу с номером вывода к которому подключён датчик звука
const uint16_t  varVolume = 800;      //  Определяем константу с уровнем громкости сигнала      (принимаются только те сигналы, громкость которых выше указанного уровня)
const uint32_t  tmrSignal = 300;      //  Определяем константу с указанием длительности сигнала (если сигнал короче - точка, если сигнал длиннее - тире)
const uint32_t  tmrPause  = 500;      //  Определяем константу с указанием длительности паузы   (если пауза между сигналами дольше, значит начинается новое слово)
      uint32_t  tmrSeparator;         //  Объявляем переменную для определения граничного времени для сигналов и пауз
      uint8_t   varLetter;            //  Объявляем переменную для хранения принятых точек и тире одного символа (бит 0 - точка, бит 1 - тире)
      uint8_t   lenLetter;            //  Объявляем переменную для хранения количества точек и тире в принятом символе
      bool      flgSignal;            //  Объявляем флаг указывающий на то что была принята хотя бы одна точка или тире
      bool      flgLetter;            //  Объявляем флаг указывающий на то что был принят символ
      char*     RUS(char*);           //  Объявляем функцию перевода русских символов из кодировки UTF-8 в кодировку CP866
      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(){                                                                         //
    mySerial.begin(9600);                                                             // Инициируем передачу данных по программной шине UART на скорости 9600 бот
    printer.begin();                                                                  // Инициируем работу с принтером
    printer.justify('C');                                                             // Устанавливаем выравнивание по центру
    printer.setSize('M');                                                             // Устанавливаем средний размер шрифта
    printer.setCodePage(CODEPAGE_CP866);                                              // Устанавливаем кодовую таблицу CP866 с поддержкой русского языка
    printer.println("--------------------------------");                              // Выводим текст "--------------------------------"
    printer.println(RUS("Дешифратор азбуки Морзе"));                                  // Выводим текст "Дешифратор азбуки Морзе" через функцию RUS
    printer.setSize('S');                                                             // Устанавливаем маленький размер шрифта
    printer.println("iarduino.ru");                                                   // Выводим текст "iarduino.ru"
    printer.setSize('M');                                                             // Устанавливаем средний размер шрифта
    printer.println("--------------------------------");                              // Выводим текст "--------------------------------"
    printer.feed(2);                                                                  // Прокручиваем ленту на две строки
    printer.setSize('L');                                                             // Устанавливаем большой размер шрифта
    flgLetter=varLetter=lenLetter=0;                                                  // Сбрасываем флаги и переменные относящиеся к принятому символу
}                                                                                     //
                                                                                      //
void loop(){                                                                          //
//  Если зафиксирован звук:                                                           //
    if(analogRead(pinSensor) > varVolume){                                            // Если уровень звука считанный со входа pinSensor превышает значение varVolume
        flgSignal=true;                                                               // Устанавливаем флаг указывающий на наличие сигнала
        lenLetter++;                                                                  // Увеличиваем счетчик количества точек и тире в принятом символе
        tmrSeparator = millis()+tmrSignal;                                            // Определяем граничное время сигнала (если сигнал пропадёт до этого времени - значит принята точка, иначе принято тире)
        while(analogRead(pinSensor) > varVolume){delay(10);}                          // Ждём пока не пропадёт сигнал
        varLetter<<=1; varLetter|=tmrSeparator<millis();                              // Сдвигаем все биты переменной varLetter (она хранит принятые точки и тире символа) и записываем в последний бит этой переменной «0» или «1» (зависит от длительности сигнала)
//  Если зафиксирована пауза:                                                         //
    }else{                                                                            // Если уровень звука считанный со входа pinSensor меньше или равен значению varVolume (считаем что это пауза)
        tmrSeparator = millis()+tmrPause;                                             // Определяем граничное время паузы (если пауза пропадёт до этого времени - значит мы продолжаем принимать символ, иначе символ полностью принят)
        while(analogRead(pinSensor) < varVolume && tmrSeparator>millis()){delay(10);} // Ждём пока не исчезнет пауза, но не дольше чем время указанное в 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){printer.feed(2);}                                        // Если найденный символ является символом начала '\n' или конца '\r' строки, то прокручиваем ленту на две строки
            else            {printer.println(chrMorze[i]);}                           // Если найденный символ не является символом начала '\n' или конца '\r' строки, то просто его выводим на экран (позиция символа на экране смещается автоматически)
        }}  flgLetter=varLetter=lenLetter=0;                                          // Сбрасываем флаги и переменные относящиеся к принятому символу, так как мы его уже вывели
    }                                                                                 //
}                                                                                     //
                                                                                      //
// Функция перевода русских символов строки str из кодировки UTF-8 в кодировку CP866:
char* RUS(char* str){                                                                                                                      // Определяем функцию которая преобразует код русских символов из кодировки UTF-8 в кодировку CP866
    uint8_t i=0, j=0;                                                                                                                      // Определяем переменные: i - счетчик входящих символов, j - счетчик исходящих символов
    while(str[i]){                                                                                                                         // Проходим по всем символам строки str, пока не встретим символ конца строки (код 0)
        if(uint8_t(str[i]) == 0xD0 && uint8_t(str[i+1]) >= 0x90 && uint8_t(str[i+1]) <= 0xBF ){str[j] = (uint8_t) str[i+1]-0x10; i++;}else // Символы «А-Я а-п» (код UTF-8: D090-D0AF D0B0-D0BF) сохраняем в кодировке CP866: код 80-9F A0-AF (символ занимал 2 байта, а стал занимать 1 байт)
        if(uint8_t(str[i]) == 0xD1 && uint8_t(str[i+1]) >= 0x80 && uint8_t(str[i+1]) <= 0x8F ){str[j] = (uint8_t) str[i+1]+0x60; i++;}else // Символы «р-я»     (код UTF-8: D180-D18F)           сохраняем в кодировке CP866: код E0-EF       (символ занимал 2 байта, а стал занимать 1 байт)
        if(uint8_t(str[i]) == 0xD0 && uint8_t(str[i+1]) == 0x81                              ){str[j] = 0xF0;                    i++;}else // Символ «Ё»        (код UTF-8: D081)                сохраняем в кодировке CP866: код F0          (символ занимал 2 байта, а стал занимать 1 байт)
        if(uint8_t(str[i]) == 0xD1 && uint8_t(str[i+1]) == 0x91                              ){str[j] = 0xF1;                    i++;}else // Символ «ё»        (код UTF-8: D191)                сохраняем в кодировке CP866: код F1          (символ занимал 2 байта, а стал занимать 1 байт)
                                                                                              {str[j] = (uint8_t) str[i];}  j++; i++;      // Остальные символы оставляем как есть, без преобразования, но их место в строке могло сдвинуться, если до них были встречены русские символы
    }   while(j<i){str[j]=0; j++;} return str;                                                                                             // Так как место занимаемое символами в строке могло уменьшиться, заполняем оставщиеся байты символами конца строки (код 0)
}
Вывод данных в монитор последовательного порта:
const uint8_t   pinSensor = A3;       //  Определяем константу с номером вывода к которому подключён датчик звука
const uint16_t  varVolume = 800;      //  Определяем константу с уровнем громкости сигнала      (принимаются только те сигналы, громкость которых выше указанного уровня)
const uint32_t  tmrSignal = 300;      //  Определяем константу с указанием длительности сигнала (если сигнал короче - точка, если сигнал длиннее - тире)
const uint32_t  tmrPause  = 500;      //  Определяем константу с указанием длительности паузы   (если пауза между сигналами дольше, значит начинается новое слово)
      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(){                                                                         //
    flgLetter=varLetter=lenLetter=0;                                                  // Сбрасываем флаги и переменные относящиеся к принятому символу
    Serial.begin(9600);                                                               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек
    Serial.println("Детектор азбуки Морзе");                                          // Выводим текст "Детектор азбуки Морзе"
    Serial.println("=====================");                                          // Выводим текст "====================="
}                                                                                     //
                                                                                      //
void loop(){                                                                          //
//  Если зафиксирован звук:                                                           //
    if(analogRead(pinSensor) > varVolume){                                            // Если уровень звука считанный со входа pinSensor превышает значение varVolume
        flgSignal=true;                                                               // Устанавливаем флаг указывающий на наличие сигнала
        lenLetter++;                                                                  // Увеличиваем счетчик количества точек и тире в принятом символе
        tmrSeparator = millis()+tmrSignal;                                            // Определяем граничное время сигнала (если сигнал пропадёт до этого времени - значит принята точка, иначе принято тире)
        while(analogRead(pinSensor) > varVolume){delay(10);}                          // Ждём пока не пропадёт сигнал
        varLetter<<=1; varLetter|=tmrSeparator<millis();                              // Сдвигаем все биты переменной varLetter (она хранит принятые точки и тире символа) и записываем в последний бит этой переменной «0» или «1» (зависит от длительности сигнала)
//  Если зафиксирована пауза:                                                         //
    }else{                                                                            // Если уровень звука считанный со входа pinSensor меньше или равен значению varVolume (считаем что это пауза)
        tmrSeparator = millis()+tmrPause;                                             // Определяем граничное время паузы (если пауза пропадёт до этого времени - значит мы продолжаем принимать символ, иначе символ полностью принят)
        while(analogRead(pinSensor) < varVolume && tmrSeparator>millis()){delay(10);} // Ждём пока не исчезнет пауза, но не дольше чем время указанное в 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], то...
            Serial.print(chrMorze[i]);                                                // Выводим символ из chrMorze[i] в монитор последовательного порта
        }}  flgLetter=varLetter=lenLetter=0;                                          // Сбрасываем флаги и переменные относящиеся к принятому символу, так как мы его уже вывели
    }                                                                                 //
}                                                                                     //

Ссылки:




Обсуждение

Гарантии и возврат Используя сайт Вы соглашаетесь с условями