The values of the EEPROM2 settings are displayed in pc.print in a special line with the current diagnostic data. An additional block has been made in the parser for decoding incoming alarm settings; they are written in EEPROM2.
main.cpp@0:f2aaa8c6decf, 2020-05-01 (annotated)
- Committer:
- Aleksk
- Date:
- Fri May 01 11:41:23 2020 +0000
- Revision:
- 0:f2aaa8c6decf
- Child:
- 1:1d4ec28f17c4
The new parser with the FIFO buffer is very fast. You can send data every 20 ms, this does not affect the cycle time of the relay controller. CR LF line ending characters are desirable but not required.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Aleksk | 0:f2aaa8c6decf | 1 | #include "mbed.h" |
Aleksk | 0:f2aaa8c6decf | 2 | |
Aleksk | 0:f2aaa8c6decf | 3 | AnalogIn analog_value(A0); //подключение аналогового входа A0 |
Aleksk | 0:f2aaa8c6decf | 4 | DigitalOut led(LED1); |
Aleksk | 0:f2aaa8c6decf | 5 | DigitalOut digital_4(PB_5); //initialize digital pin 4 as an output (high pressure air bulb charge). |
Aleksk | 0:f2aaa8c6decf | 6 | DigitalOut digital_7(PA_8); //initialize digital pin 7 as an output. (high pressure air bulb discharge |
Aleksk | 0:f2aaa8c6decf | 7 | RawSerial pc(USBTX, USBRX, 115200); // tx, rx for F411RE in port command string |
Aleksk | 0:f2aaa8c6decf | 8 | RawSerial plotter(PA_9, PA_10, 115200); // tx, rx for F411RE out port for serial_plotter |
Aleksk | 0:f2aaa8c6decf | 9 | EventQueue *queue = mbed_event_queue(); //инициализация очереди событий RTOS mbed5 |
Aleksk | 0:f2aaa8c6decf | 10 | Timer timer; //инициализация таймера |
Aleksk | 0:f2aaa8c6decf | 11 | |
Aleksk | 0:f2aaa8c6decf | 12 | int flag_autoset = 0; //отладочный флаг. При 0 - запрет автоуставки давления, при 1 - разрешение |
Aleksk | 0:f2aaa8c6decf | 13 | int flag_plotter = 0; //отладочный флаг. При 0 - запрет печати в плоттер, при 1 - разрешение |
Aleksk | 0:f2aaa8c6decf | 14 | int value = 0; //set begin value "pressure" |
Aleksk | 0:f2aaa8c6decf | 15 | int delta_value = 0; //set delta pressure |
Aleksk | 0:f2aaa8c6decf | 16 | int value_auto=250 ; //set begin value auto "pressure" |
Aleksk | 0:f2aaa8c6decf | 17 | int sensor_value =0; //напряжение с аналогового входа А0 (текущее давление) |
Aleksk | 0:f2aaa8c6decf | 18 | int counter_cycle1 = 0; |
Aleksk | 0:f2aaa8c6decf | 19 | int counter_cycle2 = 0; |
Aleksk | 0:f2aaa8c6decf | 20 | int sig = 1; //знак инкримента для автоустаки |
Aleksk | 0:f2aaa8c6decf | 21 | // FIFO_buffer must be full (only char and '\0') |
Aleksk | 0:f2aaa8c6decf | 22 | //#define maxnsym 24 // maximum nbr of symbols FIFO_buffer (вариант без символов окончания) |
Aleksk | 0:f2aaa8c6decf | 23 | #define maxnsym 26 // maximum nbr of symbols FIFO_buffer +CR+LF (символы окончания должны быть включены на передаче) |
Aleksk | 0:f2aaa8c6decf | 24 | char Source[maxnsym]="$press,1000,25,0,0,2050**"; //23 char- string ,весь массив со строкой для поиска 23+1(null terminal)=24 |
Aleksk | 0:f2aaa8c6decf | 25 | //уставки и контрольная сумма умноженная на два, должны быть больше нуля |
Aleksk | 0:f2aaa8c6decf | 26 | char trueSource[maxnsym]; //верифицированная строка для callback |
Aleksk | 0:f2aaa8c6decf | 27 | |
Aleksk | 0:f2aaa8c6decf | 28 | volatile char chr_a; //в прерываниях переменные должны быть защищены при помощи volatile от оптимизации компилятором |
Aleksk | 0:f2aaa8c6decf | 29 | volatile bool flag_comand_detected = false; //если строка декодирована правильно то true |
Aleksk | 0:f2aaa8c6decf | 30 | |
Aleksk | 0:f2aaa8c6decf | 31 | //______________________________________________________________________________ |
Aleksk | 0:f2aaa8c6decf | 32 | void substring(char *s,char *d,int pos,int len) { |
Aleksk | 0:f2aaa8c6decf | 33 | //usage: substring(Source,Destination,pos,len); |
Aleksk | 0:f2aaa8c6decf | 34 | char *t; |
Aleksk | 0:f2aaa8c6decf | 35 | s=s+(pos-1); |
Aleksk | 0:f2aaa8c6decf | 36 | t=s+len; |
Aleksk | 0:f2aaa8c6decf | 37 | while (s!=t) { |
Aleksk | 0:f2aaa8c6decf | 38 | *d=*s; |
Aleksk | 0:f2aaa8c6decf | 39 | s++; |
Aleksk | 0:f2aaa8c6decf | 40 | d++; |
Aleksk | 0:f2aaa8c6decf | 41 | } |
Aleksk | 0:f2aaa8c6decf | 42 | *d='\0'; |
Aleksk | 0:f2aaa8c6decf | 43 | } |
Aleksk | 0:f2aaa8c6decf | 44 | //______________________________________________________________________________ |
Aleksk | 0:f2aaa8c6decf | 45 | void onDataReceived(); // callback |
Aleksk | 0:f2aaa8c6decf | 46 | //______________________________________________________________________________ |
Aleksk | 0:f2aaa8c6decf | 47 | void read_serial(void) { |
Aleksk | 0:f2aaa8c6decf | 48 | char Destination[50]; |
Aleksk | 0:f2aaa8c6decf | 49 | int pos,len; |
Aleksk | 0:f2aaa8c6decf | 50 | int controlSum1, controlSum2; |
Aleksk | 0:f2aaa8c6decf | 51 | int value_, delta_value_, flag_autoset_, flag_plotter_; |
Aleksk | 0:f2aaa8c6decf | 52 | int ch = '$'; // Код искомого символа |
Aleksk | 0:f2aaa8c6decf | 53 | int indexCh; // Char on position |
Aleksk | 0:f2aaa8c6decf | 54 | char *ach; // Указатель на искомую переменную в строке, по которой осуществляется поиск. |
Aleksk | 0:f2aaa8c6decf | 55 | while(pc.readable()) { |
Aleksk | 0:f2aaa8c6decf | 56 | chr_a = pc.getc(); |
Aleksk | 0:f2aaa8c6decf | 57 | //_____FIFO_buffer_begin_____ |
Aleksk | 0:f2aaa8c6decf | 58 | for ( int i = 2; i < maxnsym; i++) { |
Aleksk | 0:f2aaa8c6decf | 59 | Source[i-2]=Source[i-1]; |
Aleksk | 0:f2aaa8c6decf | 60 | } |
Aleksk | 0:f2aaa8c6decf | 61 | Source[maxnsym-2]=chr_a; //предпоследний элемент |
Aleksk | 0:f2aaa8c6decf | 62 | Source[maxnsym-1] ='\0'; //последний элемент массива это нуль-терминал для формирования конца строки в Си |
Aleksk | 0:f2aaa8c6decf | 63 | //_____FIFO_buffer_end_______ |
Aleksk | 0:f2aaa8c6decf | 64 | } |
Aleksk | 0:f2aaa8c6decf | 65 | ach=strchr (Source,ch); //поиск первого вхождения символа в строку , ищем указатель символа ‘$’ |
Aleksk | 0:f2aaa8c6decf | 66 | if (ach==NULL) { |
Aleksk | 0:f2aaa8c6decf | 67 | //pc.printf ("Char not finded \r\n"); //Символ $ в строке не найден |
Aleksk | 0:f2aaa8c6decf | 68 | goto endParsing; //пропускаем парсинг |
Aleksk | 0:f2aaa8c6decf | 69 | } |
Aleksk | 0:f2aaa8c6decf | 70 | else { |
Aleksk | 0:f2aaa8c6decf | 71 | indexCh = ach-Source+1; //вычитаем указатель из указателя! |
Aleksk | 0:f2aaa8c6decf | 72 | //pc.printf ("Char '$' on position %d\r\n",indexCh); //Искомый символ в строке на позиции |
Aleksk | 0:f2aaa8c6decf | 73 | } |
Aleksk | 0:f2aaa8c6decf | 74 | if (indexCh!=1) { //позиция символа $ не 1 |
Aleksk | 0:f2aaa8c6decf | 75 | //pc.printf ("$ position not 1 \r\n"); |
Aleksk | 0:f2aaa8c6decf | 76 | goto endParsing; //пропускаем парсинг |
Aleksk | 0:f2aaa8c6decf | 77 | } |
Aleksk | 0:f2aaa8c6decf | 78 | |
Aleksk | 0:f2aaa8c6decf | 79 | pos=1; //начало подстроки $press - на 1 позиции |
Aleksk | 0:f2aaa8c6decf | 80 | len=6; //длина подстроки $press равна 6 |
Aleksk | 0:f2aaa8c6decf | 81 | substring(Source,Destination,pos,len); |
Aleksk | 0:f2aaa8c6decf | 82 | //pc.printf("for pos=%d and len=%d resultat is d= %s\r\n", pos, len, Destination); |
Aleksk | 0:f2aaa8c6decf | 83 | |
Aleksk | 0:f2aaa8c6decf | 84 | if (strcmp(Destination,"$press" ) != 0) { //функция возвращает ноль если строки совпадают |
Aleksk | 0:f2aaa8c6decf | 85 | //pc.printf("wrong Destination=%s\r\n",Destination); //печать "неправильной" нулевой строки |
Aleksk | 0:f2aaa8c6decf | 86 | goto endParsing ; //в начале сообщения нет $press пропускаем парсинг |
Aleksk | 0:f2aaa8c6decf | 87 | } |
Aleksk | 0:f2aaa8c6decf | 88 | pos=8; //начало подстроки 1000 - на 8 позиции |
Aleksk | 0:f2aaa8c6decf | 89 | len=4; //длина подстроки 1000 равна 4 |
Aleksk | 0:f2aaa8c6decf | 90 | substring(Source,Destination,pos,len); |
Aleksk | 0:f2aaa8c6decf | 91 | value_=atoi(Destination); |
Aleksk | 0:f2aaa8c6decf | 92 | if (value_==0) { |
Aleksk | 0:f2aaa8c6decf | 93 | goto endParsing; //уставка должна быть больше еденицы, пропускаем парсинг |
Aleksk | 0:f2aaa8c6decf | 94 | } |
Aleksk | 0:f2aaa8c6decf | 95 | //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, value_); |
Aleksk | 0:f2aaa8c6decf | 96 | pos=13; //начало подстроки 25 - на 13 позиции |
Aleksk | 0:f2aaa8c6decf | 97 | len=2; //длина подстроки 25 равна 2 |
Aleksk | 0:f2aaa8c6decf | 98 | substring(Source,Destination,pos,len); |
Aleksk | 0:f2aaa8c6decf | 99 | delta_value_=atoi(Destination); |
Aleksk | 0:f2aaa8c6decf | 100 | if (delta_value_==0) { |
Aleksk | 0:f2aaa8c6decf | 101 | goto endParsing; //уставка отклонения должна быть больше еденицы, пропускаем парсинг |
Aleksk | 0:f2aaa8c6decf | 102 | } |
Aleksk | 0:f2aaa8c6decf | 103 | //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, delta_value_); |
Aleksk | 0:f2aaa8c6decf | 104 | pos=16; //начало подстроки 0 - на 16 позиции |
Aleksk | 0:f2aaa8c6decf | 105 | len=1; //длина подстроки 0 равна 1 |
Aleksk | 0:f2aaa8c6decf | 106 | substring(Source,Destination,pos,len); |
Aleksk | 0:f2aaa8c6decf | 107 | flag_autoset_=atoi(Destination); |
Aleksk | 0:f2aaa8c6decf | 108 | //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_autoset_); |
Aleksk | 0:f2aaa8c6decf | 109 | pos=18; //начало подстроки 0 - на 18 позиции |
Aleksk | 0:f2aaa8c6decf | 110 | len=1; //длина подстроки 0 равна 1 |
Aleksk | 0:f2aaa8c6decf | 111 | substring(Source,Destination,pos,len); |
Aleksk | 0:f2aaa8c6decf | 112 | flag_plotter_=atoi(Destination); |
Aleksk | 0:f2aaa8c6decf | 113 | //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_plotter_); |
Aleksk | 0:f2aaa8c6decf | 114 | pos=20; //начало подстроки 1025 - на 18 позиции |
Aleksk | 0:f2aaa8c6decf | 115 | len=4; //длина подстроки 1025 равна 4 |
Aleksk | 0:f2aaa8c6decf | 116 | substring(Source,Destination,pos,len); |
Aleksk | 0:f2aaa8c6decf | 117 | controlSum1=atoi(Destination); |
Aleksk | 0:f2aaa8c6decf | 118 | if (controlSum1==0) { |
Aleksk | 0:f2aaa8c6decf | 119 | goto endParsing; //контрольная сумма должна быть больше еденицы, пропускаем парсинг |
Aleksk | 0:f2aaa8c6decf | 120 | } |
Aleksk | 0:f2aaa8c6decf | 121 | //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, controlSum1); |
Aleksk | 0:f2aaa8c6decf | 122 | controlSum2=(value_+delta_value_+flag_autoset_+flag_plotter_)*2; //удвоение чтобы не было одинаковых чисел в сообщении |
Aleksk | 0:f2aaa8c6decf | 123 | //pc.printf("controlSum1=%d controlSum2=%d\r\n", controlSum1, controlSum2); |
Aleksk | 0:f2aaa8c6decf | 124 | if (controlSum1!=controlSum2) { //не совпала контрольная сумма |
Aleksk | 0:f2aaa8c6decf | 125 | //pc.printf ("controlSum1!=controlSum2 \r\n"); |
Aleksk | 0:f2aaa8c6decf | 126 | goto endParsing; //пропускаем парсинг |
Aleksk | 0:f2aaa8c6decf | 127 | } |
Aleksk | 0:f2aaa8c6decf | 128 | //присваиваем проверенные значения глобальным переменным |
Aleksk | 0:f2aaa8c6decf | 129 | strcpy(trueSource,Source); //копировать из Source в trueSource |
Aleksk | 0:f2aaa8c6decf | 130 | value=value_; |
Aleksk | 0:f2aaa8c6decf | 131 | delta_value=delta_value_; |
Aleksk | 0:f2aaa8c6decf | 132 | flag_autoset=flag_autoset_; |
Aleksk | 0:f2aaa8c6decf | 133 | flag_plotter=flag_plotter_; |
Aleksk | 0:f2aaa8c6decf | 134 | flag_comand_detected=true; //если флаг true, то всем переменным присвоены новые значения уставок |
Aleksk | 0:f2aaa8c6decf | 135 | |
Aleksk | 0:f2aaa8c6decf | 136 | endParsing: |
Aleksk | 0:f2aaa8c6decf | 137 | |
Aleksk | 0:f2aaa8c6decf | 138 | |
Aleksk | 0:f2aaa8c6decf | 139 | pc.attach(&onDataReceived, Serial::RxIrq); // reattach interrupt - переподключение прерывания перед выходом из функции |
Aleksk | 0:f2aaa8c6decf | 140 | } |
Aleksk | 0:f2aaa8c6decf | 141 | //______________________________________________________________________________ |
Aleksk | 0:f2aaa8c6decf | 142 | void onDataReceived() { |
Aleksk | 0:f2aaa8c6decf | 143 | pc.attach(nullptr, Serial::RxIrq); // detach interrupt |
Aleksk | 0:f2aaa8c6decf | 144 | queue->call(read_serial); // process in a non ISR context - переход к функции приема строки - |
Aleksk | 0:f2aaa8c6decf | 145 | } // - в статусе отключенного прерывания (учим указатели!) |
Aleksk | 0:f2aaa8c6decf | 146 | //______________________________________________________________________________ |
Aleksk | 0:f2aaa8c6decf | 147 | void auto_set () { |
Aleksk | 0:f2aaa8c6decf | 148 | if (counter_cycle2 >= 100 && flag_autoset == 1) { |
Aleksk | 0:f2aaa8c6decf | 149 | counter_cycle2=0; |
Aleksk | 0:f2aaa8c6decf | 150 | if (value_auto > 2800 || value_auto < 250) { |
Aleksk | 0:f2aaa8c6decf | 151 | sig = -sig; //меняем знак для изменения направления роста/спада автоуставки |
Aleksk | 0:f2aaa8c6decf | 152 | } |
Aleksk | 0:f2aaa8c6decf | 153 | value_auto = value_auto + sig * 250; |
Aleksk | 0:f2aaa8c6decf | 154 | value=value_auto; |
Aleksk | 0:f2aaa8c6decf | 155 | } |
Aleksk | 0:f2aaa8c6decf | 156 | counter_cycle2++; //увеличиваем счетчик функции auto_set() на 1 |
Aleksk | 0:f2aaa8c6decf | 157 | } |
Aleksk | 0:f2aaa8c6decf | 158 | //***************************************************************************** |
Aleksk | 0:f2aaa8c6decf | 159 | //***************************************************************************** |
Aleksk | 0:f2aaa8c6decf | 160 | |
Aleksk | 0:f2aaa8c6decf | 161 | int main() { |
Aleksk | 0:f2aaa8c6decf | 162 | pc.printf("program started \r\n"); |
Aleksk | 0:f2aaa8c6decf | 163 | pc.attach(&onDataReceived, Serial::RxIrq); |
Aleksk | 0:f2aaa8c6decf | 164 | int time, valve1, valve2, countValve1=0, countValve2=0; |
Aleksk | 0:f2aaa8c6decf | 165 | int frequencyValve1, frequencyValve2; |
Aleksk | 0:f2aaa8c6decf | 166 | float raw_value_sum = 0 ; |
Aleksk | 0:f2aaa8c6decf | 167 | timer.start(); |
Aleksk | 0:f2aaa8c6decf | 168 | while (true){ //бесконечный цикл |
Aleksk | 0:f2aaa8c6decf | 169 | |
Aleksk | 0:f2aaa8c6decf | 170 | if (flag_comand_detected) { |
Aleksk | 0:f2aaa8c6decf | 171 | pc.printf("$press,%d,%d,%d,%d,%d\r\n", |
Aleksk | 0:f2aaa8c6decf | 172 | value,delta_value,flag_autoset,flag_plotter,sensor_value); //текущие данные |
Aleksk | 0:f2aaa8c6decf | 173 | //pc.printf("%s\r\n",trueSource); //эхо для отладки канала связи |
Aleksk | 0:f2aaa8c6decf | 174 | flag_comand_detected=false; //в последующих обращениях не печатать пока нет новых уставок из СОМ-порта |
Aleksk | 0:f2aaa8c6decf | 175 | //plotter.printf("$%d %d %d %d %d;\r\n", digital_4.read()*100-110, |
Aleksk | 0:f2aaa8c6decf | 176 | // digital_7.read()*100-220, value, sensor_value, time ); //печать в плоттер в другой СОМ-порт |
Aleksk | 0:f2aaa8c6decf | 177 | } |
Aleksk | 0:f2aaa8c6decf | 178 | float raw_value = analog_value.read(); // Чтение аналогового входа (0.0 to 1.0 = full ADC диапазон) |
Aleksk | 0:f2aaa8c6decf | 179 | raw_value_sum = raw_value_sum + raw_value; |
Aleksk | 0:f2aaa8c6decf | 180 | |
Aleksk | 0:f2aaa8c6decf | 181 | if (counter_cycle1 > 20 ) { |
Aleksk | 0:f2aaa8c6decf | 182 | counter_cycle1=0; |
Aleksk | 0:f2aaa8c6decf | 183 | sensor_value = raw_value_sum/20 * 3300; // преобразование в напряжение 0-3300 mV с усреднением |
Aleksk | 0:f2aaa8c6decf | 184 | raw_value_sum = 0 ; |
Aleksk | 0:f2aaa8c6decf | 185 | //--------------regulator begin----------------------- |
Aleksk | 0:f2aaa8c6decf | 186 | if (sensor_value > value + delta_value) { |
Aleksk | 0:f2aaa8c6decf | 187 | valve2 = digital_7.read(); |
Aleksk | 0:f2aaa8c6decf | 188 | digital_7.write(1); //valve2 = 1; |
Aleksk | 0:f2aaa8c6decf | 189 | if (valve2 < digital_7.read()) {countValve2++;} //счётчик передних фронтов напряжения (срабатывания клапана 2) |
Aleksk | 0:f2aaa8c6decf | 190 | digital_4.write(0); //valve1 = 0; |
Aleksk | 0:f2aaa8c6decf | 191 | } else if (sensor_value < value - delta_value) { |
Aleksk | 0:f2aaa8c6decf | 192 | valve1 = digital_4.read(); |
Aleksk | 0:f2aaa8c6decf | 193 | digital_4.write(1); //valve1 = 1; |
Aleksk | 0:f2aaa8c6decf | 194 | if (valve1 < digital_4.read()) {countValve1++;} //счётчик передних фронтов напряжения (срабатывания клапана 1) |
Aleksk | 0:f2aaa8c6decf | 195 | digital_7.write(0); //valve2 = 0; |
Aleksk | 0:f2aaa8c6decf | 196 | } else { |
Aleksk | 0:f2aaa8c6decf | 197 | digital_4.write(0); //valve1 = 0; |
Aleksk | 0:f2aaa8c6decf | 198 | digital_7.write(0); //valve2 = 0; |
Aleksk | 0:f2aaa8c6decf | 199 | } |
Aleksk | 0:f2aaa8c6decf | 200 | //--------------regulator end------------------------- |
Aleksk | 0:f2aaa8c6decf | 201 | time=timer.read_us(); |
Aleksk | 0:f2aaa8c6decf | 202 | if (time > 1000000) { |
Aleksk | 0:f2aaa8c6decf | 203 | timer.reset(); //начало счёта времени |
Aleksk | 0:f2aaa8c6decf | 204 | frequencyValve1 = countValve1; //частота (Гц) срабатывания клапана 1 |
Aleksk | 0:f2aaa8c6decf | 205 | frequencyValve2 = countValve2; //частота (Гц) срабатывания клапана 2 |
Aleksk | 0:f2aaa8c6decf | 206 | countValve1=0; |
Aleksk | 0:f2aaa8c6decf | 207 | countValve2=0; |
Aleksk | 0:f2aaa8c6decf | 208 | } |
Aleksk | 0:f2aaa8c6decf | 209 | |
Aleksk | 0:f2aaa8c6decf | 210 | if (flag_plotter == 1) { |
Aleksk | 0:f2aaa8c6decf | 211 | plotter.printf("$%d %d %d %d %d %d;\r\n", digital_4.read()*100-110, |
Aleksk | 0:f2aaa8c6decf | 212 | digital_7.read()*100-220, value, sensor_value, 100*frequencyValve1, 100*frequencyValve2 ); //печать в плоттер в другой СОМ-порт (только для отладки) |
Aleksk | 0:f2aaa8c6decf | 213 | } |
Aleksk | 0:f2aaa8c6decf | 214 | |
Aleksk | 0:f2aaa8c6decf | 215 | auto_set(); //Ступенчатое увеличение и уменьшение уставки value (для отладки если flag_autoset =1) |
Aleksk | 0:f2aaa8c6decf | 216 | led = !led; //гасим/зажигаем индикаторный светодиод |
Aleksk | 0:f2aaa8c6decf | 217 | } |
Aleksk | 0:f2aaa8c6decf | 218 | ThisThread::sleep_for(1); // (mc) правильный оператор задержки для mbed5 |
Aleksk | 0:f2aaa8c6decf | 219 | counter_cycle1++; |
Aleksk | 0:f2aaa8c6decf | 220 | |
Aleksk | 0:f2aaa8c6decf | 221 | } |
Aleksk | 0:f2aaa8c6decf | 222 | } |