#include // библиотека для работы с дисплеем #include "Free_Fonts.h" // подключаемый файл #include // библиотека Arduino TFT_HX8357 tft = TFT_HX8357(); // вызов пользовательской библиотеки int echoPinA = 54; // назначение вывода echoA (3500 mV) int echoPinB = 55; // назначение вывода echoB (2500 mV) int echoPinC = 56; // назначение вывода echoC (1000 mV) int echoPinD = 57; // назначение вывода echoD (200 mV) int ctrl0Pin = 59; // назначение вывода ctrl0Pin 0 - воздух, 1 - вода int ctrl1Pin = 60; // назначение вывода ctrl1Pin 0 - A,C, 1 - B,D int ctrl2Pin = 61; // назначение вывода ctrl2Pin 0 - B,A, 1 - D,C int ctrl3Pin = 62; // назначение вывода ctrl3Pin 0 - AUTO, 1 - SEPAR int analogPin = 63; // назначение вывода analogPin Uпит int trigPin = 64; // назначение вывода trig CKL int v(v=85); // указание счётчика строк v (начальное значение 85) float m; // указание переменной с плавающей точкой m float mp; // указание переменной с плавающей точкой mp int mn; // указание предельного расстояния mn int mnp; // указание предельного расстояния mnp int vmn; // указание предельного расстояния vmn int vmnp; // указание предельного расстояния vmnp int dispm; // указание количества точек disp int disp; // указание количества точек disp int dispp; // указание количества точек disp float cm; // объявление переменной cm (расстояние в см) float cmp; // объявление переменной cmp (расстояние в см) uint16_t duration; // объявление переменной duration float voltage = 0.0; // объявление переменной voltage float analog = 0.0; // объявление переменной analog #define LOG_SIZE 20 // размер лога (штук) uint16_t us[LOG_SIZE]; // массив измерений. Для импульсов короче 65мс можно сделать uint16_t uint16_t durus[LOG_SIZE]; // массив измерений. Для импульсов короче 65мс можно сделать uint16_t uint32_t start; // Время старта uint32_t now; // Текущее машинное время в мкс uint32_t prevUs; // Предыдущее время изменения состояния пина int IN_PIN; // Данные текущего канала int count = 0; // Счётчик циклов измерения bool first, prevS, flag = 0; // Первое, предыдущее состояние пина, флаг не первого измерения bool flagn = 0; // Если 1, то пин в этом цикле прочитан bool airgnd; // 0 - пин на земле, 1 - висит в воздухе bool ctrl1; // 0 - A,C, 1 - B,D bool ctrl2; // 0 - B,A, 1 - D,C bool ctrl3; // 0 - AUTO, 1 - SEPAR int k = 0; // Указатель текущего канала для чтения void setup() { pinMode(trigPin, OUTPUT); // назначение вывода trig выходом pinMode(echoPinA, INPUT); // назначение вывода echoA входом pinMode(echoPinB, INPUT); // назначение вывода echoB входом pinMode(echoPinC, INPUT); // назначение вывода echoC входом pinMode(echoPinD, INPUT); // назначение вывода echoD входом pinMode(ctrl0Pin, INPUT_PULLUP); // назначение вывода ctrl0 входом pinMode(ctrl1Pin, INPUT_PULLUP); // назначение вывода ctrl1 входом pinMode(ctrl2Pin, INPUT_PULLUP); // назначение вывода ctrl2 входом pinMode(ctrl3Pin, INPUT_PULLUP); // назначение вывода ctrl3 входом pinMode(analogPin, INPUT); // назначение вывода analogPin входом analogReference(INTERNAL2V56); tft.begin(); // инициализациz TFT-экрана tft.setRotation(1); // альбомное расположение экрана tft.fillScreen(TFT_BLACK); // очистка экрана, цвет чёрный tft.setTextColor(TFT_YELLOW,TFT_BLACK); // жёлтый шрифт на чёрном фоне tft.setFreeFont(FSB24); // выбор фонта "Serif Bold 24pt" impuls(); // Выдача запускающего импульса trig (CKL), запись машинного времени старта в start } void loop() { // Чтение данных от приёмника // Выясняем, какой пин текущий и заносим его в IN_PIN ctrl3 = digitalRead(ctrl3Pin); // 0 - AUTO, 1 - SEPAR if (ctrl3 == 0 ) { // Если 0 - AUTO, читаем все пины if (flagn == 0 ) { // Если 0, идём читать пин, иначе - уходим if (k == 0) // Если k = 0, - PinD {IN_PIN = echoPinD; // Читаем PinD flagn = 1; // Устанавливаем flagn = 1. Пин прочитан k = 1; } // Устанавливаем следующий Pin else // Если k не 0, идём дальше if (k == 1) // Если k = 1, PinC {IN_PIN = echoPinC; // Читаем PinC flagn = 1; // Устанавливаем flagn = 1. Пин прочитан k = 2; } // Устанавливаем следующий Pin else // Если k не 1, идём дальше if (k == 2) // Если k = 2, PinB {IN_PIN = echoPinB; // Читаем PinB flagn = 1; // Устанавливаем flagn = 1. Пин прочитан k = 3; } // Устанавливаем следующий Pin else // Если k не 2, идём дальше if (k == 3) // Если k = 3, PinA {IN_PIN = echoPinA; // Читаем PinA flagn = 1; // Устанавливаем flagn = 1. Пин прочитан k = 0;} // Устанавливаем PinD } // flagn =1. Пин уже прочитан, уходим }else { // Значит, ctrl3 = 1 - SEPAR, идём читать ctrl1 = digitalRead(ctrl1Pin); // Читаем ctrl1Pin ctrl2 = digitalRead(ctrl2Pin); // Читаем ctrl2Pin if (ctrl1 == 0 && ctrl2 == 0) // Если ctrl1, ctrl2 = 0,0 {IN_PIN = echoPinA; } // Читаем PinA else // Если нет, идём дальше if (ctrl1 == 1 && ctrl2 == 0) // Если ctrl1, ctrl2 = 1,0 {IN_PIN = echoPinB; } // Читаем PinB else // Если нет, идём дальше if (ctrl1 == 0 && ctrl2 == 1) // Если ctrl1, ctrl2 = 0,1 {IN_PIN = echoPinC; } // Читаем PinC else // Если нет, идём дальше if (ctrl1 == 1 && ctrl2 == 1) // Если ctrl1, ctrl2 = 1,1 {IN_PIN = echoPinD; } // Читаем PinD } // С пинами разобрались. Идём дальше // читаем время и текущий пин из IN_PIN now = micros(); // Читаем текущее машинное время bool s = digitalRead(IN_PIN); // Читаем текущее состояние пина if (prevS != s) { // Состояние пина изменилось? prevS = s; // Если изменилось, запомнили текущее состояние if (!flag) { // Опрос флага (первое срабатывание?) flag = 1; // Если первое срабатывание, устанавливаем флаг в 1 us[count] = now - start; // Время до первого импульса durus[count] = us[count]; // Заносим время до первого импульса в durus[count] duration = durus[count]; // duration = время до первого импульса prevUs = now; // Заносим время первого импульса в prevUs count++; // + 1 в счётчик циклов } else // Если не первое срабатывание { // Обрабатываем следующие импульсы us[count] = now - prevUs; // длительность импульса durus[count] = (durus[count - 1] + us[count]); // durus[count] = текущее время всех импульов duration = durus[count]; // duration = последнее время всех импульов prevUs = now; // Запомнили машинное время count++; // + 1 в счётчик циклов if (count >= LOG_SIZE) logOut(); // Если буфер переполнен - вывод лога } // Если состояние пина не изменилось, идём дальше } // Завершение void loop() if (now - start > 60000) // Если время измерения истекло { // Устанавливаем начальные значения if (flag == 0) { // flag durus[0] = 0; // durus[0] durus[1] = 0; // durus[1] count = 1;} // count logOut(); // Переходим на вывод лога } // Если время измерения не истекло if (flag && now - prevUs > 60000) logOut(); // таймаут 0,1 секунда (сигнал пропал) - вывод лога } // Вывод лога void logOut() { analog = analogRead(analogPin); voltage = (analog*6.2) / 400; airgnd = digitalRead(ctrl0Pin); // Чтение переключателя воздух / вода if (airgnd == 0){ // Если 0, то воздух cm = duration / 58; // Вычисление расстояния до объекта в воздухе и запись его в регистр if (cm <= 100) {(mn = 1); (vmn = 18);} // если расстояние меньше или равно 100, записываем 1 в mn else if (cm > 100 && cm <= 200) {(mn = 2); (vmn = 37);} // если расстояние больше 100, но меньше или равно 200, записываем 2 в mn else if (cm > 200 && cm <= 400) {(mn = 4); (vmn = 74);} // если расстояние больше 200, но меньше или равно 400, записываем 4 в mn else if (cm > 400 && cm <= 800) {(mn = 8); (vmn = 147);} // если расстояние больше 400, но меньше или равно 800, записываем 8 в mn m=(float)cm/100.0; // Запись в регистр m расстояния, делённого на 100 (перевод в метры) } else { // Если не 0, то вода cm = duration / 13; // Вычисление расстояния до объекта в воде и запись его в регистр if (cm <= 500) {(mn = 5); (vmn = 22);} // если расстояние меньше или равно 500, записываем 5 в mn else if (cm > 500 && cm <= 1000) {(mn = 10); (vmn = 45);} // если расстояние больше 500, но меньше или равно 1000, записываем 10 в mn else if (cm > 1000 && cm <= 2000) {(mn = 20); (vmn = 89);} // если расстояние больше 1000, но меньше или равно 2000, записываем 20 в mn else if (cm > 2000 && cm <= 4000) {(mn = 40); (vmn = 223);} // если расстояние больше 2000, но меньше или равно 4000, записываем 40 в mn m=(float)cm/100.0; // запись в регистр m расстояния, делённого на 100 (перевод в метры) } // Вывод на дисплей tft.setTextColor(TFT_YELLOW,TFT_BLACK); // жёлтый шрифт на чёрном фоне tft.fillRect(0,0,82,60,TFT_BLACK); // запись на экран чёрного квадрата tft.setCursor(0,40); // установка курсора на указанные позиции {tft.println(m,1); } // вывод на экран содержимого регистра (m) tft.fillRect(0,260,82,60,TFT_BLACK); // запись на экран чёрного квадрата tft.setCursor(16,304); // установка курсора на указанные позиции {tft.print(mn); } // вывод на экран содержимого регистра (mn) tft.drawLine(0,160,84,160,TFT_YELLOW ); // вывод на экран средней линии tft.drawLine(84, 0, 84,320,TFT_YELLOW); // вывод на экран вертикальной линии) tft.fillRect(0,100,82,60,TFT_BLACK); // запись на экран чёрного квадрата tft.setCursor(0,140); // установка курсора на указанные позиции if (voltage >= 10.5){ tft.setTextColor(TFT_GREEN,TFT_BLACK); // зелёный шрифт на чёрном фоне tft.println(voltage,1); // вывод на экран содержимого регистра (mn) }else { tft.setTextColor(TFT_RED,TFT_BLACK); // красный шрифт на чёрном фоне tft.println(voltage,1);} // вывод на экран содержимого регистра (mn) for (int j = 0; j < count;) { if (j == 0){ disp = durus[j] / vmn; dispp = durus[j+1] / vmn; tft.drawLine(v,disp, v,0,TFT_LIGHTGREY); // вывод на экран графика содержимого регистра (disp)GREEN tft.drawLine(v,dispp, v,disp,TFT_MAGENTA); // вывод на экран графика содержимого регистра (disp)YELLOW j = j+2; } else { dispm = durus[j-1] / vmn; disp = durus[j] / vmn; dispp = durus[j+1] / vmn; tft.drawLine(v,disp, v,dispm,TFT_BLACK); // вывод на экран графика содержимого регистра (disp) if (IN_PIN == echoPinA ) {tft.drawLine(v,dispp, v,disp,TFT_RED); } else if (IN_PIN == echoPinB ) {tft.drawLine(v,dispp, v,disp,TFT_YELLOW); } else if (IN_PIN == echoPinC ) {tft.drawLine(v,dispp, v,disp,TFT_GREEN); } else if (IN_PIN == echoPinD ) {tft.drawLine(v,dispp, v,disp,TFT_BLUE); } j = j+2; } } v = v + 1; // переход графика на следующую позицию if (v==460){ (v = 85); tft.fillScreen(TFT_BLACK); // очистка экрана, цвет чёрный tft.setTextColor(TFT_YELLOW,TFT_BLACK); // жёлтый шрифт на чёрном фоне tft.setFreeFont(FSB24); // выбор фонта "Serif Bold 24pt" } impuls(); // Выдача запускающего импульса trig } void impuls() { // Выдача запускающего импульса trig // Установка начальных значений count = 0; // count flag = 0; // flag flagn = 0; // flagn first = prevS = digitalRead(IN_PIN); // Запомнили начальное состояние текущего пина digitalWrite(trigPin, LOW); // запись нуля в выходной вывод delayMicroseconds(2); // удержание нуля в течение 2 мксек digitalWrite(trigPin, HIGH); // запись единицы в выходной вывод delayMicroseconds(10); // удержание единицы в течение 10 мксек digitalWrite(trigPin, LOW); // запись нуля в выходной вывод start = micros(); }