Alex K / Mbed OS mbed-os5-press_7

Dependencies:   _24LCXXX

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }