/
morze2.ino
125 lines (110 loc) · 9.93 KB
/
morze2.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <Wire.h> // Библиотека связи Arduino с устройствами по шине I2C
#include <LiquidCrystal_I2C.h> // Библиотека работы с жидкокристаллическими символьными дисплеями по шине I2C
#include <LCD_1602_RUS.h> // Библиотека вывода русского алфавита на дисплей, не поддерживающий русские символы
LCD_1602_RUS lcd(0x27,16,2); // Адрес и тип жидкокристаллического дисплея: 2 строки по 16 символов
#define LIGHT 2 // Пин считывания сигнала с фоторезистора
#define LASER 3 // Пин управления лазерным излучателем
int lcdSymbol = 0; // Переменная для счетчика символов для дисплея
int waitTimer = 0; // Переменная для счетчика таймера ожидания лазерного сигнала
unsigned long signal, press, release; // Переменные для хранения длительности сигнала, времени приема лазерного сигнала и его исчезновения
String morze = ""; // Строка для записи морзянки
String message = ""; // Строка для записи принятого с компьютера сообщения
const char * dotsAndDashes[] = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", // Массив строк азбуки Морзе
"-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-",
"..-", "...-", ".--", "-..-", "-.--", "--..",
".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", "-----",
"......", ".-.-.-", "---...", "-.-.-.", ".----.", ".-..-.", "-....-", "..--.-", "..--..", "--..--", ".-.-.", "-...-" };
const char symbols[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.,:;`'-_?!+ "; // Массив алфавита, цифр и знаков, соответствующий массиву азбуки Морзе
void setup() {
Serial.begin(9600); // Инициализируем обмен данным с компьютером
Serial.setTimeout(100); // Время ожидания данных с компьютера, устанавливаем в 100 миллисекунд
lcd.init(); // Инициализация дисплея
lcd.backlight(); // Включение подсветки дисплея
lcd.clear(); // Очистка дисплея и памяти его контроллера
pinMode(LIGHT, INPUT_PULLUP); // Инициализация пина для чтения сигнала с фоторезистора
pinMode(LASER, OUTPUT); // Инициализируем пин управления лазерным излучателем
}
void loop() {
Start: // метка для оператора возврата
if (Serial.available()) { // Если связь с компьютером установлена
getMessage(); // то запускаем функцию getMessage()
}
if (digitalRead(LIGHT)) { // Если приняли лазерный сигнал (пин фоторезистора зафиксировал высокий уровень)
press = millis(); // то запоминаем время от начала цикла loop
while (digitalRead(LIGHT)) { // Пока сигнал пина фоторезистора высокий
signal = millis() - press; // Вычисляем длительность лазерного сигнала: время от начала цикла loop минус время, сохраненное до цикла while. Разницу сохраняем в переменную signal
}
if (signal > 100) {
morze += morzeCode(); // Если длительность сигнала больше 100 миллисекунд, запускаем функцию morzeCode()
signal = 0; // Обнуляем переменную signal для следующего цикла
}
lcd.setCursor(0,0); // Устанавливаем курсор дисплея на первую строку в первую символьную ячейку
lcd.print("Код: ");
lcd.print(morze); // Показываем принятый код Морзе
release = millis(); // Сохраняем время от начала цикла loop
while (!digitalRead(LIGHT)) {
if (Serial.read() != -1) { // Если с компьютера начали поступать данные
goto Start; // прерываем цикл и переходим к метке Start
}
waitTimer = millis() - release; // Вычисляем время без лазерного луча: время от исчезновения луча минус время, сохраненное до цикла while. Разницу сохраняем в переменную release
if (waitTimer >= 500 && morze.length() >= 1 && morze.length() <= 6) { // Если счетчик ожидания лазерного сигнала больше 0,5 секунды и длина строки morze больше или один символ и меньше или равен 6 символам
if (lcdSymbol < 16) { // Если значение переменной lcdSymbol меньше 16
lcd.setCursor(lcdSymbol,1); // то выставляем курсор на вторую строку в ячейку, соответствующую значению в переменной lcdSymbol
} else if (lcdSymbol == 16) { // Если же значение переменной равно 16, то есть строка закончилась,
lcd.setCursor(0,1); // то ставим курсор в начало строки
lcdSymbol = 0; // и обнуляем переменную lcdSymbol
}
morze2letter(); // Запускаем функцию morze2letter()
nullFirstRow(); // Запускаем функцию nullFirstRow()
morze = ""; // Опустошаем строку morze
}
}
}
}
void getMessage() { // Функция приема и обработки сообщения с компьютера
message = Serial.readString(); // Читаем сообщение и сохраняем в виде строки
Serial.println(message); // Показываем в "Мониторе порта" принятое сообщение
for (int i = 0; i < message.length(); i++) { // Определяем длину принятого сообщения и повторяем цикл в соответствии с определенной длиной
for (int j = 0; j < 55; j++) { // Итерируемся по количеству строк в массиве латинского алфавита
if (symbols[j] == message[i]) { // Если из массива алфавита совпадает с буквой из строкового массива сообщения
for (int ij = 0; ij < strlen(dotsAndDashes[j]); ij++) { // то запускаем итерацию по массиву "точек-тире"
if (dotsAndDashes[j][ij] == '.') { // Если первый символ из строки в массиве "точек-тире" точка
digitalWrite(LASER, HIGH); // Включаем лазер
delay(100); // Ждем 100 миллисекунд
digitalWrite(LASER, LOW); // Выключаем лазер
delay(100); // Ждем 100 миллисекунд
} else if (dotsAndDashes[j][ij] == '-') { // Если же первый символ из строки в массиве "точек-тире" тире
digitalWrite(LASER, HIGH); // Включаем лазер
delay(250); // Ждем 250 миллисекунд
digitalWrite(LASER, LOW); // Выключаем лазер
delay(100); // Ждем 100 миллисекунд
}
}
}
}
delay(800); // Ждем 800 миллисекунд, чтобы сработал таймер приема морзянки
}
}
String morzeCode() { // Функция определения "точка или тире". Возвращает строковый символ
if (signal < 300) {
return "."; // Если длительность лазерного сигнала меньше 300 миллисекунд, то дописываем в morze точку
} else if (signal > 300) {
return "-"; // Если же больше 300 миллисекунд, то дописываем в morze тире
}
}
void morze2letter() { // Функция расшифровки морзянки
int i = 0; // Переменная для счетчика цикла
while (i < 55) { // Цикл выполняется, пока i меньше 55 (число элементов в массиве алфавита)
if (morze == dotsAndDashes[i]) { // Если полученный код соответствует одной из строк в массиве алфавита Морзе
lcd.print(symbols[i]); // Выводим на дисплей букву русского алфавита
lcd.print(" "); // Следующую ячейку заполняем пробелом
lcdSymbol++; // Увеличиваем счетчик lcdSymbol на единицу
break; // Прерываем цикл
}
i++; // Увеличиваем переменную цикла на единицу
}
}
void nullFirstRow() { // Функция обнуления первой строки дисплея
lcd.setCursor(0,0);
lcd.print("Код: ");
}