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 // 05.06.2020 Продолжение (клон )mbed-os5-press6 00002 // Принимается флаг от кнопки Стоп - полной остановки регулятора - закрытие всех 4-х клапанов и передача статуса кнопки в программу оператора 00003 // Принимается флаг от кнопок включения - выключения компрессора, - идет команда на дискретный выход digital_6(PB_10) 00004 // Принимается новая уставка num_chan - переключение номера активного измерительного канала для обратной связи регулятора. 00005 // Эта уставка, как и все остальные, пишется в EEPROM. 00006 // Включены все шесть аналоговых входа, читаются пять 00007 // при получении командной строки с нулевой суммой, по новому флагу flag_zerostart, передаётся в сериал текущие уставки и величины 00008 // (важно для старта программы на PC), эти нулевые уставки не вводятся в регулятор и не записываются в EEPROM. 00009 // сторожевой таймер, истекает через 100мс 00010 // 00011 00012 #include "mbed.h" 00013 #include "_24LCXXX.h" 00014 00015 I2C i2c(PB_9,PB_8); // sda, scl 00016 _24LCXXX eeprom(&i2c, 0x50); 00017 00018 AnalogIn analog_value_0(A0); //подключение аналогового входа A0 00019 AnalogIn analog_value_1(A1); //подключение аналогового входа A1 00020 AnalogIn analog_value_2(A2); //подключение аналогового входа A2 00021 AnalogIn analog_value_3(A3); //подключение аналогового входа A3 00022 AnalogIn analog_value_4(A4); //подключение аналогового входа A4 00023 AnalogIn analog_value_5(A5); //подключение аналогового входа A5 00024 DigitalOut led(LED1); 00025 DigitalOut digital_4(PB_5); //initialize digital pin 4 as an output (high pressure air bulb charge). 00026 DigitalOut digital_7(PA_8); //initialize digital pin 7 as an output. (high pressure air bulb discharge) 00027 DigitalOut digital_5(PB_4); //initialize digital pin 5 as an output (valve3,4) 00028 DigitalOut digital_6(PB_10); //initialize digital pin 6 as an output (compressor on/off) 00029 00030 RawSerial plotter(USBTX, USBRX, 115200); // tx, rx for F411RE port for serial_plotter and temporary messages 00031 RawSerial pc(PA_9, PA_10, 115200); // tx, rx for F411RE port for command string distance PC 00032 EventQueue *queue = mbed_event_queue(); //инициализация очереди событий RTOS mbed5 00033 Timer timer; //инициализация таймера 00034 //========УСТАВКИ======== 00035 uint8_t delta_value = 0; //set delta pressure 1...99 00036 uint8_t flag_autoset = 0; //флаг компрессора. При 0 - выключение компрессора, при 1 - включение компрессора 00037 uint8_t flag_plotter = 0; //Stop- флаг . При 0 - разрешение работы регулятора, при 1 - запрет и запиране всех клапанов 00038 uint8_t num_chan = 1; //set номер аналогового канала 0...5 (1-as default = Pa) 00039 int value = 0; //set begin value "pressure" 1...3300 00040 00041 //======================= 00042 int value_auto=250 ; //set begin value auto "pressure" 00043 int WL = 0; //напряжение с аналогового входа А0 (WL - вес опресовщика) 00044 int sensor_value =0; //напряжение с аналогового входа А1 (Pa - текущее давление) 00045 int Pb = 0; //напряжение с аналогового входа А2 (Pb - давление в баллоне) 00046 int Pw1 = 0; //напряжение с аналогового входа А3 (Pw1 - давление воды на входе опрессовщика) 00047 int Pw2 = 0; //напряжение с аналогового входа А4 (Pw2 - давление воды в контуре макета) 00048 int Pd = 0; //напряжение с аналогового входа А5 (Pd - дифференциальное давление опресовщика) 00049 int counter_cycle1 = 0; //счётчик цикла while(true) 00050 int counter_cycle2 = 0; //счётчик внутри функции auto_set 00051 int sig = 1; //знак инкримента для автоустаки 00052 // FIFO_buffer must be full (only char and '\0') 00053 //#define maxnsym 26 // maximum nbr of symbols FIFO_buffer (вариант без символов окончания) 00054 #define maxnsym 28 // maximum nbr of symbols FIFO_buffer +CR+LF (символы окончания должны быть включены на передаче) 00055 char Source[maxnsym]="$press,1000,25,0,0,1,2050**"; //25 char- string ,весь массив со строкой для поиска 25+1(null terminal)=26 00056 //уставки и контрольная сумма умноженная на два, должны быть больше нуля 00057 char trueSource[maxnsym]; //верифицированная строка для callback 00058 char trueSourceOld[maxnsym]; //предыдущая верифицированная строка для callback 00059 00060 volatile char chr_a; //в прерываниях переменные должны быть защищены при помощи volatile от оптимизации компилятором 00061 volatile bool flag_comand_detected = false; //если строка декодирована правильно то true 00062 volatile bool flag_zerostart = false; //если строка декодирована c нулевой контрольной суммой то true 00063 volatile bool flag_stopRegulator = true; //флаг остановки , закрыть все клапана 00064 //_____________________________________________________________________________ 00065 void save_EEPROM () { 00066 int data2; 00067 plotter.printf("EEPROM write------\r\n"); 00068 eeprom.byte_write(0, delta_value); 00069 eeprom.byte_write(1, flag_autoset); 00070 eeprom.byte_write(2, flag_plotter); 00071 eeprom.byte_write(3, num_chan); 00072 data2 = value; 00073 eeprom.nbyte_write( 10, &data2, sizeof(int)); 00074 } 00075 //_____________________________________________________________________________ 00076 void load_EEPROM () { 00077 uint8_t data1; 00078 int data2; 00079 plotter.printf("EEPROM read------\r\n"); 00080 eeprom.nbyte_read( 0, &data1, 1 ); 00081 plotter.printf("adress 0 =%d \r\n",data1); 00082 delta_value=data1; 00083 eeprom.nbyte_read( 1, &data1, 1 ); 00084 plotter.printf("adress 1 =%d \r\n",data1); 00085 flag_autoset=data1; 00086 eeprom.nbyte_read( 2, &data1, 1 ); 00087 plotter.printf("adress 2 =%d \r\n",data1); 00088 flag_plotter=data1; 00089 eeprom.nbyte_read( 3, &data1, 1 ); 00090 plotter.printf("adress 3 =%d \r\n",data1); 00091 num_chan=data1; 00092 eeprom.nbyte_read( 10, &data2, sizeof(int) ); 00093 plotter.printf("adress 10 = %d \r\n",data2); 00094 value=data2; 00095 } 00096 //______________________________________________________________________________ 00097 void substring(char *s,char *d,int pos,int len) { 00098 //usage: substring(Source,Destination,pos,len); 00099 char *t; 00100 s=s+(pos-1); 00101 t=s+len; 00102 while (s!=t) { 00103 *d=*s; 00104 s++; 00105 d++; 00106 } 00107 *d='\0'; 00108 } 00109 //______________________________________________________________________________ 00110 void onDataReceived(); // callback 00111 //______________________________________________________________________________ 00112 void read_serial(void) { 00113 char Destination[50]; 00114 int pos,len; 00115 int controlSum1, controlSum2; 00116 int value_, delta_value_, flag_autoset_, flag_plotter_, num_chan_; 00117 int ch = '$'; // Код искомого символа 00118 int indexCh; // Char on position 00119 char *ach; // Указатель на искомую переменную в строке, по которой осуществляется поиск. 00120 while(pc.readable()) { 00121 chr_a = pc.getc(); 00122 //_____FIFO_buffer_begin_____ 00123 for ( int i = 2; i < maxnsym; i++) { 00124 Source[i-2]=Source[i-1]; 00125 } 00126 Source[maxnsym-2]=chr_a; //предпоследний элемент 00127 Source[maxnsym-1] ='\0'; //последний элемент массива это нуль-терминал для формирования конца строки в Си 00128 //_____FIFO_buffer_end_______ 00129 } 00130 ach=strchr (Source,ch); //поиск первого вхождения символа в строку , ищем указатель символа ‘$’ 00131 if (ach==NULL) { 00132 //pc.printf ("Char not finded \r\n"); //Символ $ в строке не найден 00133 goto endParsing; //пропускаем парсинг 00134 } 00135 else { 00136 indexCh = ach-Source+1; //вычитаем указатель из указателя! 00137 //pc.printf ("Char '$' on position %d\r\n",indexCh); //Искомый символ в строке на позиции 00138 } 00139 if (indexCh!=1) { //позиция символа $ не 1 00140 //pc.printf ("$ position not 1 \r\n"); 00141 goto endParsing; //пропускаем парсинг 00142 } 00143 00144 pos=1; //начало подстроки $press - на 1 позиции 00145 len=6; //длина подстроки $press равна 6 00146 substring(Source,Destination,pos,len); 00147 //pc.printf("for pos=%d and len=%d resultat is d= %s\r\n", pos, len, Destination); 00148 00149 if (strcmp(Destination,"$press" ) != 0) { //функция возвращает ноль если строки совпадают 00150 //pc.printf("wrong Destination=%s\r\n",Destination); //печать "неправильной" нулевой строки 00151 goto endParsing ; //в начале сообщения нет $press пропускаем парсинг 00152 } 00153 pos=8; //начало подстроки 1000 - на 8 позиции 00154 len=4; //длина подстроки 1000 равна 4 00155 substring(Source,Destination,pos,len); 00156 value_=atoi(Destination); 00157 //if (value_==0) { 00158 // flag_zerostart = true; //индикатор первого пуска удаленной программы на PC без введенных уставок, надо передать текущее состояние на PC 00159 // goto endParsing; //уставка должна быть больше еденицы, пропускаем парсинг 00160 //} 00161 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, value_); 00162 pos=13; //начало подстроки 25 - на 13 позиции 00163 len=2; //длина подстроки 25 равна 2 00164 substring(Source,Destination,pos,len); 00165 delta_value_=atoi(Destination); 00166 //if (delta_value_==0) { 00167 // flag_zerostart = true; //индикатор первого пуска удаленной программы на PC без введенных уставок, надо передать текущее состояние на PC 00168 // goto endParsing; //уставка отклонения должна быть больше еденицы, пропускаем парсинг 00169 //} 00170 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, delta_value_); 00171 pos=16; //начало подстроки 0 - на 16 позиции 00172 len=1; //длина подстроки 0 равна 1 00173 substring(Source,Destination,pos,len); 00174 flag_autoset_=atoi(Destination); 00175 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_autoset_); 00176 pos=18; //начало подстроки 0 - на 18 позиции 00177 len=1; //длина подстроки 0 равна 1 00178 substring(Source,Destination,pos,len); 00179 flag_plotter_=atoi(Destination); 00180 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_plotter_); 00181 00182 pos=20; //начало подстроки 1 - на 20 позиции 00183 len=1; //длина подстроки 1 равна 1 00184 substring(Source,Destination,pos,len); 00185 num_chan_=atoi(Destination); 00186 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, num_chan_); 00187 00188 pos=22; //начало подстроки 1025 - на 22 позиции 00189 len=4; //длина подстроки 1025 равна 4 00190 substring(Source,Destination,pos,len); 00191 controlSum1=atoi(Destination); 00192 if (controlSum1==2) { 00193 flag_zerostart = true; //индикатор первого пуска удаленной программы на PC без введенных уставок, надо передать текущее состояние на PC 00194 flag_autoset=flag_autoset_; //здесь можно включать-выключать компрессор, но без записи в EEPROM 00195 goto endParsing; //контрольная сумма должна быть больше двух, пропускаем парсинг 00196 } 00197 //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, controlSum1); 00198 controlSum2=(value_+delta_value_+flag_autoset_+flag_plotter_+num_chan_)*2; //удвоение чтобы не было одинаковых чисел в сообщении 00199 //pc.printf("controlSum1=%d controlSum2=%d\r\n", controlSum1, controlSum2); 00200 if (controlSum1!=controlSum2) { //не совпала контрольная сумма 00201 //pc.printf ("controlSum1!=controlSum2 \r\n"); 00202 goto endParsing; //пропускаем парсинг 00203 } 00204 //*********присваиваем проверенные значения глобальным переменным*********** 00205 strcpy(trueSource,Source); //копировать из Source в trueSource 00206 if (value_==0 || delta_value_==0) { //при старте с пустой уставкой не имземняем их в регуляторе и не пишем в EEPROM 00207 flag_autoset=flag_autoset_; 00208 flag_plotter=flag_plotter_; //для работы кнопки Stop 00209 } else { 00210 value=value_; 00211 delta_value=delta_value_; 00212 flag_autoset=flag_autoset_; 00213 flag_plotter=flag_plotter_; 00214 num_chan=num_chan_; 00215 } 00216 00217 flag_comand_detected=true; //если флаг true, то всем переменным присвоены новые значения уставок 00218 00219 endParsing: 00220 00221 00222 pc.attach(&onDataReceived, Serial::RxIrq); // reattach interrupt - переподключение прерывания перед выходом из функции 00223 } 00224 //______________________________________________________________________________ 00225 void onDataReceived() { 00226 pc.attach(nullptr, Serial::RxIrq); // detach interrupt 00227 queue->call(read_serial); // process in a non ISR context - переход к функции приема строки - 00228 } // - в статусе отключенного прерывания (учим указатели!) 00229 //______________________________________________________________________________ 00230 void auto_set () { //подпрограмма управления компрессором 00231 00232 digital_6.write(flag_autoset); //включение-выкючение компрессора 00233 00234 } 00235 //***************************************************************************** 00236 //***************************************************************************** 00237 00238 int main() { 00239 00240 pc.attach(&onDataReceived, Serial::RxIrq); 00241 int time, valve1, valve2, countValve1=0, countValve2=0, temp_valueSensor; 00242 int frequencyValve1, frequencyValve2; 00243 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; 00244 digital_4.write(0); //valve1 off; 00245 digital_7.write(0); //valve2 off; 00246 digital_5.write(0); //valve3,4 off; 00247 digital_6.write(0); //выключение компрессора 00248 load_EEPROM (); //загрузка уставок из EEPROM 00249 if (value >= 1 && delta_value >= 1 && flag_autoset < 2 && flag_plotter < 2 && num_chan < 6) { 00250 flag_stopRegulator=false; //уставки из EEPROM похожи на правду, разрешаем работу регулятора 00251 } else { 00252 flag_stopRegulator = true; //флаг остановки установлен 00253 pc.printf("Regulator stopped, error in EEPROM \r\n"); 00254 } 00255 00256 pc.printf("Program started \r\n"); 00257 Watchdog &watchdog = Watchdog::get_instance(); 00258 watchdog.start(100); //WDlimit = 100 ms 00259 timer.start(); 00260 00261 while (true){ //бесконечный цикл 00262 // kick watchdog regularly within provided timeout (сброс собаки в начало счёта) 00263 watchdog.kick(); 00264 00265 flag_stopRegulator = flag_plotter; //вывод на плоттер не актуален, теперь он будет флагом полной остановки опрессовщика 00266 if (flag_stopRegulator) { //полный останов регулятора и принудительное запирание всех клапанов 00267 digital_4.write(0); //valve1 off 00268 digital_7.write(0); //valve2 off 00269 digital_5.write(0); //valve3,4 off 00270 //digital_6.write(0); //выключение компрессора 00271 } 00272 00273 if (flag_comand_detected) { //пришла правильная командная строка 00274 pc.printf("$press,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,*\r\n", 00275 value,delta_value,flag_autoset,flag_plotter, 00276 sensor_value,frequencyValve1,frequencyValve2, 00277 WL,Pb,Pw1,Pw2,Pd, 00278 digital_4.read(),digital_7.read(),digital_5.read(),digital_6.read()); //передача текущих значений в РС 00279 00280 // pc.printf("$press,%d,%d,%d,%d,%d,%d,%d,*\r\n", 00281 // value,delta_value,flag_autoset,flag_plotter, 00282 // sensor_value,frequencyValve1,frequencyValve2); //передача текущих значений в РС 00283 00284 //pc.printf("%s\r\n",trueSource); //эхо для отладки канала связи 00285 flag_comand_detected = false; //в последующих обращениях не печатать пока нет новых уставок из СОМ-порта 00286 //flag_stopRegulator = false; //сброс флага, регулятор ждет пока не будет сброшен этот флаг 00287 //plotter.printf("$%d %d %d %d %d;\r\n", digital_4.read()*100-110, 00288 // digital_7.read()*100-220, value, sensor_value, time ); //печать в плоттер в другой СОМ-порт 00289 if (strcmp(trueSourceOld,trueSource) != 0) { //функция возвращает ноль если командные строки совпадают 00290 save_EEPROM (); //пишем в память уставки отличные от старых 00291 load_EEPROM (); 00292 } 00293 00294 strcpy(trueSourceOld,trueSource); //копировать из trueSource в trueSourceOld 00295 } 00296 00297 if (flag_zerostart) { //пришла командная строка с пустыми уставками (актуально для получения данных на PC при первом запуске) 00298 pc.printf("$press,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,*\r\n", 00299 value,delta_value,flag_autoset,flag_plotter, 00300 sensor_value,frequencyValve1,frequencyValve2, 00301 WL,Pb,Pw1,Pw2,Pd, 00302 digital_4.read(),digital_7.read(),digital_5.read(),digital_6.read()); //передача текущих значений в РС 00303 flag_zerostart = false; 00304 } 00305 00306 if (counter_cycle1 < 10 ) { 00307 float raw_value_0 = analog_value_0.read(); // Чтение аналогового входа 0 (0.0 to 1.0 = full ADC диапазон) 00308 raw_value_sum_0 = raw_value_sum_0 + raw_value_0; 00309 float raw_value_1 = analog_value_1.read(); // Чтение аналогового входа 1 (0.0 to 1.0 = full ADC диапазон) 00310 raw_value_sum_1 = raw_value_sum_1 + raw_value_1; 00311 float raw_value_2 = analog_value_2.read(); // Чтение аналогового входа 2 (0.0 to 1.0 = full ADC диапазон) 00312 raw_value_sum_2 = raw_value_sum_2 + raw_value_2; 00313 } 00314 if (counter_cycle1 >= 10 ) { 00315 float raw_value_3 = analog_value_3.read(); // Чтение аналогового входа 3 (0.0 to 1.0 = full ADC диапазон) 00316 raw_value_sum_3 = raw_value_sum_3 + raw_value_3; 00317 float raw_value_4 = analog_value_4.read(); // Чтение аналогового входа 4 (0.0 to 1.0 = full ADC диапазон) 00318 raw_value_sum_4 = raw_value_sum_4 + raw_value_4; 00319 //float raw_value_5 = analog_value_5.read(); // Чтение аналогового входа 5 (0.0 to 1.0 = full ADC диапазон) 00320 //raw_value_sum_5 = raw_value_sum_5 + raw_value_5; 00321 } 00322 00323 if (counter_cycle1 >= 19 ) { 00324 counter_cycle1=0; 00325 00326 WL = raw_value_sum_0/10 * 3300; // преобразование в напряжение 0-3300 mV с усреднением 00327 raw_value_sum_0 = 0 ; 00328 sensor_value = raw_value_sum_1/10 * 3300; // преобразование в напряжение 0-3300 mV с усреднением 00329 raw_value_sum_1 = 0 ; 00330 Pb = raw_value_sum_2/10 * 3300; // преобразование в напряжение 0-3300 mV с усреднением 00331 raw_value_sum_2 = 0 ; 00332 Pw1 = raw_value_sum_3/10 * 3300; // преобразование в напряжение 0-3300 mV с усреднением 00333 raw_value_sum_3 = 0 ; 00334 Pw2 = raw_value_sum_4/10 * 3300; // преобразование в напряжение 0-3300 mV с усреднением 00335 raw_value_sum_4 = 0 ; 00336 //Pd = raw_value_sum_5/20 * 3300; // преобразование в напряжение 0-3300 mV с усреднением 00337 //raw_value_sum_5 = 0 ; 00338 00339 if (num_chan == 1) {temp_valueSensor = sensor_value;} //теперь источник сигнала для регулятора - канал 1 00340 if (num_chan == 3) {temp_valueSensor = Pw1;} //теперь источник сигнала для регулятора - канал 3 00341 if (num_chan == 4) {temp_valueSensor = Pw2;} //теперь источник сигнала для регулятора - канал 4 00342 00343 if (flag_stopRegulator == false) { // можно запускать регулятор 00344 digital_5.write(1); //valve3,4 открыты - подключаемся к контуру охлаждения макета 00345 //--------------regulator begin----------------------- 00346 if (temp_valueSensor > value + delta_value) { 00347 valve2 = digital_7.read(); 00348 digital_7.write(1); //valve2 on; 00349 if (valve2 < digital_7.read()) {countValve2++;} //счётчик передних фронтов напряжения (срабатывания клапана 2) 00350 digital_4.write(0); //valve1 off; 00351 } else if (temp_valueSensor < value - delta_value) { 00352 valve1 = digital_4.read(); 00353 digital_4.write(1); //valve1 on; 00354 if (valve1 < digital_4.read()) {countValve1++;} //счётчик передних фронтов напряжения (срабатывания клапана 1) 00355 digital_7.write(0); //valve2 off; 00356 } else { 00357 digital_4.write(0); //valve1 off; 00358 digital_7.write(0); //valve2 off; 00359 } 00360 //--------------regulator end------------------------- 00361 } 00362 time=timer.read_us(); 00363 if (time > 1000000) { 00364 timer.reset(); //начало счёта времени 00365 frequencyValve1 = countValve1; //частота (Гц) срабатывания клапана 1 00366 frequencyValve2 = countValve2; //частота (Гц) срабатывания клапана 2 00367 countValve1=0; 00368 countValve2=0; 00369 } 00370 00371 auto_set(); //включение-выкючение компрессора через flag_autoset 00372 led = !led; //гасим/зажигаем индикаторный светодиод 00373 } 00374 ThisThread::sleep_for(1); // (mc) правильный оператор задержки для mbed5 00375 counter_cycle1++; 00376 00377 } 00378 }
Generated on Wed Jul 20 2022 20:10:25 by
1.7.2