123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- #include "usart.h"
- #ifdef USE_USART
- /**
- * @brief USART initialization
- * Если задействовано управление регулятором ТЭНа через UART, инициализируем оный
- */
- void USART_start(void) {
- Serial.begin(9600, SERIAL_8N1); // Инициализируем USART
- #ifdef Debug
- Serial.println("Started");
- #endif
- }
- /**
- * @brief Функция возвращает значение текущей мощности с учетом режима "Разгон"
- */
- static uint16_t get_Power(void) {
- if (fl.stab_off || fl.Udown || fl.NotZero) { // Если авария или сеть в дауне - передаем ноль
- return 0;
- }
- else if (fl.razg_on || fl.Ulow) { // В разгоне и при недостаточном сетевом передаем расчетную текущую мощность
- uint32_t tmp_u = (long)U_sum * U_sum;
- tmp_u /= 100;
- tmp_u *= Pnom;
- tmp_u /= U_LINE_Q;
- return tmp_u;
- } else { // В рабочем режиме - передаем уставку
- return Pust;
- }
- }
- /**
- * @brief Функция установки текущей мощности по запросу
- */
- static void set_newPDM(uint16_t power) {
- if (power >= Pnom) { // Если параметр превышает максимально возможное значение,
- PDMust = CICLE; // значит ставим максимально возможное значение.
- } else {
- PDMust = calc_proportion(power, CICLE, Pnom);
- }
- set_Pust(); // Пересчитаем Pust
- fl.dspNewData = 1; // Обновление информации на дисплее
- }
- #endif /* USE_USART */
- #ifdef USE_ADprotocol
- /* USART */
- /**
- * Байт "состав данных" b00010111 (основной параметр - мощность в нагрузке,
- * доп. параметр - напряжение сети) в HEX-формате 0x17
- */
- static char USART_InfoData[14] = {'T','1','7','0','0','0','0','0','0','0','0','0','0',0x0D}; // Массив готовых данных для передачи внешнему контроллеру
- static char USART_SetData[6]; // Массив управляющих символов от внешнего контроллера
- /**
- * @brief Парсим управляющую последовательность по универсальному протоколу
- */
- void USART_parser(void) {
- static uint8_t index = 0;
- static uint8_t data_size;
- while (Serial.available() > 0) {
- if (fl.stab_off) {
- Serial.read(); // Вычитываем очередной байт, чтобы не засирать буфер
- } else if ( !index || fl.uartTimeout ) { // Начало
- USART_SetData[0] = Serial.read(); // Вычитываем очередной байт
- fl.uartTimeout = 0; // Сбросим флаг таймаута ожидания окончания посылки
- cnt_uartWDT = 0; // Сбросим таймер ожидания окончания посылки
- switch ( USART_SetData[0] ) { // Ждём первый символ...
- case 'M':
- case 'm': { // ...запроса на изменение режима работы
- data_size = 2;
- index=1;
- break;
- }
- case 'P':
- case 'p': { // ...запроса на изменение уставки
- data_size = 5;
- index=1;
- break;
- }
- default: {
- // break;
- }
- }
- } else {
- USART_SetData[index] = Serial.read(); // Вычитываем очередной байт
- if ( USART_SetData[index] == 0x0D ) { // Ждем последнего символа посылки <CR>
- if ( index == data_size ) {
- switch (index) {
- case 2: { // Парсим запрос на смену режима
- switch ( USART_SetData[1] ) {
- case '0': { // Переход в рабочий режим
- if ( fl.razg_on ) {
- stop_razgon();
- }
- break;
- }
- case '1': { // Переход в режим разгона
- if ((!fl.NotZero) & (!fl.Udown) & (!fl.razg_off)) { // Если электросеть в дауне или разгон запрещен - не разгонишься
- fl.razg_on = 1;
- fl.razg = 1;
- }
- break;
- }
- case '2': { // Отключение нагрузки
- PDMust = 0;
- stop_razgon();
- Pust = 0;
- break;
- }
- default: {
- break;
- }
- }
- break;
- }
- case 5: { // Парсим запрос на смену уставки
- uint16_t tmp_p = 0;
- uint8_t b;
- for (uint8_t x=1; x <= 4; x++ ) {
- tmp_p *= 16;
- b = A_to_HEX (USART_SetData[x]);
- if (b == 255) {
- break;
- }
- tmp_p += b;
- }
- if (b != 255) {
- set_newPDM (tmp_p); // Установим новую уставку мощности;
- }
- break;
- }
- }
- index = 0;
- fl.dspNewData = 1; //Обновление информации на дисплее
- } else index = 0;
- } else if ( index++ == data_size ) {
- index = 0;
- }
- }
- }
- }
- /**
- * @brief Отчет внешнему контроллеру по универсальному протоколу
- */
- void USART_report(void) {
- uint16_t b;
- if (fl.stab_off) {
- b = 3; // b000000(11) - аварийное отключение нагрузки (удаленное включение невозможно)
- } else if (fl.Udown || fl.NotZero) {
- b = 6; // b000001(10) - отсутствие сетевого напряжения, нагрузка отключена
- } else if (fl.razg_on) {
- b = 1; // b(000000)(01) - разгон
- } else if (PDMust == 0) {
- b = 2; // b000000(10) - нагрузка отключена
- } else if (fl.Ulow) {
- b = 8; // b000010(00) - напряжения сети недостаточно для достижения уставки
- } else {
- b = 0; // b000000(00) - режим рабочий, ошибок нет
- }
- // Закодируем состав данных
- USART_InfoData[3] = HEX_to_A ( b / 16 ); // Старший разряд байта "Режим + ошибки"
- USART_InfoData[4] = HEX_to_A ( b % 16 ); // Младший разряд байта "Режим + ошибки"
- // Закодируем основной параметр - мощность на выходе
- b = get_Power(); // Получим текущую мощщу
- USART_InfoData[8] = HEX_to_A ( b % 16 ); // 0 разряд основного параметра
- b /= 16;
- USART_InfoData[7] = HEX_to_A ( b % 16 ); // 1 разряд основного параметра
- b /= 16;
- USART_InfoData[6] = HEX_to_A ( b % 16 ); // 2 разряд основного параметра
- USART_InfoData[5] = HEX_to_A ( b / 16 ); // 3 разряд основного параметра
- // Закодируем доп.параметр - напряжение сети
- if (fl.NotZero) { // Если сети нет, то и на выходе пусто
- USART_InfoData[12] = '0'; // 0 разряд основного параметра
- USART_InfoData[11] = '0'; // 1 разряд основного параметра
- USART_InfoData[10] = '0'; // 2 разряд основного параметра
- USART_InfoData[9] = '0'; // 3 разряд основного параметра
- } else {
- b = U_sum;
- USART_InfoData[12] = HEX_to_A ( b % 16 ); // 0 разряд основного параметра
- b /= 16;
- USART_InfoData[11] = HEX_to_A ( b % 16 ); // 1 разряд основного параметра
- b /= 16;
- USART_InfoData[10] = HEX_to_A ( b % 16 ); // 2 разряд основного параметра
- USART_InfoData[9] = HEX_to_A ( b / 16 ); // 3 разряд основного параметра
- }
- // Отправим
- Serial.write(USART_InfoData, 14);
- }
- #endif /* USE_ADprotocol */
- #ifdef USE_RMVK
- /* RMVK_/_Samovar */
- /**
- * @brief Функция возвращает значение текущего напряжения без десятичного знака
- */
- uint16_t get_Uin(void) {
- return ((U_real_dec < 5)? U_real : (U_real + 1));
- }
- /**
- * @brief Функция возвращает расчетное значение текущего (если getReal=true)
- * или желаемого (если getReal=false) напряжения
- */
- uint16_t get_Uout(const bool getReal) {
- if ( fl.Udown || fl.NotZero || (PDMust == 0) ) { // Если сеть в дауне или стаб в стопе - передаем ноль
- return 0;
- } else if ( getReal && ( fl.razg_on || fl.Ulow ) ) { // В разгоне и при недостаточном сетевом передаем текущее сетевое, если надо
- return get_Uin();
- } else { // В рабочем режиме - передаем уставку
- return calc_proportion(PDMust, U_LINE);
- }
- }
- /**
- * @brief Парсим управляющую последовательность от RMVK_/_Samovar
- */
- void USART_parser(void) {
- static String inoutString;
- static uint8_t index = 0;
- while (Serial.available() > 0) {
- char inChar = (char)Serial.read();// Вычитываем очередной байт
- if ( !index || fl.uartTimeout ) { // Начало посылки
- if ((inChar == 'A') || ((uint8_t)(inChar) == 0xD0)) { // Ждём первый символ посылки "A" или первый байт UTF-кириллицы из протокола Samovar'a
- inoutString = inChar;
- index=1;
- fl.uartTimeout = 0; // Сбросим флаг таймаута ожидания окончания посылки
- cnt_uartWDT = 0; // Сбросим таймер ожидания окончания посылки
- }
- } else if ( index++ < 13 ) { // Пока посылка не длиннее 13 символов, считаем её корректной
- if ( inChar == 0x0D ) { // Ждем последнего символа посылки <CR>
- index = 0;
- // Парсим строку, поскольку кончилась
- // В протоколе Samovar стандартное начало посылки "АТ" пересылается русскими символами в Юникоде. Баг или фича?
- if (( inoutString == ("AT+VI?")) || // Запрос текущего напряжения сети
- ( inoutString == ("АТ+VI?"))) { // В этой строке "АТ" - русскими символами!
- if (fl.NotZero) { // Если сети нет, то и на выходе пусто
- inoutString = String(0);
- } else {
- inoutString = String(get_Uin());
- }
- } else if (( inoutString == F("АТ+VO?")) || ( inoutString == F("АТ+VS?"))) { // Запрос текущей мощности от Samovar. В этой строке "АТ" - русскими символами!
- inoutString = String(get_Power());
- } else if ( inoutString == F("AT+VO?") ) { // Запрос текущего напряжения на выходе от РМВ-К
- inoutString = String(get_Uout(true));
- } else if ( inoutString == F("AT+VS?") ) { // Запрос напряжения уставки на выходе от РМВ-К
- inoutString = String(get_Uout(false));
- } else if ( inoutString == F("AT+ON?") ) { // Запрос состояния выхода от РМВ-К
- if ((PDMust == 0) || (fl.NotZero) || (fl.Udown)) { // Если на выходе 0
- inoutString = String("OFF");
- } else {
- inoutString = String("ON");
- }
- } else if (( inoutString == F("AT+SS?")) || // Запрос режима от Samovar
- ( inoutString == F("АТ+SS?"))) { // В этой строке "АТ" - русскими символами!
- if (fl.stab_off || fl.Udown || fl.NotZero) { // При аварии, сильно пониженном напряжении сети или его отсутствии - передаем ошибку
- inoutString = String(3);
- } else if (fl.razg_on) { // Передаем "Разгон"
- inoutString = String(1);
- } else if (PDMust == 0) { // Передаем "Стоп"
- inoutString = String(2);
- } else { // Передаем "Рабочий режим"
- inoutString = String(0);
- }
- } else if (( inoutString == F("AT+ON=0")) || // Запрос на выключение стабилизатора
- ( inoutString == F("АТ+ON=0"))) { // В этой строке "АТ" - русскими символами!
- if (!fl.stab_off) { // Если стаб не выключен аварийно...
- PDMust = 0;
- stop_razgon();
- Pust = 0;
- fl.dspNewData = 1; //Обновление информации на дисплее
- inoutString = "";
- }
- } else if (( inoutString == F("AT+ON=1")) || // Запрос на включение режима "Разгон"
- ( inoutString == F("АТ+ON=1"))) { // В этой строке "АТ" - русскими символами!
- if ((!fl.stab_off) && (!fl.NotZero) && (!fl.Udown) && (!fl.razg_off)) { // Если авария, электросеть в дауне или разгон запрещен - не разгонишься
- fl.razg_on = 1;
- fl.razg = 1;
- fl.dspNewData = 1; //Обновление информации на дисплее
- }
- inoutString = "";
- } else if ( inoutString.substring(0,8) == F("АТ+VS=") ) { // Запрос на изменение уставки от Samovar. В этой строке "АТ" - русскими символами!
- if (!fl.stab_off) { // Если стаб не выключен аварийно...
- //выключаем разгон, на всякий случай
- stop_razgon();
- set_newPDM (inoutString.substring(8).toInt()); // Установим новую уставку мощности
- inoutString = "";
- }
- } else if ( inoutString.substring(0,6) == F("AT+VS=") ) { // Запрос на изменение уставки от РМВ-К
- if (fl.stab_off || fl.Udown || fl.NotZero) { // Если авария или сеть в дауне - ничего не меняем, передаем ошибку
- inoutString = String(F("error"));
- } else {
- uint16_t tmp_u = inoutString.substring(6).toInt();
- if ( tmp_u < U_LINE ) {
- tmp_u *= CICLE;
- PDMust = tmp_u / U_LINE;
- } else PDMust = CICLE;
- //выключаем разгон, на всякий случай
- stop_razgon();
- set_Pust(); // Посчитаем Pust
- fl.dspNewData = 1; // Обновление информации на дисплее
- inoutString = String(get_Uout(false));
- }
- } else { // Неизвестная или закосяченная команда
- #ifdef Debug
- inoutString = String(F("(o_O unknown!)"));
- #else
- inoutString = "";
- #endif
- }
- if ( inoutString != "" ) { // Если строка не пустая
- inoutString += char(0x0D); // Добавляем в конец <CR>
- Serial.print( inoutString ); // Шлём!
- }
- } else { // Еще не конец
- inoutString += inChar; // Добавляем и это лыко в строку
- }
- } else { // Посылка длинновата, а значит - некорректна, начинаем сначала
- index = 0;
- }
- }
- }
- #endif /* RMVK_/_Samovar */
|