/* Для WeMos, связанной с Исполнительным Устройством. Приём от Ардуино режима работы. Выдача байта режимов и сигнала инициализации CKL на излучатель. Обработка входного сигнала полностью и передача результатов на Ардуино. Доработка: Для возможности наблдения процессов на мониторе при наладке пришлось освободить выводы WeMos RX и TX. Сигнал, который приходил от усилителя на RX (3) перепаян на вывод D0 (16), который на TX (1), - на вывод D8 (15). */ #include // библиотека ESP8266WiFi #include // библиотека espnow #include // библиотека Arduino // МАС-АДРЕС платы, на которую отправляем данные. C8:C9:A3:6A:D9:64 uint8_t broadcastAddress[] = {0xC8, 0xC9, 0xA3, 0x6A, 0xD9, 0x64}; int trigPin = 0; // назначение вывода trig CKL int echoPinA = 16; // назначение вывода echoA L4 (3500 mV) int echoPinB = 15; // назначение вывода echoB L3 (2500 mV) int echoPinC = 5; // назначение вывода echoC L2 (1000 mV) int echoPinD = 4; // назначение вывода echoD L1 (200 mV) int analog1Pin = A0; // назначение вывода analog1Pin Uпит излучателя #define MOSI_PIN 13 // назначение вывода MOSI_PIN #define MISO_PIN 12 // назначение вывода MISO_PIN #define SCK_PIN 14 // назначение вывода SCK_PIN // #define SS_PIN 15 // назначение вывода SS_PIN int IN_PIN; // Пин входа текущего канала float analog1 = 0.0; // объявление переменной analog1 uint32_t start; // Время старта uint32_t now; // Текущее машинное время в мкс uint32_t prevUs; // Предыдущее время изменения состояния пина int count = 0; // Счётчик циклов измерения bool first,prevS,flag,flerr = 0; // Первое, предыдущее состояние пина, флаг не первого измерения, флаг ошибки bool flagrec = 0; // флаг приёма данных #define LOG_SIZE 12 // размер лога (LOG_SIZE ячеек) uint16_t us[LOG_SIZE]; // массив измерений. Для длительности отрезков между изменениями входа uint16_t errus[LOG_SIZE]; // массив измерений. Для текущего времени в момент изменения при ошибке // Вводим переменные для хранения отправляемых данных byte regkn2 = 0xFF; // регистр чтения кнопок управления каналами byte regm1 = 0xC6; // регистр хранения режима управления исполнительным устройством byte regm2 = 0x3C; // регистр храннения режима управления каналами byte reg_IN = 0x02; // регистр пина индикации byte regout = 0x3A; // регистр выдачи на исполнительное устройство float voltage1 = 0.0; // объявление переменной voltage1 uint16_t duration; // объявление переменной длительности сигнала от приёмника uint16_t durus[LOG_SIZE]; // массив измерений. Для текущего времени в момент изменения uint16_t arrey1[LOG_SIZE]; // массив измерений. Для передачи // Вводим переменные для хранения принимаемых данных byte incomingReg1; byte incomingReg2; byte incomingReg3; byte incomingReg4; byte incomingReg5; float incomingVoltbat; uint16_t incomingDursig; uint16_t incomingArrey1[LOG_SIZE]; // Переменная для хранения состояния отправки String success; // структуры для отправки // (Должна совпадать со структурой на плате-приемнике) typedef struct struct_message { byte reg1; byte reg2; byte reg3; byte reg4; byte reg5; float voltbat; // напряжение батареи uint16_t dursig; // длительность сигнала от приёмника uint16_t arrey1[LOG_SIZE]; // массив измерений. } struct_message; // Создаем переменную для хранения отправляемого сообщения struct_message ISPReadings; // То же, но для принимаемого сообщения struct_message incomingReadings; // Callback-функция для получения состояния отправки void OnDataSent(uint8_t * mac_addr, uint8_t sendStatus) { Serial.print("Last Packet Send Status: "); if (sendStatus == 0){ Serial.println("Delivery success"); } else{ Serial.println("Delivery fail"); } } // То же, для индикации состояния приема данных void OnDataRecv(uint8_t * mac, uint8_t * incomingData, uint8_t len) { memcpy(&incomingReadings, incomingData, sizeof(incomingReadings)); Serial.print("Bytes received: "); Serial.println(len); // приём данных regkn2 = incomingReadings.reg1; regm1 = incomingReadings.reg2; regm2 = incomingReadings.reg3; reg_IN = incomingReadings.reg4; regout = incomingReadings.reg5; voltage1 = incomingReadings.voltbat; duration = incomingReadings.dursig; for (int i = 0; i < LOG_SIZE; i++) { durus[i] = incomingReadings.arrey1[i]; } printIncomingReadings(); initial(); flagrec = 1; // устанавливаем в 1 флаг приёма данных } void printIncomingReadings(){ // Отображаем показания в мониторе порта Serial.println("INCOMING READINGS"); Serial.println(regkn2); Serial.println(regm1); Serial.println(regm2); Serial.println(reg_IN); Serial.println(regout); } void printSendingData(){ Serial.println("SENDING_DATA"); Serial.print("count: "); Serial.println(count); Serial.print("voltage1: "); Serial.println(voltage1); Serial.print("duration: "); Serial.println(duration); Serial.println("durus: "); for (int i = 0; i < LOG_SIZE; i++) { Serial.println(durus[i]); } } void setup() { pinMode(trigPin, OUTPUT); // назначение вывода trig выходом pinMode(echoPinA, INPUT); // назначение вывода echoA входом pinMode(echoPinB, INPUT); // назначение вывода echoB входом pinMode(echoPinC, INPUT); // назначение вывода echoC входом pinMode(echoPinD, INPUT); // назначение вывода echoD входом pinMode(analog1Pin, INPUT); // назначение вывода analog1Pin входом pinMode(MOSI_PIN, OUTPUT); // назначение вывода MOSI_PIN выходом pinMode(MISO_PIN, INPUT); // назначение вывода MISO_PIN входом pinMode(SCK_PIN, OUTPUT); // назначение вывода SCK_PIN выходом // pinMode(SS_PIN, OUTPUT); // назначение вывода SS_PIN выходом // Запускаем монитор порта Serial.begin(115200); // Выставляем режим работы Wi-Fi WiFi.mode(WIFI_STA); WiFi.disconnect(); // Инициализируем протокол ESP-NOW if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } // Указываем роль платы в сети esp_now_set_self_role(ESP_NOW_ROLE_COMBO); // Регистрируем callback-функцию для получения статуса отправки esp_now_register_send_cb(OnDataSent); // Регистрируем пиры esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_COMBO, 1, NULL, 0); // Регистрируем callback-функцию для получения статуса приема esp_now_register_recv_cb(OnDataRecv); } void loop() { if (flagrec == 1) { // если пришла посылка от WeMosArd // Чтение данных от приёмника // читаем время и текущий пин из IN_PIN now = micros(); // Читаем текущее машинное время bool s = digitalRead(IN_PIN); // Читаем текущее состояние пина if (prevS != s) { // Состояние пина изменилось? prevS = s; // Если изменилось, запомнили текущее состояние if (!flag) { // Опрос флага (первое срабатывание?) flag = 1; // Если первое срабатывание, устанавливаем флаг в 1 us[count] = now - start; // время до первого импульса if (flerr == 1) { // если установлен флаг ошибки errus[count] = us[count]; // заносим время до первого импульса в errus[count] }else { durus[count] = us[count]; // заносим время до первого импульса в durus[count] duration = durus[count]; } // duration = время до фронта первого импульса prevUs = now; // заносим текущее машинное время в prevUs count++; // + 1 в счётчик циклов } else // Если не первое срабатывание { // Обрабатываем следующие импульсы us[count] = now - prevUs; // длительность импульса if (flerr == 1) { // если установлен флаг ошибки errus[count] = (errus[count - 1] + us[count]); // errus[count] = текущее время всех импульсов if (count == 2) { // если это начало второго импульса durus[0] = errus[count]; // durus[count] = текущее время всех импульсов duration = errus[count]; // duration = время до фронта первого импульса flerr = 0; // сброс флага ошибки count = 0; }} // установка счётчика в 1 else { // если флага ошибки нет, считаем как обычно durus[count] = (durus[count - 1] + us[count]); // durus[count] = текущее время всех импульсов duration = durus[count - 1];} // duration = время до фронта последнего импульса prevUs = now; // Запомнили машинное время count++; // + 1 в счётчик циклов if (count >= LOG_SIZE) logOut(); // Если буфер переполнен - вывод лога } // Если состояние пина не изменилось, идём дальше } // Завершение чтения пина if (now - start > 60000) // Если время измерения истекло { // Устанавливаем начальные значения if (flag == 0) { // если импульсов не было duration = 0; // duration = время до фронта последнего импульса for (int i = 0; i < LOG_SIZE; i++) { durus[i] = 0; } count = 1;} // установка счётчика Для вывода на экран logOut(); // Переходим на вывод лога } // Если время измерения не истекло if (flag && now - prevUs > 60000) logOut(); // таймаут 60 мс (сигнал пропал) - вывод лога } } void initial() { // Установка начальных значений if (bitRead(reg_IN,1) == 0) { // Если А IN_PIN = echoPinA; // Назначаем IN_PIN А errA(); // Вызываем подпрограмму коррекции A } else // если нет, идём дальше if (bitRead(reg_IN,2) == 0) { // Если B IN_PIN = echoPinB; // Назначаем IN_PIN B errB(); // Вызываем подпрограмму коррекции B } else // если нет, идём дальше if (bitRead(reg_IN,3) == 0) { // Если C IN_PIN = echoPinC; // Назначаем IN_PIN C errC(); // Вызываем подпрограмму коррекции C } else // если нет, идём дальше if (bitRead(reg_IN,4) == 0) { // Если D IN_PIN = echoPinD; // Назначаем IN_PIN D errD(); // Вызываем подпрограмму коррекции D } count = 0; // count duration = 0; // duration = время до фронта последнего импульса for (int i = 0; i < LOG_SIZE; i++) { durus[i] = 0; } flag = 0; // flag first = prevS = digitalRead(IN_PIN); // Запомнили начальное состояние текущего пина // Выводим сигнал запуска излучателя send_CKL(); } void logOut() { // передача полученных результатов на WeMosArd // Читаем напряжение analog1 = analogRead(analog1Pin); // читаем напряжение источника питания voltage1 = (analog1*50.0) / 1024; // пересчитываем число в вольты printSendingData(); // Записываем переменные для отправки ISPReadings.reg1 = regkn2; ISPReadings.reg2 = regm1; ISPReadings.reg3 = regm2; ISPReadings.reg4 = reg_IN; ISPReadings.reg5 = count; ISPReadings.voltbat = voltage1; ISPReadings.dursig = duration; for (int i = 0; i < LOG_SIZE; i++) { ISPReadings.arrey1[i] = durus[i]; } // Отправляем сообщение esp_now_send(broadcastAddress,(uint8_t*)&ISPReadings,sizeof(ISPReadings)); flagrec = 0; // сброс флага посылки } void send_CKL() { // выдача сигналов управления на исполнительное устройство shiftOut(MOSI_PIN,SCK_PIN,MSBFIRST,regout); // пересылка байта regout digitalWrite(trigPin, LOW); // запись нуля в выходной вывод delayMicroseconds(2); // удержание нуля в течение 2 мксек digitalWrite(trigPin, HIGH); // запись единицы в выходной вывод delayMicroseconds(10); // удержание единицы в течение 10 мксек digitalWrite(trigPin, LOW); // запись нуля в выходной вывод start = micros(); } void errA() { // условие коррекции канала А if (bitRead(regkn2,1) == 1){ // Если нет нажатия кнопки канала А if (bitRead(regm1,4) == 0) { // Если питание 12 В if (bitRead(regm1,7) == 0) { // Если Ку = 36 if (bitRead(regm1,1) == 0) { // Если 8 имп flerr = 1; }} // Установка флага ошибки else // если не этот режим if (bitRead(regm1,2) == 0) { // Если 16 имп flerr = 1; }} // Установка флага ошибки else // если питание 24 В if (bitRead(regm1,7) == 0) { // Если Ку = 36 flerr = 1; }} // Установка флага ошибки } void errB() { // условие коррекции канала B if (bitRead(regkn2,2) == 1) { // Если нет нажатия кнопки канала B if (bitRead(regm1,4) == 0) { // Если питание 12 В if (bitRead(regm1,6) == 0) { // Если Ку = 6 if (bitRead(regm1,2) == 0) { // Если 16 имп flerr = 1; }} // Установка флага ошибки else // если не этот режим if (bitRead(regm1,7) == 0) { // Если Ку = 36 flerr = 1; }} // Установка флага ошибки else // если питание 24 В if (bitRead(regm1,6) == 0) { // Если Ку = 6 if (bitRead(regm1,1) == 0) { // Если 8 имп flerr = 1; }} // Установка флага ошибки else // если не этот режим if (bitRead(regm1,2) == 0) { // Если 16 имп flerr = 1; } // Установка флага ошибки else // если не этот режим if (bitRead(regm1,7) == 0) { // Если Ку = 36 flerr = 1; }} // Установка флага ошибки } void errC() { // условие коррекции канала C if (bitRead(regkn2,3) == 1) { // Если нет нажатия кнопки канала C if (bitRead(regm1,4) == 0) { // Если питание 12 В if (bitRead(regm1,6) == 0) { // Если Ку = 6 if (bitRead(regm1,1) == 0) { // Если 8 имп flerr = 1; }} // Установка флага ошибки else // если не этот режим if (bitRead(regm1,2) == 0) { // Если 16 имп flerr = 1; } // Установка флага ошибки else // если не этот режим if (bitRead(regm1,7) == 0) { // Если Ку = 36 flerr = 1; }} // Установка флага ошибки else // если питание 24 В if (bitRead(regm1,6) == 0) { // Если Ку = 6 flerr = 1; } // Установка флага ошибки else // если не этот режим if (bitRead(regm1,7) == 0) { // Если Ку = 36 flerr = 1; }} // Установка флага ошибки } void errD() { // условие коррекции канала D if (bitRead(regkn2,4) == 1) { // Если нет нажатия кнопки канала D if (bitRead(regm1,4) == 0) { // Если питание 12 В if (bitRead(regm1,6) == 0) { // Если Ку = 6 flerr = 1; } // Установка флага ошибки else // если не этот режим if (bitRead(regm1,7) == 0) { // Если Ку = 36 flerr = 1; }} // Установка флага ошибки else // если питание 24 В if (bitRead(regm1,5) == 0) { // Если Ку = 1 if (bitRead(regm1,2) == 0) { // Если 16 имп flerr = 1; }} // Установка флага ошибки else // если не этот режим if (bitRead(regm1,6) == 0) { // Если Ку = 6 flerr = 1; } // Установка флага ошибки else // если не этот режим if (bitRead(regm1,7) == 0) { // Если Ку = 36 flerr = 1; }} // Установка флага ошибки } /* 7 6 5 4 3 2 1 0 regm1 X36 X6 X1 12/24V - 16 имп 8 имп 4 имп reg_IN - - - D C B A - regkn2 ЭКРАН - АВТО D C B A СРЕДА - - - - L1 L2 L3 L4 - - - - - КАН 4 КАН 3 КАН 2 КАН 1 - regout - - A0T DC A1T A0R A1R - int i; for (i = 0; i < 5; i = i + 1) { Serial.println(myArray[i]); } */