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.

Committer:
Aleksk
Date:
Fri May 01 11:41:23 2020 +0000
Revision:
0:f2aaa8c6decf
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?

UserRevisionLine numberNew 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 }