Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 // 23.12.2021 Продолжение (клон )mbed-os5-press25 00002 //21. Автоматическое поддержание давления в рампе в диапазоне 50...150 Бар, запрет повторного включения компрессора в течении 10...15 мин. 00003 //20. Давления со всех АЦП теперь дополнительно интегрируются для уменьшения шумов. 00004 //19. Теперь вес принимается по шине i2c в Ньютонах, как на дисплее динамометра. 00005 //18. По шине i2c Arduino Nano с адресом 2, передает значение веса с дискретностью 1 кг, приём происходит раз в секунду, используется timer. 00006 //17. digital pin 11, pin 12 as an input концевики теперь нормально замкнутые. 00007 //16. Вернул timer_4. Теперь он периодически открывает выпускной клапан для контроля утечек воды. 00008 //15. Вместо pc.printf("Reset ALARM \r\n") теперь plotter.printf("Reset ALARM \r\n") это нужно для парсера программы Setup_EEPROM. 00009 //14. Удалена команда pc.printf, посылающая пустую строку раз в секунду и связанный с ней timer_4, т.к. изменена программа оператора (Loc()). 00010 //13. Суммирование значений каналов А0 А1 А2 было 9 раз, исправлено на 10. 00011 //12. Передаваемые через pc.printf сообщения в РС дополнены контрольными суммами для увеличения надёжности связи. 00012 //11. Введена команда pc.printf, посылающая пустую строку раз в секунду, на случай потери (порчи )данных при пересылке и 00013 // возможного зависания программы оператора при ожидании символа из serial порта (для этого добавлен timer_4). 00014 //10. Значения уставок EEPROM2 выводяться в pc.print в специальной строке с текущими данными диагностики. 00015 //9. Сделан дополнительный блок в парсере для декодирования приходящих аварийных уставок, они пишутся в EEPROM2. 00016 //8. Сделан timer_2 для отсчёта времени открытого состояния вентиля 1. 00017 // Сделан timer_3 для отсчёта времени открытого состояния вентиля 2. 00018 //7. Подключены цифровые входы D11,D12,D13. Реализованы условия остановки по 10 аварийным событиям. 00019 //6. Реализован сброс события (event_N = 255) через кнопку Стоп в программе оператора . 00020 //5. Принимается флаг от кнопки Стоп - полной остановки регулятора - закрытие всех 4-х клапанов и передача статуса кнопки в программу оператора. 00021 // Принимается флаг от кнопок включения - выключения компрессора, - идет команда на дискретный выход digital_6(PB_10) 00022 //4. Принимается новая уставка num_chan - переключение номера активного измерительного канала для обратной связи регулятора. 00023 // эта уставка, как и все остальные, пишется в EEPROM. 00024 //3. Включены все шесть аналоговых входа, читаются пять. 00025 //2. При получении командной строки с нулевой суммой, по новому флагу flag_zerostart, передаётся в сериал текущие уставки и величины 00026 // (важно для старта программы на PC), эти нулевые уставки не вводятся в регулятор и не записываются в EEPROM. 00027 //1. Сторожевой таймер, истекает через 100мс. 00028 // 00029 00030 #include "mbed.h" 00031 #include "_24LCXXX.h" 00032 00033 I2C i2c(PB_9,PB_8); // sda, scl 00034 _24LCXXX eeprom(&i2c, 0x50); 00035 const int addr7bit = 0x02; // 7 bit I2C address slave Arduino_Nano 00036 const int addr8bit = 0x02 << 1; // 8bit I2C address, 0x90 00037 00038 AnalogIn analog_value_0(A0); //подключение аналогового входа A0 00039 AnalogIn analog_value_1(A1); //подключение аналогового входа A1 00040 AnalogIn analog_value_2(A2); //подключение аналогового входа A2 00041 AnalogIn analog_value_3(A3); //подключение аналогового входа A3 00042 AnalogIn analog_value_4(A4); //подключение аналогового входа A4 00043 AnalogIn analog_value_5(A5); //подключение аналогового входа A5 00044 00045 DigitalOut digital_4(PB_5); //initialize digital pin 4 as an output (high pressure air bulb charge). 00046 DigitalOut digital_7(PA_8); //initialize digital pin 7 as an output. (high pressure air bulb discharge) 00047 DigitalOut digital_5(PB_4); //initialize digital pin 5 as an output (valve3,4) 00048 DigitalOut digital_6(PB_10); //initialize digital pin 6 as an output (compressor on/off) 00049 DigitalIn idigital_11(PA_7); //initialize digital pin 11 as an input концевик при растяжении сильфона 00050 DigitalIn idigital_12(PA_6); //initialize digital pin 12 as an input концевик при сжатии сильфона 00051 DigitalIn idigital_13(PA_5); //initialize digital pin 13 as an input внутрь опрессовщика попала вода 00052 00053 RawSerial plotter(USBTX, USBRX, 115200); // tx, rx for F411RE port for serial_plotter and temporary messages 00054 RawSerial pc(PA_9, PA_10, 115200); // tx, rx for F411RE port for command string distance PC 00055 EventQueue *queue = mbed_event_queue(); //инициализация очереди событий RTOS mbed5 00056 Timer timer; //инициализация таймера для определения частот переключений вентилей 1 и 2 00057 Timer timer_2; //инициализация таймера 2 для отсчёта времени открытого состояния вентиля 1 00058 Timer timer_3; //инициализация таймера 3 для отсчёта времени открытого состояния вентиля 2 00059 Timer timer_4; //инициализация таймера 4 для отсчёта периода времени между контрольными открываниями вентиля 2 00060 Timer timer_5; //инициализация таймера 5 для отсчёта времени запрета на включение компрессора 00061 //========УСТАВКИ_1 EEPROM======== 00062 uint8_t delta_value = 0; //set delta pressure 1...99 mV 00063 uint8_t flag_compressor = 0; //флаг компрессора. При 0 - разрешение на выключение компрессора, при 1 -разрешение на включение компрессора 00064 uint8_t flag_stopRegulator = 0; //Stop- флаг . При 0 - разрешение работы регулятора, при 1 - запрет и запиране всех клапанов 00065 uint8_t num_chan = 1; //set номер аналогового канала 0...5 (1-as default = Pa) 00066 int value = 0; //set begin value "pressure" 1...3300 mV 00067 //========УСТАВКИ_2 EEPROM======== 00068 int Pd_eeprom = 2000; // mV, максимальное дифференциальное давление (беззнаковое) 00069 int frequencyValve1_eeprom = 5; // Гц, максимальная частота переключений клапана 1 00070 int frequencyValve2_eeprom = 5; // Гц, максимальная частота переключений клапана 2 00071 int WL01_eeprom = 10; // mV, минимальный вес опрессовщика 00072 int WL99_eeprom = 2000; // mV, максимальный вес опрессовщика 00073 int T_1 = 4000; // ms, максимальное время открытого состояния для клапана 1 00074 int T_2 = 4000; // ms, максимальное время открытого состояния для клапана 2 00075 uint8_t event_N = 255; // номер события , по умолчанию 255 - событий нет 00076 uint8_t flag_stopRegulatorEEPROM = 0; //если 1 остановка регулятора, когда вручную управляют клапанами через программу SetUp_EEPROM 00077 int openTimeV2_H2O = 2; // ms, Время открытого состояния вентиля V2 для датчика влаги должно быть меньше WDlimit=100ms 00078 int periodV2_H2O = 10000; // ms, Период открывания вентиля V2 для датчика влаги 00079 int Pb_1 = 1080; // mV, минимальное давление в баллоне рампы компрессора 50Бар=(1080-600)/9.6 00080 int Pb_2 = 2040; // mV, максимальное давление в баллоне рампы компрессора 150Бар=(2040-600)/9.6 00081 int Tb = 600000; // ms, минимальный интервал времени перед следующим включением компрессора 00082 //======temporary set===== 00083 int numSet, anySet; 00084 //================================= 00085 int value_auto=250 ; //set begin value auto "pressure" 00086 int WL = 0; // WL - вес опресовщика 00087 int sensor_value =0; // с аналогового входа А1 (Pa - текущее давление) 00088 int Pb = 0; // с аналогового входа А2 (Pb - давление в баллоне) 00089 int Pw1 = 0; // с аналогового входа А3 (Pw1 - давление воды на входе опрессовщика) 00090 int Pw2 = 0; // с аналогового входа А4 (Pw2 - давление воды в контуре макета) 00091 int Pd = 0; // с аналогового входа А5 (Pd - дифференциальное давление опресовщика) 00092 int counter_cycle1 = 0; //счётчик цикла while(true) 00093 int counter_cycle2 = 0; //счётчик внутри функции auto_set 00094 int sig = 1; //знак инкримента для автоустаки 00095 int Ki = 10; //коэффициент интегрирования (по сути это - во сколько раз меньше вклад нового значения по сравнению с интегральной суммой) 00096 00097 // FIFO_buffer must be full (only char and '\0') 00098 //#define maxnsym 26 // maximum nbr of symbols FIFO_buffer (вариант без символов окончания) 00099 #define maxnsym 28 // maximum nbr of symbols FIFO_buffer +CR+LF (символы окончания должны быть включены на передаче) 00100 char Source[maxnsym]="$press,1000,25,0,0,1,2050**"; //25 char- string ,весь массив со строкой для поиска 25+1(null terminal)=26 00101 //уставки и контрольная сумма умноженная на два, должны быть больше нуля 00102 char trueSource[maxnsym]; //верифицированная строка для callback 00103 char trueSourceOld[maxnsym]; //предыдущая верифицированная строка для callback 00104 char trueSource2[maxnsym]; //верифицированная строка для callback 00105 char trueSource2Old[maxnsym]; //предыдущая верифицированная строка для callback 00106 00107 volatile char chr_a; //в прерываниях переменные должны быть защищены при помощи volatile от оптимизации компилятором 00108 volatile bool flag_comand_detected = false; //если строка декодирована правильно то true 00109 volatile bool flag_comand2_detected = false; //если строка в блоке парсинга уставок eeprom декодирована правильно то true 00110 volatile bool flag_zerostart = false; //если строка декодирована c нулевой контрольной суммой то true 00111 //volatile bool flag_stopRegulator = true; //флаг остановки , закрыть все клапана 00112 //_____________________________________________________________________________ 00113 void save_EEPROM () { 00114 int data2; 00115 plotter.printf("EEPROM write------\r\n"); 00116 eeprom.byte_write(0, delta_value); 00117 eeprom.byte_write(1, flag_compressor); 00118 eeprom.byte_write(2, flag_stopRegulator); 00119 eeprom.byte_write(3, num_chan); 00120 data2 = value; 00121 eeprom.nbyte_write( 10, &data2, sizeof(int)); 00122 } 00123 void save_EEPROM2 () { 00124 int data2; 00125 plotter.printf("EEPROM2 write------\r\n"); 00126 eeprom.nbyte_read( 100, &data2, sizeof(int) ); 00127 if (data2 != Pd_eeprom) { //записываем в eeprom только изменившиеся значения (одна из семи уставок) 00128 data2 = Pd_eeprom; 00129 eeprom.nbyte_write( 100, &data2, sizeof(int)); 00130 } 00131 eeprom.nbyte_read( 110, &data2, sizeof(int) ); 00132 if (data2 != frequencyValve1_eeprom){ 00133 data2 = frequencyValve1_eeprom; 00134 eeprom.nbyte_write( 110, &data2, sizeof(int)); 00135 } 00136 eeprom.nbyte_read( 120, &data2, sizeof(int) ); 00137 if (data2 != frequencyValve2_eeprom){ 00138 data2 = frequencyValve2_eeprom; 00139 eeprom.nbyte_write( 120, &data2, sizeof(int)); 00140 } 00141 eeprom.nbyte_read( 130, &data2, sizeof(int) ); 00142 if (data2 != WL01_eeprom){ 00143 data2 = WL01_eeprom; 00144 eeprom.nbyte_write( 130, &data2, sizeof(int)); 00145 } 00146 eeprom.nbyte_read( 140, &data2, sizeof(int) ); 00147 if (data2 != WL99_eeprom){ 00148 data2 = WL99_eeprom; 00149 eeprom.nbyte_write( 140, &data2, sizeof(int)); 00150 } 00151 eeprom.nbyte_read( 180, &data2, sizeof(int) ); 00152 if (data2 != T_1){ 00153 data2 = T_1; 00154 eeprom.nbyte_write( 180, &data2, sizeof(int)); 00155 } 00156 eeprom.nbyte_read( 190, &data2, sizeof(int) ); 00157 if (data2 != T_2){ 00158 data2 = T_2; 00159 eeprom.nbyte_write( 190, &data2, sizeof(int)); 00160 } 00161 eeprom.nbyte_read( 200, &data2, sizeof(int) ); 00162 if (data2 != openTimeV2_H2O){ 00163 data2 = openTimeV2_H2O; 00164 eeprom.nbyte_write( 200, &data2, sizeof(int)); 00165 } 00166 eeprom.nbyte_read( 210, &data2, sizeof(int) ); 00167 if (data2 != periodV2_H2O){ 00168 data2 = periodV2_H2O; 00169 eeprom.nbyte_write( 210, &data2, sizeof(int)); 00170 } 00171 eeprom.nbyte_read( 220, &data2, sizeof(int) ); 00172 if (data2 != Pb_1){ 00173 data2 = Pb_1; 00174 eeprom.nbyte_write( 220, &data2, sizeof(int)); 00175 } 00176 eeprom.nbyte_read( 230, &data2, sizeof(int) ); 00177 if (data2 != Pb_2){ 00178 data2 = Pb_2; 00179 eeprom.nbyte_write( 230, &data2, sizeof(int)); 00180 } 00181 eeprom.nbyte_read( 240, &data2, sizeof(int) ); 00182 if (data2 != Tb){ 00183 data2 = Tb; 00184 eeprom.nbyte_write( 240, &data2, sizeof(int)); 00185 } 00186 } 00187 //_____________________________________________________________________________ 00188 void load_EEPROM () { 00189 uint8_t data1; 00190 int data2; 00191 plotter.printf("EEPROM read------\r\n"); 00192 eeprom.nbyte_read( 0, &data1, 1 ); 00193 plotter.printf("adress 0 =%d \r\n",data1); 00194 delta_value=data1; 00195 eeprom.nbyte_read( 1, &data1, 1 ); 00196 plotter.printf("adress 1 =%d \r\n",data1); 00197 flag_compressor=data1; 00198 eeprom.nbyte_read( 2, &data1, 1 ); 00199 plotter.printf("adress 2 =%d \r\n",data1); 00200 flag_stopRegulator=data1; 00201 eeprom.nbyte_read( 3, &data1, 1 ); 00202 plotter.printf("adress 3 =%d \r\n",data1); 00203 num_chan=data1; 00204 eeprom.nbyte_read( 10, &data2, sizeof(int) ); 00205 plotter.printf("adress 10 = %d \r\n",data2); 00206 value=data2; 00207 } 00208 void load_EEPROM2 () { 00209 int data2; 00210 plotter.printf("EEPROM2 read------\r\n"); 00211 eeprom.nbyte_read( 100, &data2, sizeof(int) ); 00212 //pc.printf("$adress,100,%d,*\r\n",data2); 00213 Pd_eeprom=data2; 00214 eeprom.nbyte_read( 110, &data2, sizeof(int) ); 00215 //pc.printf("$adress,110,%d,*\r\n",data2); 00216 frequencyValve1_eeprom=data2; 00217 eeprom.nbyte_read( 120, &data2, sizeof(int) ); 00218 //pc.printf("$adress,120,%d,*\r\n",data2); 00219 frequencyValve2_eeprom=data2; 00220 eeprom.nbyte_read( 130, &data2, sizeof(int) ); 00221 //pc.printf("$adress,130,%d,*\r\n",data2); 00222 WL01_eeprom=data2; 00223 eeprom.nbyte_read( 140, &data2, sizeof(int) ); 00224 //pc.printf("$adress,140,%d,*\r\n",data2); 00225 WL99_eeprom=data2; 00226 eeprom.nbyte_read( 180, &data2, sizeof(int) ); 00227 //pc.printf("$adress,180,%d,*\r\n",data2); 00228 T_1=data2; 00229 eeprom.nbyte_read( 190, &data2, sizeof(int) ); 00230 //pc.printf("$adress,190,%d,*\r\n",data2); 00231 T_2=data2; 00232 eeprom.nbyte_read( 200, &data2, sizeof(int) ); 00233 //pc.printf("$adress,200,%d,*\r\n",data2); 00234 openTimeV2_H2O=data2; 00235 eeprom.nbyte_read( 210, &data2, sizeof(int) ); 00236 //pc.printf("$adress,210,%d,*\r\n",data2); 00237 periodV2_H2O=data2; 00238 eeprom.nbyte_read( 220, &data2, sizeof(int) ); 00239 //pc.printf("$adress,220,%d,*\r\n",data2); 00240 Pb_1=data2; 00241 eeprom.nbyte_read( 230, &data2, sizeof(int) ); 00242 //pc.printf("$adress,230,%d,*\r\n",data2); 00243 Pb_2=data2; 00244 eeprom.nbyte_read( 240, &data2, sizeof(int) ); 00245 //pc.printf("$adress,240,%d,*\r\n",data2); 00246 Tb=data2; 00247 //pc.printf("$adress,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,*\r\n",Pd_eeprom,frequencyValve1_eeprom,frequencyValve2_eeprom,WL01_eeprom,WL99_eeprom,T_1,T_2,openTimeV2_H2O,periodV2_H2O,Pb_1,Pb_2,Tb); 00248 } 00249 //______________________________________________________________________________ 00250 void substring(char *s,char *d,int pos,int len) { 00251 //usage: substring(Source,Destination,pos,len); 00252 char *t; 00253 s=s+(pos-1); 00254 t=s+len; 00255 while (s!=t) { 00256 *d=*s; 00257 s++; 00258 d++; 00259 } 00260 *d='\0'; 00261 } 00262 //______________________________________________________________________________ 00263 void onDataReceived(); // callback 00264 //______________________________________________________________________________ 00265 void read_serial(void) { 00266 char Destination[50]; 00267 int pos,len; 00268 int controlSum1, controlSum2; 00269 int value_, delta_value_, flag_compressor_, flag_stopRegulator_, num_chan_; 00270 int controlSumSet1, controlSumSet2; 00271 int numSet_, anySet_; 00272 int ch = '$'; // Код искомого символа 00273 int indexCh; // Char on position 00274 char *ach; // Указатель на искомую переменную в строке, по которой осуществляется поиск. 00275 while(pc.readable()) { 00276 chr_a = pc.getc(); 00277 //_____FIFO_buffer_begin_____ 00278 for ( int i = 2; i < maxnsym; i++) { 00279 Source[i-2]=Source[i-1]; 00280 } 00281 Source[maxnsym-2]=chr_a; //предпоследний элемент 00282 Source[maxnsym-1] ='\0'; //последний элемент массива это нуль-терминал для формирования конца строки в Си 00283 //_____FIFO_buffer_end_______ 00284 } 00285 ach=strchr (Source,ch); //поиск первого вхождения символа в строку , ищем указатель символа ‘$’ 00286 if (ach==NULL) { 00287 //pc.printf ("Char not finded \r\n"); //Символ $ в строке не найден 00288 goto endParsing; //пропускаем парсинг 00289 } 00290 else { 00291 indexCh = ach-Source+1; //вычитаем указатель из указателя! 00292 //pc.printf ("Char '$' on position %d\r\n",indexCh); //Искомый символ в строке на позиции 00293 } 00294 if (indexCh!=1) { //позиция символа $ не 1 00295 //pc.printf ("$ position not 1 \r\n"); 00296 goto endParsing; //пропускаем парсинг 00297 } 00298 00299 pos=1; //начало подстроки $press - на 1 позиции 00300 len=6; //длина подстроки $press равна 6 00301 substring(Source,Destination,pos,len); 00302 //pc.printf("for pos=%d and len=%d resultat is d= %s\r\n", pos, len, Destination); 00303 00304 if (strcmp(Destination,"$press" ) != 0) { //функция возвращает ноль если строки совпадают 00305 //pc.printf("wrong Destination=%s\r\n",Destination); //печать "неправильной" нулевой строки 00306 goto eepromSet ; //в начале сообщения нет $press , переход с следующему блоку приёма 00307 } 00308 pos=8; //начало подстроки 1000 - на 8 позиции 00309 len=4; //длина подстроки 1000 равна 4 00310 substring(Source,Destination,pos,len); 00311 value_=atoi(Destination); 00312 //if (value_==0) { 00313 // flag_zerostart = true; //индикатор первого пуска удаленной программы на PC без введенных уставок, надо передать текущее состояние на PC 00314 // goto endParsing; //уставка должна быть больше еденицы, пропускаем парсинг 00315 //} 00316 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, value_); 00317 pos=13; //начало подстроки 25 - на 13 позиции 00318 len=2; //длина подстроки 25 равна 2 00319 substring(Source,Destination,pos,len); 00320 delta_value_=atoi(Destination); 00321 //if (delta_value_==0) { 00322 // flag_zerostart = true; //индикатор первого пуска удаленной программы на PC без введенных уставок, надо передать текущее состояние на PC 00323 // goto endParsing; //уставка отклонения должна быть больше еденицы, пропускаем парсинг 00324 //} 00325 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, delta_value_); 00326 pos=16; //начало подстроки 0 - на 16 позиции 00327 len=1; //длина подстроки 0 равна 1 00328 substring(Source,Destination,pos,len); 00329 flag_compressor_=atoi(Destination); 00330 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_compressor_); 00331 pos=18; //начало подстроки 0 - на 18 позиции 00332 len=1; //длина подстроки 0 равна 1 00333 substring(Source,Destination,pos,len); 00334 flag_stopRegulator_=atoi(Destination); 00335 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_stopRegulator_); 00336 00337 pos=20; //начало подстроки 1 - на 20 позиции 00338 len=1; //длина подстроки 1 равна 1 00339 substring(Source,Destination,pos,len); 00340 num_chan_=atoi(Destination); 00341 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, num_chan_); 00342 00343 pos=22; //начало подстроки 1025 - на 22 позиции 00344 len=4; //длина подстроки 1025 равна 4 00345 substring(Source,Destination,pos,len); 00346 controlSum1=atoi(Destination); 00347 if (controlSum1==2) { 00348 flag_zerostart = true; //индикатор первого пуска удаленной программы на PC без введенных уставок, надо передать текущее состояние на PC 00349 flag_compressor=flag_compressor_; //здесь можно включать-выключать компрессор, но без записи в EEPROM 00350 goto endParsing; //контрольная сумма должна быть больше двух, пропускаем парсинг 00351 } 00352 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, controlSum1); 00353 controlSum2=(value_+delta_value_+flag_compressor_+flag_stopRegulator_+num_chan_)*2; //удвоение чтобы не было одинаковых чисел в сообщении 00354 //pc.printf("controlSum1=%d controlSum2=%d\r\n", controlSum1, controlSum2); 00355 if (controlSum1!=controlSum2) { //не совпала контрольная сумма 00356 //pc.printf ("controlSum1!=controlSum2 \r\n"); 00357 goto endParsing; //пропускаем парсинг 00358 } 00359 //*********присваиваем проверенные значения глобальным переменным*********** 00360 strcpy(trueSource,Source); //копировать из Source в trueSource 00361 if (value_==0 || delta_value_==0) { //при старте с пустой уставкой не изменяем их в регуляторе и не пишем в EEPROM 00362 flag_compressor=flag_compressor_; 00363 flag_stopRegulator=flag_stopRegulator_; //для работы кнопки Stop 00364 } else { 00365 value=value_; 00366 delta_value=delta_value_; 00367 flag_compressor=flag_compressor_; 00368 flag_stopRegulator=flag_stopRegulator_; 00369 num_chan=num_chan_; 00370 } 00371 flag_stopRegulatorEEPROM = 0; //флаг остановки только релейного регулятора (теперь регулятор управляет клапанами!) 00372 flag_comand_detected=true; //если флаг true, то всем переменным присвоены новые значения уставок 00373 goto endParsing ; //завершение блока приема рабочих уставок для работяющего релейного регулятора 00374 00375 //========Начало блока приёма аварийных граничных (максимальных) уставок для записи в EEPROM =================== 00376 eepromSet: 00377 if (strcmp(Destination,"$setup" ) != 0) { //функция возвращает ноль если строки совпадают 00378 //pc.printf("wrong Destination=%s\r\n",Destination); //печать "неправильной" нулевой строки 00379 goto endParsing ; //в начале сообщения нет $setup , пропускаем парсинг 00380 } 00381 pos=8; //начало подстроки 123 - на 8 позиции 00382 len=3; //длина подстроки 123 равна 3 00383 substring(Source,Destination,pos,len); 00384 numSet_=atoi(Destination); 00385 pos=12; //начало подстроки 123456 - на 12 позиции 00386 len=6; //длина подстроки 123456 равна 6 00387 substring(Source,Destination,pos,len); 00388 anySet_ =atoi(Destination); 00389 pos=19; //начало подстроки 1234567 - на 19 позиции 00390 len=7; //длина подстроки 1234567 равна 7 00391 substring(Source,Destination,pos,len); 00392 controlSumSet1 =atoi(Destination); 00393 controlSumSet2=(numSet_+anySet_)*2; 00394 if (controlSumSet1!=controlSumSet2) { //не совпала контрольная сумма 00395 //pc.printf ("controlSumSet1!=controlSumSet2 \r\n"); 00396 goto endParsing; //пропускаем парсинг 00397 } 00398 //*********присваиваем проверенные значения глобальным переменным*********** 00399 strcpy(trueSource2,Source); //копировать из Source в trueSource2 00400 if (numSet_==0) { //при старте с пустым номером не изменяем уставки и не пишем в EEPROM 00401 goto endParsing; //пропускаем парсинг 00402 } else { 00403 numSet=numSet_; 00404 anySet=anySet_; 00405 } 00406 //При первом входе в режим $setup из режима $press - Закрываются все клапана 00407 if (flag_stopRegulatorEEPROM == 0) { 00408 digital_4.write(0); //valve1 off 00409 digital_7.write(0); //valve2 off 00410 digital_5.write(0); //valve3,4 off 00411 digital_6.write(0); //выключение компрессора 00412 } 00413 00414 switch ( numSet ) { 00415 case 1: // это двоеточие 00416 digital_4.write(anySet); //valve1 00417 plotter.printf("1 Valve1=%d\r\n",anySet); 00418 break; 00419 case 2: 00420 digital_7.write(anySet); //valve2 00421 plotter.printf("2 Valve2=%d\r\n",anySet); 00422 break; 00423 case 3: 00424 digital_5.write(anySet); //valve3,4 00425 plotter.printf("3 Valve3,4=%d\r\n",anySet); 00426 break; 00427 case 4: 00428 digital_6.write(anySet); //компрессор 00429 plotter.printf("4 Compressor=%d\r\n",anySet ); 00430 break; 00431 case 9: 00432 if (anySet == 0) { 00433 flag_stopRegulator=0; 00434 plotter.printf("Reset ALARM \r\n"); 00435 } else { 00436 flag_stopRegulator = 1; 00437 } 00438 break; 00439 case 10: 00440 Pd_eeprom = anySet; 00441 plotter.printf( "10 Pd_eeprom=%d\r\n",anySet ); 00442 break; 00443 case 11: 00444 frequencyValve1_eeprom = anySet; 00445 plotter.printf( "11 frequencyValve1_eeprom=%d\r\n",anySet ); 00446 break; 00447 case 12: 00448 frequencyValve2_eeprom = anySet; 00449 plotter.printf( "12 frequencyValve2_eeprom=%d\r\n",anySet ); 00450 break; 00451 case 13: 00452 WL01_eeprom = anySet; 00453 plotter.printf( "13 WL01_eeprom=%d\r\n",anySet ); 00454 break; 00455 case 14: 00456 WL99_eeprom = anySet; 00457 plotter.printf( "14 WL99_eeprom=%d\r\n",anySet ); 00458 break; 00459 case 18: 00460 T_1 = anySet; 00461 plotter.printf( "18 T_1=%d\r\n",anySet ); 00462 break; 00463 case 19: 00464 T_2 = anySet; 00465 plotter.printf( "19 T_2=%d\r\n",anySet ); 00466 break; 00467 case 20: 00468 openTimeV2_H2O = anySet; 00469 plotter.printf( "20 openTimeV2_H2O=%d\r\n",anySet ); 00470 break; 00471 case 21: 00472 periodV2_H2O = anySet; 00473 plotter.printf( "21 periodV2_H2O=%d\r\n",anySet ); 00474 break; 00475 case 22: 00476 Pb_1 = anySet; 00477 plotter.printf( "22 Pb_1=%d\r\n",anySet ); 00478 break; 00479 case 23: 00480 Pb_2 = anySet; 00481 plotter.printf( "23 Pb_2=%d\r\n",anySet ); 00482 break; 00483 case 24: 00484 Tb = anySet; 00485 plotter.printf( "24 Tb=%d\r\n",anySet ); 00486 break; 00487 default: 00488 plotter.printf( "Wrong case.\r\n" ); 00489 } 00490 00491 flag_stopRegulatorEEPROM = 1; //флаг остановки только релейного регулятора (теперь оператор вручную управляет клапанами!) 00492 flag_comand2_detected=true; //если флаг true, то всем переменным присвоены новые значения уставок 00493 //========Конец блока приёма аварийных граничных (максимальных) уставок для записи в EEPROM =================== 00494 00495 endParsing: 00496 00497 00498 pc.attach(&onDataReceived, Serial::RxIrq); // reattach interrupt - переподключение прерывания перед выходом из функции 00499 } 00500 //______________________________________________________________________________ 00501 void onDataReceived() { 00502 pc.attach(nullptr, Serial::RxIrq); // detach interrupt 00503 queue->call(read_serial); // process in a non ISR context - переход к функции приема строки - 00504 } // - в статусе отключенного прерывания (учим указатели!) 00505 //______________________________________________________________________________ 00506 void auto_set () { //подпрограмма управления компрессором 00507 int time_5; 00508 if (flag_stopRegulatorEEPROM != 0 ) { //в программе SetUp_EEPROM автоматика управления отключается, компрессор можно включать-выключать вручную 00509 goto endAutoset; 00510 } 00511 time_5 = timer_5.read_ms(); 00512 if (time_5 >= Tb && Pb < Pb_1 && flag_compressor == 1) { 00513 digital_6.write(1); //включение работы компрессора 00514 } 00515 if (Pb > Pb_2 || flag_compressor == 0) { 00516 digital_6.write(0); //отключение работы компрессора по превышении уставки или по команде с кнопки 00517 timer_5.reset(); //сброс в ноль защитного таймера сна компрессора 00518 time_5 = 0; 00519 } 00520 endAutoset: 00521 time_5=time_5; //эта пустая операция из-за того, что метку перехода не получилось установить в конце подпрограммы. 00522 } 00523 //****************************************************************************************************************** 00524 //****************************************************************************************************************** 00525 00526 int main() { 00527 00528 pc.attach(&onDataReceived, Serial::RxIrq); 00529 int time, time_2, time_3, time_4, ks, valve1, valve2, countValve1=0, countValve2=0, temp_valueSensor; 00530 int frequencyValve1, frequencyValve2; 00531 float raw_value_sum_0=0, raw_value_sum_1=0, raw_value_sum_2=0, raw_value_sum_3=0, raw_value_sum_4=0, raw_value_sum_5=0; 00532 char cmd[2]; //массив с весом, принятым от slave 00533 //i2c.read( addr8bit, cmd, 1); //читаем вес по шине i2c из slave Arduino_Nano 00534 //pc.printf("cmd[0] = %x\n", cmd[0]); 00535 00536 digital_4.write(0); //valve1 off; 00537 digital_7.write(0); //valve2 off; 00538 digital_5.write(0); //valve3,4 off; 00539 digital_6.write(0); //выключение компрессора 00540 //eeprom.nbyte_write( 200, &openTimeV2_H2O, sizeof(int)); //debug set 00541 //eeprom.nbyte_write( 210, &periodV2_H2O, sizeof(int)); //debug set 00542 load_EEPROM (); //загрузка уставок из EEPROM 00543 load_EEPROM2 (); //загрузка граничных уставок (аварийных событий)из EEPROM2 00544 if (value >= 1 && delta_value >= 1 && flag_compressor < 2 && flag_stopRegulator < 2 && num_chan < 6) { 00545 flag_stopRegulator=0; //уставки из EEPROM похожи на правду, разрешаем работу регулятора 00546 } else { 00547 flag_stopRegulator = 1; //флаг остановки установлен 00548 pc.printf("Regulator stopped, error in EEPROM \r\n"); 00549 } 00550 00551 pc.printf("Program started \r\n"); 00552 Watchdog &watchdog = Watchdog::get_instance(); 00553 watchdog.start(100); //WDlimit = 100 ms 00554 timer.start(); 00555 timer_2.start(); 00556 timer_3.start(); 00557 timer_4.start(); 00558 timer_5.start(); 00559 00560 while (true){ //бесконечный цикл 00561 // kick watchdog regularly within provided timeout (сброс собаки в начало счёта) 00562 watchdog.kick(); 00563 00564 if (flag_stopRegulator == 1){ event_N = 255;} //сброс события через кнопку Стоп в программе оператора 00565 00566 if (flag_stopRegulator == 1 || event_N < 255) { //полный останов регулятора и принудительное запирание всех клапанов 00567 digital_4.write(0); //valve1 off 00568 digital_7.write(0); //valve2 off 00569 digital_5.write(0); //valve3,4 off 00570 //digital_6.write(0); //выключение компрессора 00571 } 00572 00573 if (flag_comand_detected) { //пришла правильная командная строка 00574 ks=(value+delta_value+flag_compressor+flag_stopRegulator+ 00575 sensor_value+frequencyValve1+frequencyValve2+ 00576 WL+Pb+Pw1+Pw2+Pd+ 00577 digital_4.read()+digital_7.read()+digital_5.read()+digital_6.read()+event_N+idigital_11.read()+idigital_12.read()+idigital_13.read())*2; 00578 pc.printf("$press,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,*\r\n", 00579 value,delta_value,flag_compressor,flag_stopRegulator, 00580 sensor_value,frequencyValve1,frequencyValve2, 00581 WL,Pb,Pw1,Pw2,Pd, 00582 digital_4.read(),digital_7.read(),digital_5.read(),digital_6.read(),event_N,idigital_11.read(),idigital_12.read(),idigital_13.read(), 00583 ks); //передача текущих значений в РС 00584 00585 //pc.printf("%s\r\n",trueSource); //эхо для отладки канала связи 00586 flag_comand_detected = false; //в последующих обращениях не печатать пока нет новых уставок из СОМ-порта 00587 00588 if (strcmp(trueSourceOld,trueSource) != 0) { //функция возвращает ноль если командные строки совпадают 00589 save_EEPROM (); //пишем в память уставки отличные от старых 00590 load_EEPROM (); 00591 } 00592 00593 strcpy(trueSourceOld,trueSource); //копировать из trueSource в trueSourceOld 00594 } 00595 00596 if (flag_comand2_detected ) { //пришла правильная строка из программы SetUp_EEPROM и передана уставка 00597 ks=(value+delta_value+flag_compressor+flag_stopRegulator+ 00598 sensor_value+frequencyValve1+frequencyValve2+ 00599 WL+Pb+Pw1+Pw2+Pd+ 00600 digital_4.read()+digital_7.read()+digital_5.read()+digital_6.read()+ 00601 event_N+idigital_11.read()+idigital_12.read()+idigital_13.read()+ 00602 Pd_eeprom+frequencyValve1_eeprom+frequencyValve2_eeprom+WL01_eeprom+WL99_eeprom+T_1+T_2+openTimeV2_H2O+periodV2_H2O+Pb_1+Pb_2+Tb)*2; 00603 pc.printf("$press,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,*\r\n", 00604 value,delta_value,flag_compressor,flag_stopRegulator, //1,2,3,4 00605 sensor_value,frequencyValve1,frequencyValve2, //5,6,7 00606 WL,Pb,Pw1,Pw2,Pd, //8,9,10,11,12 00607 digital_4.read(),digital_7.read(),digital_5.read(),digital_6.read(), //13,14,15,16 00608 event_N,idigital_11.read(),idigital_12.read(),idigital_13.read(), //17,18,19,20 00609 Pd_eeprom,frequencyValve1_eeprom,frequencyValve2_eeprom,WL01_eeprom,WL99_eeprom,T_1,T_2, 00610 openTimeV2_H2O,periodV2_H2O,Pb_1,Pb_2,Tb,ks); //21,22,23,24,25,26,27,28,29,30,31,32,33 00611 flag_comand2_detected = false; //в последующих обращениях не печатать пока нет нового сообщения из СОМ-порта 00612 00613 if (strcmp(trueSource2Old,trueSource2) != 0 && numSet >= 10) { //функция возвращает ноль если командные строки совпадают 00614 00615 save_EEPROM2 (); //пишем в память все уставки от SetUp_EEPROM если хоть одна изменилась 00616 load_EEPROM2 (); 00617 } 00618 strcpy(trueSource2Old,trueSource2); //копировать из trueSource2 в trueSource2Old 00619 //pc.printf("$adress,%d,%d,%d,%d,%d,%d,%d,*\r\n",Pd_eeprom,frequencyValve1_eeprom,frequencyValve2_eeprom,WL01_eeprom,WL99_eeprom,T_1,T_2); 00620 } 00621 00622 if (flag_zerostart) { //пришла командная строка с пустыми уставками (актуально для получения данных на PC при первом запуске) 00623 ks=(value+delta_value+flag_compressor+flag_stopRegulator+ 00624 sensor_value+frequencyValve1+frequencyValve2+ 00625 WL+Pb+Pw1+Pw2+Pd+ 00626 digital_4.read()+digital_7.read()+digital_5.read()+digital_6.read()+event_N+idigital_11.read()+idigital_12.read()+idigital_13.read())*2; 00627 pc.printf("$press,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,*\r\n", 00628 value,delta_value,flag_compressor,flag_stopRegulator, 00629 sensor_value,frequencyValve1,frequencyValve2, 00630 WL,Pb,Pw1,Pw2,Pd, 00631 digital_4.read(),digital_7.read(),digital_5.read(),digital_6.read(),event_N,idigital_11.read(),idigital_12.read(),idigital_13.read(), 00632 ks); //передача текущих значений в РС 00633 flag_zerostart = false; 00634 } 00635 //счет counter_cycle1 идет от еденицы 00636 if (counter_cycle1 < 11 ) { 00637 float raw_value_0 = analog_value_0.read(); // Чтение аналогового входа 0 (0.0 to 1.0 = full ADC диапазон) 00638 raw_value_sum_0 = raw_value_sum_0 + raw_value_0; 00639 float raw_value_1 = analog_value_1.read(); // Чтение аналогового входа 1 (0.0 to 1.0 = full ADC диапазон) 00640 raw_value_sum_1 = raw_value_sum_1 + raw_value_1; 00641 float raw_value_2 = analog_value_2.read(); // Чтение аналогового входа 2 (0.0 to 1.0 = full ADC диапазон) 00642 raw_value_sum_2 = raw_value_sum_2 + raw_value_2; 00643 } 00644 if (counter_cycle1 >= 11 ) { 00645 float raw_value_3 = analog_value_3.read(); // Чтение аналогового входа 3 (0.0 to 1.0 = full ADC диапазон) 00646 raw_value_sum_3 = raw_value_sum_3 + raw_value_3; 00647 float raw_value_4 = analog_value_4.read(); // Чтение аналогового входа 4 (0.0 to 1.0 = full ADC диапазон) 00648 raw_value_sum_4 = raw_value_sum_4 + raw_value_4; 00649 //float raw_value_5 = analog_value_5.read(); // Чтение аналогового входа 5 (0.0 to 1.0 = full ADC диапазон) 00650 //raw_value_sum_5 = raw_value_sum_5 + raw_value_5; 00651 } 00652 00653 if (counter_cycle1 >= 20 ) { 00654 counter_cycle1=0; 00655 00656 //float m_WL = raw_value_sum_0/10 * 3300; //уровень воды, преобразование в напряжение 0-3300 mV с усреднением (теперь передаётся по i2c) 00657 raw_value_sum_0 = 0 ; 00658 //WL = (WL*Ki+m_WL)/(Ki+1); //интегральное значение 00659 float m_sensor_value = raw_value_sum_1/10 * 3300; //давление воздушной стороны сильфона, преобразование в напряжение 0-3300 mV с усреднением 00660 raw_value_sum_1 = 0 ; 00661 sensor_value = (sensor_value*Ki+m_sensor_value)/(Ki+1); //интегральное значение 00662 float m_Pb = raw_value_sum_2/10 * 3300; //давление в баллоне компрессора, преобразование в напряжение 0-3300 mV с усреднением 00663 raw_value_sum_2 = 0 ; 00664 Pb = (Pb*Ki+m_Pb)/(Ki+1); //интегральное значение 00665 float m_Pw1 = raw_value_sum_3/10 * 3300; //давление водяной стороны сильфона, преобразование в напряжение 0-3300 mV с усреднением 00666 raw_value_sum_3 = 0 ; 00667 Pw1 = (Pw1*Ki+m_Pw1)/(Ki+1); //интегральное значение 00668 float m_Pw2 = raw_value_sum_4/10 * 3300; //давление в контруре охлаждения макета, преобразование в напряжение 0-3300 mV с усреднением 00669 raw_value_sum_4 = 0 ; 00670 Pw2 = (Pw2*Ki+m_Pw2)/(Ki+1); //интегральное значение 00671 //float m_Pd = raw_value_sum_5/20 * 3300; //дифференциальное давление сильфона, преобразование в напряжение 0-3300 mV с усреднением 00672 //raw_value_sum_5 = 0 ; 00673 //Pd = (Pd*Ki+m_Pd)/(Ki+1); //интегральное значение 00674 Pd = abs(sensor_value - Pw1); //упрощённый вариант , когда нет дифференциального датчика давления 00675 00676 if (num_chan == 1) {temp_valueSensor = sensor_value;} //теперь источник сигнала для регулятора - канал 1 00677 if (num_chan == 3) {temp_valueSensor = Pw1;} //теперь источник сигнала для регулятора - канал 3 00678 if (num_chan == 4) {temp_valueSensor = Pw2;} //теперь источник сигнала для регулятора - канал 4 00679 00680 if (flag_stopRegulator == 0 && event_N == 255 && flag_stopRegulatorEEPROM == 0) { // можно запускать регулятор 00681 digital_5.write(1); //valve3,4 открыты - подключаемся к контуру охлаждения макета 00682 //-----------Контроль протечки воды через периодическое отпирание Valve2---------- 00683 time_4 = timer_4.read_ms(); 00684 if (time_4 >= periodV2_H2O) { //Время таймера достигло периода включения вентиля V2 00685 timer_4.reset(); 00686 digital_7.write(1); //valve2 on; 00687 ThisThread::sleep_for(openTimeV2_H2O); //Время открытого состояния (mc) вентиля V2 должно быть меньше WDlimit=100ms 00688 digital_7.write(0); //valve2 off; 00689 } 00690 //--------------regulator begin----------------------- 00691 if (temp_valueSensor > value + delta_value) { 00692 valve2 = digital_7.read(); 00693 digital_7.write(1); //valve2 on; 00694 if (valve2 < digital_7.read()) {countValve2++;} //счётчик передних фронтов напряжения (срабатывания клапана 2) 00695 digital_4.write(0); //valve1 off; 00696 } else if (temp_valueSensor < value - delta_value) { 00697 valve1 = digital_4.read(); 00698 digital_4.write(1); //valve1 on; 00699 if (valve1 < digital_4.read()) {countValve1++;} //счётчик передних фронтов напряжения (срабатывания клапана 1) 00700 digital_7.write(0); //valve2 off; 00701 } else { 00702 digital_4.write(0); //valve1 off; 00703 digital_7.write(0); //valve2 off; 00704 } 00705 //--------------regulator end------------------------- 00706 } 00707 time=timer.read_us(); //условие будет выполнятся ровно один раз в секунду 00708 if (time > 1000000) { 00709 timer.reset(); //начало счёта времени 00710 frequencyValve1 = countValve1; //частота (Гц) срабатывания клапана 1 00711 frequencyValve2 = countValve2; //частота (Гц) срабатывания клапана 2 00712 countValve1=0; 00713 countValve2=0; 00714 i2c.read( addr8bit, cmd, 2); //читаем вес в байтах по шине i2c из slave Arduino_Nano 00715 WL = (cmd[0]<<8)|cmd[1]; //преобразовываем байты побитовым сдвигом влево и сложением в десятичное число Ньютонов 00716 //plotter.printf("cmd[0] = %x\n", cmd[0]); 00717 } 00718 //--------------------==_ALARM_scope_Begin==---------------------- 00719 if (Pd >= Pd_eeprom) { 00720 event_N = 0; 00721 } 00722 if (frequencyValve1 >= frequencyValve1_eeprom) { 00723 event_N = 1; 00724 } 00725 if (frequencyValve2 >= frequencyValve2_eeprom) { 00726 event_N = 2; 00727 } 00728 if (WL <= WL01_eeprom) { 00729 event_N = 3; 00730 } 00731 if (WL >= WL99_eeprom) { 00732 event_N = 4; 00733 } 00734 if (idigital_11.read()==1) { 00735 event_N = 5; 00736 } 00737 if (idigital_12.read()==1) { 00738 event_N = 6; 00739 } 00740 if (idigital_13.read()==0) { 00741 event_N = 7; 00742 } 00743 00744 //-----------------Valve1 open time---------------------- 00745 if (digital_4.read() == 0 || flag_stopRegulatorEEPROM == 1 ) { // для режима $setup отключаем счёт времени 00746 timer_2.reset(); 00747 time_2 = 0; 00748 } else { 00749 time_2 = timer_2.read_ms(); 00750 } 00751 if (time_2 >= T_1) { 00752 event_N = 8; 00753 } 00754 //-----------------Valve2 open time---------------------- 00755 if (digital_7.read() == 0 || flag_stopRegulatorEEPROM == 1) { // для режима $setup отключаем счёт времен 00756 timer_3.reset(); 00757 time_3 = 0; 00758 } else { 00759 time_3 = timer_3.read_ms(); 00760 } 00761 if (time_3 >= T_2) { 00762 event_N = 9; 00763 } 00764 //--------------------==_ALARM_scope_End==---------------------- 00765 00766 00767 auto_set(); //подпрограмма управления компрессором 00768 00769 00770 } 00771 00772 00773 00774 ThisThread::sleep_for(1); // (mc) правильный оператор задержки для mbed5 00775 counter_cycle1++; 00776 00777 } 00778 }
Generated on Wed Aug 3 2022 04:49:32 by
1.7.2