Alex K
/
mbed-os5-press_23
On the i2c bus, Arduino Nano with address 2, transmits the weight value with a resolution of 1 kg.
main.cpp
- Committer:
- Aleksk
- Date:
- 2020-05-15
- Revision:
- 3:712f751b4974
- Parent:
- 2:8230a5a4cc13
- Child:
- 4:c34b84bfa2fb
File content as of revision 3:712f751b4974:
// Продолжение (клон )mbed-os5-inerrupt_serial_readable_FIFO_12 // Подключена EEPROM. Теперь уставки извлекаются из неё при перезагрузке. // Создан сторожевой таймер, который истекает через 100мс #include "mbed.h" #include "_24LCXXX.h" I2C i2c(PB_9,PB_8); // sda, scl _24LCXXX eeprom(&i2c, 0x50); AnalogIn analog_value(A0); //подключение аналогового входа A0 DigitalOut led(LED1); 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 EventQueue *queue = mbed_event_queue(); //инициализация очереди событий RTOS mbed5 Timer timer; //инициализация таймера //========УСТАВКИ======== uint8_t flag_autoset = 0; //отладочный флаг. При 0 - запрет автоуставки давления, при 1 - разрешение uint8_t flag_plotter = 0; //отладочный флаг. При 0 - запрет печати в плоттер, при 1 - разрешение int value = 0; //set begin value "pressure" 1...3300 uint8_t delta_value = 0; //set delta pressure 1...99 //======================= int value_auto=250 ; //set begin value auto "pressure" int sensor_value =0; //напряжение с аналогового входа А0 (текущее давление) int counter_cycle1 = 0; //счётчик цикла while(true) int counter_cycle2 = 0; //счётчик внутри функции auto_set int sig = 1; //знак инкримента для автоустаки // FIFO_buffer must be full (only char and '\0') //#define maxnsym 24 // maximum nbr of symbols FIFO_buffer (вариант без символов окончания) #define maxnsym 26 // maximum nbr of symbols FIFO_buffer +CR+LF (символы окончания должны быть включены на передаче) char Source[maxnsym]="$press,1000,25,0,0,2050**"; //23 char- string ,весь массив со строкой для поиска 23+1(null terminal)=24 //уставки и контрольная сумма умноженная на два, должны быть больше нуля char trueSource[maxnsym]; //верифицированная строка для callback char trueSourceOld[maxnsym]; //предыдущая верифицированная строка для callback volatile char chr_a; //в прерываниях переменные должны быть защищены при помощи volatile от оптимизации компилятором volatile bool flag_comand_detected = false; //если строка декодирована правильно то true volatile bool flag_stopRegulator = true; //флаг остановки , закрыть все клапана //_____________________________________________________________________________ void save_EEPROM () { int data2; pc.printf("EEPROM write------\r\n"); eeprom.byte_write(0, delta_value); eeprom.byte_write(1, flag_autoset); eeprom.byte_write(2, flag_plotter); data2 = value; eeprom.nbyte_write( 10, &data2, sizeof(int)); } //_____________________________________________________________________________ void load_EEPROM () { uint8_t data1; int data2; pc.printf("EEPROM read------\r\n"); eeprom.nbyte_read( 0, &data1, 1 ); pc.printf("adress 0 =%d \r\n",data1); delta_value=data1; eeprom.nbyte_read( 1, &data1, 1 ); pc.printf("adress 1 =%d \r\n",data1); flag_autoset=data1; eeprom.nbyte_read( 2, &data1, 1 ); pc.printf("adress 2 =%d \r\n",data1); flag_plotter=data1; eeprom.nbyte_read( 10, &data2, sizeof(int) ); pc.printf("adress 10 = %d \r\n",data2); value=data2; } //______________________________________________________________________________ void substring(char *s,char *d,int pos,int len) { //usage: substring(Source,Destination,pos,len); char *t; s=s+(pos-1); t=s+len; while (s!=t) { *d=*s; s++; d++; } *d='\0'; } //______________________________________________________________________________ void onDataReceived(); // callback //______________________________________________________________________________ void read_serial(void) { char Destination[50]; int pos,len; int controlSum1, controlSum2; int value_, delta_value_, flag_autoset_, flag_plotter_; int ch = '$'; // Код искомого символа int indexCh; // Char on position char *ach; // Указатель на искомую переменную в строке, по которой осуществляется поиск. while(pc.readable()) { chr_a = pc.getc(); //_____FIFO_buffer_begin_____ for ( int i = 2; i < maxnsym; i++) { Source[i-2]=Source[i-1]; } Source[maxnsym-2]=chr_a; //предпоследний элемент Source[maxnsym-1] ='\0'; //последний элемент массива это нуль-терминал для формирования конца строки в Си //_____FIFO_buffer_end_______ } ach=strchr (Source,ch); //поиск первого вхождения символа в строку , ищем указатель символа ‘$’ if (ach==NULL) { //pc.printf ("Char not finded \r\n"); //Символ $ в строке не найден goto endParsing; //пропускаем парсинг } else { indexCh = ach-Source+1; //вычитаем указатель из указателя! //pc.printf ("Char '$' on position %d\r\n",indexCh); //Искомый символ в строке на позиции } if (indexCh!=1) { //позиция символа $ не 1 //pc.printf ("$ position not 1 \r\n"); goto endParsing; //пропускаем парсинг } pos=1; //начало подстроки $press - на 1 позиции len=6; //длина подстроки $press равна 6 substring(Source,Destination,pos,len); //pc.printf("for pos=%d and len=%d resultat is d= %s\r\n", pos, len, Destination); if (strcmp(Destination,"$press" ) != 0) { //функция возвращает ноль если строки совпадают //pc.printf("wrong Destination=%s\r\n",Destination); //печать "неправильной" нулевой строки goto endParsing ; //в начале сообщения нет $press пропускаем парсинг } pos=8; //начало подстроки 1000 - на 8 позиции len=4; //длина подстроки 1000 равна 4 substring(Source,Destination,pos,len); value_=atoi(Destination); if (value_==0) { goto endParsing; //уставка должна быть больше еденицы, пропускаем парсинг } //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, value_); pos=13; //начало подстроки 25 - на 13 позиции len=2; //длина подстроки 25 равна 2 substring(Source,Destination,pos,len); delta_value_=atoi(Destination); if (delta_value_==0) { goto endParsing; //уставка отклонения должна быть больше еденицы, пропускаем парсинг } //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, delta_value_); pos=16; //начало подстроки 0 - на 16 позиции len=1; //длина подстроки 0 равна 1 substring(Source,Destination,pos,len); flag_autoset_=atoi(Destination); //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_autoset_); pos=18; //начало подстроки 0 - на 18 позиции len=1; //длина подстроки 0 равна 1 substring(Source,Destination,pos,len); flag_plotter_=atoi(Destination); //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, flag_plotter_); pos=20; //начало подстроки 1025 - на 18 позиции len=4; //длина подстроки 1025 равна 4 substring(Source,Destination,pos,len); controlSum1=atoi(Destination); if (controlSum1==0) { goto endParsing; //контрольная сумма должна быть больше еденицы, пропускаем парсинг } //pc.printf("for pos=%d and len=%d resultat is d= %s atoi=%d\r\n", pos, len, Destination, controlSum1); controlSum2=(value_+delta_value_+flag_autoset_+flag_plotter_)*2; //удвоение чтобы не было одинаковых чисел в сообщении //pc.printf("controlSum1=%d controlSum2=%d\r\n", controlSum1, controlSum2); if (controlSum1!=controlSum2) { //не совпала контрольная сумма //pc.printf ("controlSum1!=controlSum2 \r\n"); goto endParsing; //пропускаем парсинг } //присваиваем проверенные значения глобальным переменным strcpy(trueSource,Source); //копировать из Source в trueSource value=value_; delta_value=delta_value_; flag_autoset=flag_autoset_; flag_plotter=flag_plotter_; flag_comand_detected=true; //если флаг true, то всем переменным присвоены новые значения уставок endParsing: pc.attach(&onDataReceived, Serial::RxIrq); // reattach interrupt - переподключение прерывания перед выходом из функции } //______________________________________________________________________________ void onDataReceived() { 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); int time, valve1, valve2, countValve1=0, countValve2=0; int frequencyValve1, frequencyValve2; float raw_value_sum = 0 ; digital_4.write(0); //valve1 off; digital_7.write(0); //valve2 off; load_EEPROM (); //загрузка уставок из EEPROM if (value >= 1 && delta_value >= 1 && flag_autoset < 2 && flag_plotter < 2) { flag_stopRegulator=false; //уставки из EEPROM похожи на правду, разрешаем работу регулятора } else { flag_stopRegulator = true; //флаг остановки установлен pc.printf("Regulator stopped, error in EEPROM \r\n"); } pc.printf("Program started \r\n"); Watchdog &watchdog = Watchdog::get_instance(); watchdog.start(100); //WDlimit = 100 ms timer.start(); while (true){ //бесконечный цикл // kick watchdog regularly within provided timeout (сброс собаки в начало счёта) watchdog.kick(); if (flag_comand_detected) { //пришла правильная командная строка pc.printf("$press,%d,%d,%d,%d,%d,%d,%d,*\r\n", value,delta_value,flag_autoset,flag_plotter,sensor_value,frequencyValve1,frequencyValve2); //текущие данные //pc.printf("%s\r\n",trueSource); //эхо для отладки канала связи flag_comand_detected=false; //в последующих обращениях не печатать пока нет новых уставок из СОМ-порта flag_stopRegulator=false; //сброс флага, регулятор ждет пока не будет сброшен этот флаг //plotter.printf("$%d %d %d %d %d;\r\n", digital_4.read()*100-110, // digital_7.read()*100-220, value, sensor_value, time ); //печать в плоттер в другой СОМ-порт if (strcmp(trueSourceOld,trueSource) != 0) { //функция возвращает ноль если командные строки совпадают save_EEPROM (); //пишем в память уставки отличные от старых load_EEPROM (); } strcpy(trueSourceOld,trueSource); //копировать из trueSource в trueSourceOld } float raw_value = analog_value.read(); // Чтение аналогового входа (0.0 to 1.0 = full ADC диапазон) raw_value_sum = raw_value_sum + raw_value; if (counter_cycle1 > 20 ) { counter_cycle1=0; sensor_value = raw_value_sum/20 * 3300; // преобразование в напряжение 0-3300 mV с усреднением raw_value_sum = 0 ; if (flag_stopRegulator == false) { // можно запускать регулятор //--------------regulator begin----------------------- if (sensor_value > value + delta_value) { valve2 = digital_7.read(); digital_7.write(1); //valve2 on; if (valve2 < digital_7.read()) {countValve2++;} //счётчик передних фронтов напряжения (срабатывания клапана 2) digital_4.write(0); //valve1 off; } else if (sensor_value < value - delta_value) { valve1 = digital_4.read(); digital_4.write(1); //valve1 on; if (valve1 < digital_4.read()) {countValve1++;} //счётчик передних фронтов напряжения (срабатывания клапана 1) digital_7.write(0); //valve2 off; } else { digital_4.write(0); //valve1 off; digital_7.write(0); //valve2 off; } //--------------regulator end------------------------- } time=timer.read_us(); if (time > 1000000) { timer.reset(); //начало счёта времени frequencyValve1 = countValve1; //частота (Гц) срабатывания клапана 1 frequencyValve2 = countValve2; //частота (Гц) срабатывания клапана 2 countValve1=0; countValve2=0; } if (flag_plotter == 1) { plotter.printf("$%d %d %d %d %d %d;\r\n", digital_4.read()*100-110, digital_7.read()*100-220, value, sensor_value, 100*frequencyValve1, 100*frequencyValve2 ); //печать в плоттер в другой СОМ-порт (только для отладки) } auto_set(); //Ступенчатое увеличение и уменьшение уставки value (для отладки если flag_autoset =1) led = !led; //гасим/зажигаем индикаторный светодиод } ThisThread::sleep_for(1); // (mc) правильный оператор задержки для mbed5 counter_cycle1++; } }