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.
Revision 4:305dc62186e8, committed 2020-04-24
- Comitter:
- Aleksk
- Date:
- Fri Apr 24 16:31:28 2020 +0000
- Parent:
- 3:285d45a0d928
- Commit message:
- The relay controller. $press, 1000,25,0,1 - for example, the following are transmitted: $ - service symbol, 1000 - pressure setpoint, 25 - delta pressure , 0 - auto-set flag OFF, 1- flag serial plotter ON .; Add protection from random input string.
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/main.cpp Fri Apr 17 13:27:48 2020 +0000 +++ b/main.cpp Fri Apr 24 16:31:28 2020 +0000 @@ -1,116 +1,163 @@ #include "mbed.h" -//17.04.2020 15:30 +//24.04.2020 11:53 //Программа для пошагового чтения байтов из последовательного порта и разделения потока байтов на подстроки в реальном времени. Разделитель - запятая. //Строка сообщения должна заканчиваться только одним символом /r или /n (обнаружение признака окончания сообщения можно сделать любым) //Программа нормально разбивает принимаемую строку на подстроки (до 20) в количестве равном количеству запятых, плюс последняя подстрока без запятой. //Регулятор релейного типа отлажен на RC-эмуляторе сосуда с двумя клапанами. Давление здесь измеряется в милливольтах. -//$,1000,25,0 - для примера здесь передаются:$ - служебный символ, 1000 - уставка давления, 25 - уставка погрешности давления, 0 - флаг запрета работы автоуставки - -AnalogIn analog_value(A0); //подключение аналогового входа A0 +//$press,1000,25,0,0 - для примера здесь передаются: +//$press - идентификатор строки, 1000 - уставка давления, 25 - уставка погрешности давления, 0 - флаг запрета автоуставки, 0 - флаг запрета печати плоттера + +AnalogIn analog_value(A0); //подключение аналогового входа A0 DigitalOut led(LED1); -DigitalOut digitalWrite4(PB_5); // initialize digital pin 4 as an output (high pressure air bulb charge). -DigitalOut digitalWrite7(PA_8); // initialize digital pin 7 as an output. (high pressure air bulb discharge -RawSerial pc(USBTX, USBRX, 115200); +DigitalOut digital_4(PB_5); //initialize digital pin 4 as an output (high pressure air bulb charge). +DigitalOut digital_7(PA_8); //initialize digital pin 7 as an output. (high pressure air bulb discharge +RawSerial pc(USBTX, USBRX, 115200); // tx, rx for F411RE in port command string +RawSerial plotter(PA_9, PA_10, 115200); // tx, rx for F411RE out port for serial_plotter +//Serial pc(PA_9,PA_10); // tx, rx for F091RC out port diagnostica +//Serial plotter(PC_10,PC_11); // tx, rx for F091RC in port command string + EventQueue *queue = mbed_event_queue(); //инициализация очереди событий RTOS mbed5 +Timer timer; #define maxnstr 20 // maximum nbr of params(sybstrings) used to hold the data fields #define maxnsym 20 // maximum nbr of symbols -char comand[maxnstr][maxnsym]={""}; // -int nstr=0; //номер строки - -int pressure=0; //давление (аналоговый вход) (резерв) -int pressure_set=0; //уставка давления (резерв) -int pressure_set_max=0; //уставка максимальног давления (резерв) -int flag_autoset=1; //отладочный флаг. При 0 - запрет автоуставки давления, при 1 - разрешение -int value=1000; //set "pressure" -int delta_value=25; //set delta pressure -int counter_cycle1=0; -int counter_cycle2=0; -int sig=1; //знак инкримента для автоустаки -int valve1=0; // state valve of charge: 0 - close, 1 - open -int valve2=0; //state valve of discharge: 0 - close, 1 - open - +char comand[maxnstr][maxnsym] = {""}; // массив подстрок командной строки +int nstr = 0; // номер подстроки + +int pressure = 0; //давление (аналоговый вход) (резерв) +int pressure_set = 0; //уставка давления (резерв) +int pressure_set_max = 0; //уставка максимальног давления (резерв) +int flag_autoset = 0; //отладочный флаг. При 0 - запрет автоуставки давления, при 1 - разрешение +int flag_plotter = 0; //отладочный флаг. При 0 - запрет печати в плоттер, при 1 - разрешение +int value = 1000; //set begin value "pressure" +int value_auto=250 ; //set begin value auto "pressure" +int sensor_value =0; //напряжение с аналогового входа А0 (текущее давление) +int delta_value = 25; //set delta pressure +int counter_cycle1 = 0; +int counter_cycle2 = 0; +int sig = 1; //знак инкримента для автоустаки +int valve1 = 0; // state valve of charge: 0 - close, 1 - open +int valve2 = 0; //state valve of discharge: 0 - close, 1 - open + //______________________________________________________________________________ void onDataReceived(); // callback //______________________________________________________________________________ void read_serial() { - char message[maxnstr][maxnsym]={""}; //обнуление строк (локального двумерного массива символов фиксированного размера) - int zap=0; // счетчик запятых + int time; + timer.reset(); + char message[maxnstr][maxnsym]={""}; //обнуление строк (локального двумерного массива символов фиксированного размера) char chr; //байтовый символ полученный из порта (или файла) nstr=0; //обнуление счетчика строк (на самом деле счетчика запятых в сообщении) rs1: int string_possition=0; //обнуляем номер символа (в строке) в массиве входящей строки сообщения - do{ chr = pc.getc(); //вынимаем символ из буфера последовательного порта - if (chr == ',') //запятая в нашей системе сообщений это признак окончания подстроки - {zap++; - message[nstr][string_possition] ='\0'; //дополняем подстроку символом окончания строки - nstr++; //стетчик строк увеличиваем на единицу - goto rs1; } //выходим в начало цикла для поиска следующей подстроки - if (chr == '\n' || chr == '\r'){message[nstr][string_possition] ='\0';break;} //если сообщение кончилось, то вставка окончания строки и выход из цикла - message[nstr][string_possition] = chr; //складываем символы в подстроку + do{ + + chr = pc.getc(); //вынимаем символ из буфера последовательного порта + if (chr == ',') { //запятая в нашей системе сообщений это признак окончания подстроки + message[nstr][string_possition] ='\0'; //дополняем подстроку символом окончания строки + nstr++; //стетчик подстрок увеличиваем на единицу + if (nstr >= maxnstr) { + goto rs2; //количество подстрок больше maxnstr, игнорируем сообщение и выходим в конец + } + goto rs1; //выходим в начало цикла для поиска следующей подстроки + } + if (chr == '\n' ){ + message[nstr][string_possition] ='\0'; + break; //если сообщение кончилось, то вставка окончания строки и выход из цикла + } + message[nstr][string_possition] = chr; //складываем символы в подстроку string_possition++; //номер позиции символа увеличиваем на единицу - }while (1); - // pc.printf("caught message_nstr is : %s\r\n", message[nstr]); //последняя подстрока пойманного сообщения - // pc.printf("****Detect number of _,_ ****=%d\r\n",zap); //количество приянтых запятых - for (int i=0; i<=nstr; i++) {strcpy(comand[i],message[i]);} //копирование строк в глобальный массив , размеры массивов должны совпадать! - for (int i=0; i<=nstr; i++) {pc.printf("Caught comand[%d] is : %s\r\n",i,comand[i]);} //печать подстрок пойманного сообщения - value=atoi(comand[1]); // перевод из строчного массива (вторая подстрока сообщения) в целое число (уставка давления) + if (string_possition > maxnsym) { + goto rs2; //количество символов больше maxnsym, игнорируем сообщение и выходим в конец + } + time=timer.read_us(); + if (time > 100000) { + //if(pc.readable()) { //работает только для одного (первого) принятого символа + pc.putc('>'); // overtime detected - callback to terminal + //} + goto rs2; //за 100 мс не обнаружен конец сообщения, игнорируем сообщение и выходим в конец + } //обычно время не превышает 1540мкс для сообщения $press,1000,25,0,0 + }while (true); + if (strcmp(message[0],"$press" ) != 0) { //функция возвращает ноль если строки совпадают, т.е. если нулевая строка равна "$" + pc.printf("message[0]=%s\r\n",message[0]); //печать "неправильной" нулевой строки + goto rs2 ; //в начале сообщения нет $ поэтому пропускаем обработку и выходим в конец + } + for (int i=0; i<=nstr; i++) {strcpy(comand[i],message[i]);} //копирование строк в глобальный массив , размеры массивов должны совпадать! + for (int i=0; i<nstr; i++) { pc.printf("%s,",comand[i]);} //эхо принятого сообщения (начало) + pc.printf("%s\r\n",comand[nstr]); //эхо принятого сообщения (конец) + pc.printf("sensor_value=%d\r\n",sensor_value); + // for (int i=0; i<=nstr; i++) { + // pc.printf("Caught comand[%d] is : %s\r\n",i,comand[i]); //отладочная печать подстрок пойманного сообщения + // } + pc.printf("time=%d\r\n",time); + value=atoi(comand[1]); // перевод из строчного массива в целое число (уставка давления) pc.printf("value=%d\r\n",value); - delta_value=atoi(comand[2]); // перевод из строчного массива (третья подстрока сообщения) в целое число (уставка отклонения давления) + delta_value=atoi(comand[2]); // перевод из строчного массива в целое число (уставка отклонения давления) pc.printf("delta_value=%d\r\n",delta_value); - flag_autoset=atoi(comand[3]); // перевод из строчного массива (четвёртая подстрока сообщения) в целое число (флаг автоуставки ) + flag_autoset=atoi(comand[3]); // перевод из строчного массива в целое число (флаг автоуставки ) pc.printf("flag_autoset=%d\r\n",flag_autoset); - + flag_plotter=atoi(comand[4]); // перевод из строчного массива в целое число (флаг плоттера ) + pc.printf("flag_plotter=%d\r\n",flag_plotter); +rs2: pc.attach(&onDataReceived, Serial::RxIrq); // reattach interrupt - переподключение прерывания перед выходом из функции } //______________________________________________________________________________ void onDataReceived() { - pc.attach(NULL, Serial::RxIrq); // detach interrupt - queue->call(read_serial); // process in a non ISR context - переход к функции приема строки в статусе отключенного прерывания (учим указатели!) + pc.attach(nullptr, Serial::RxIrq); // detach interrupt + queue->call(read_serial); // process in a non ISR context - переход к функции приема строки - +} // - в статусе отключенного прерывания (учим указатели!) +//______________________________________________________________________________ +void auto_set () { + if (counter_cycle2 >= 100 && flag_autoset == 1) { + counter_cycle2=0; + if (value_auto > 2800 || value_auto < 250) { + sig = -sig; //меняем знак для изменения направления роста/спада автоуставки + } + value_auto = value_auto + sig * 250; + value=value_auto; + } + counter_cycle2++; //увеличиваем счетчик функции auto_set() на 1 } //***************************************************************************** //***************************************************************************** -int main() -{ - pc.attach(&onDataReceived, Serial::RxIrq); //подключение прерывания и имя функции обработчика прерывания по входящему символу в serial порту - float raw_value ; - int sensor_value ; - printf("Start \r\n"); - while (1) //бесконечный цикл - { +int main() { + pc.attach(&onDataReceived, Serial::RxIrq); //подключение прерывания и имя функции обработчика прерывания по входящему символу в serial + + timer.start(); + float raw_value_sum = 0 ; + printf ("Start \r\n"); + while (true){ //бесконечный цикл + float raw_value = analog_value.read(); // Чтение аналогового входа (0.0 to 1.0 = full ADC диапазон) + raw_value_sum = raw_value_sum + raw_value; - /*--------------regulator begin---*/ - raw_value = analog_value.read(); // Чтение аналогового входа (0.0 to 1.0 = full ADC диапазон) - sensor_value = raw_value * 3300; // преобразование в напряжение 0-3300 mV - if (sensor_value>value+delta_value) - { - digitalWrite7=1; valve2=1; - digitalWrite4=0; valve1=0; - } else if (sensor_value<value-delta_value) - { - digitalWrite4=1; valve1=1; - digitalWrite7=0; valve2=0; - } else - { - digitalWrite4=0; valve1=0; - digitalWrite7=0; valve2=0; + if (counter_cycle1 > 20 ) { + counter_cycle1=0; + sensor_value = raw_value_sum/20 * 3300; // преобразование в напряжение 0-3300 mV с усреднением + // sensor_value = raw_value * 3300; // преобразование в напряжение 0-3300 mV без усреднения + raw_value_sum = 0 ; + //--------------regulator begin----------------------- + if (sensor_value > value + delta_value) { + digital_7.write(1); //valve2 = 1; + digital_4.write(0); //valve1 = 0; + } else if (sensor_value < value - delta_value) { + digital_4.write(1); //valve1 = 1; + digital_7.write(0); //valve2 = 0; + } else { + digital_4.write(0); //valve1 = 0; + digital_7.write(0); //valve2 = 0; + } + //--------------regulator end------------------------- + + if (flag_plotter == 1) { + plotter.printf("$%d %d %d %d;\r\n", digital_4.read()*100-110, + digital_7.read()*100-220, value, sensor_value ); //печать в плоттер (только для отладки! т.к. влияет на парсинг) + } + + auto_set(); //Ступенчатое увеличение и уменьшение уставки value (для отладки если flag_autoset =1) + led = !led; //гасим/зажигаем индикаторный светодиод + } + ThisThread::sleep_for(1); // (mc) правильный оператор задержки для mbed5 + counter_cycle1++; + } - /*--------------regulator end-----*/ - - pc.printf("$%d %d %d %d;\r\n", valve1*100-110, valve2*100-220, value, sensor_value ); - - //* Ступенчатое увеличение и уменьшение уставки value (для отладки) - if (counter_cycle2>=100 && flag_autoset==1) { - counter_cycle2=0; - if(value>2800 || value<250){ - sig=-sig; //меняем знак для изменения направления роста/спада автоуставки - } - value=value+sig*250; - } - //*/ - ThisThread::sleep_for(20); // (mc) правильный оператор задержки для mbed5 - led = !led; //гасим/зажигаем индикаторный светодиод - counter_cycle1=0; - counter_cycle2++; //увеличиваем счетчик на 1 - } } \ No newline at end of file