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.

main.cpp

Committer:
Aleksk
Date:
2020-05-01
Revision:
0:f2aaa8c6decf

File content as of revision 0:f2aaa8c6decf:

#include "mbed.h"

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;                                                                    //инициализация таймера

int flag_autoset = 0;                                                           //отладочный флаг. При 0 - запрет автоуставки давления, при 1 - разрешение
int flag_plotter = 0;                                                           //отладочный флаг. При 0 - запрет печати в плоттер, при 1 - разрешение
int value = 0;                                                                  //set begin value "pressure" 
int delta_value = 0;                                                            //set delta pressure
int value_auto=250 ;                                                            //set begin value auto "pressure"
int sensor_value =0;                                                            //напряжение с аналогового входа А0 (текущее давление)
int counter_cycle1 = 0;
int counter_cycle2 = 0;
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

volatile char chr_a;                                //в прерываниях переменные должны быть защищены  при помощи volatile от оптимизации компилятором
volatile bool flag_comand_detected = false;         //если строка декодирована правильно то true

//______________________________________________________________________________
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.printf("program started \r\n");
    pc.attach(&onDataReceived, Serial::RxIrq);
    int time, valve1, valve2, countValve1=0, countValve2=0;
    int frequencyValve1, frequencyValve2;
    float raw_value_sum = 0 ;
    timer.start();
  while (true){                                                                 //бесконечный цикл
    
    if (flag_comand_detected) {
      pc.printf("$press,%d,%d,%d,%d,%d\r\n",
                 value,delta_value,flag_autoset,flag_plotter,sensor_value);     //текущие данные
      //pc.printf("%s\r\n",trueSource);                                         //эхо для отладки канала связи
      flag_comand_detected=false;                                              //в последующих обращениях не печатать пока нет новых уставок из СОМ-порта
      //plotter.printf("$%d %d %d %d %d;\r\n", digital_4.read()*100-110,
      //  digital_7.read()*100-220, value, sensor_value, time );                //печать в плоттер в другой СОМ-порт
    }
    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 ;
      //--------------regulator begin-----------------------
      if (sensor_value > value + delta_value) {
        valve2 = digital_7.read();
        digital_7.write(1);                                                     //valve2 = 1;
        if (valve2 < digital_7.read()) {countValve2++;}                    //счётчик передних фронтов напряжения (срабатывания клапана 2)
        digital_4.write(0);                                                     //valve1 = 0;
      } else  if (sensor_value < value - delta_value) {
        valve1 = digital_4.read();
        digital_4.write(1);                                                     //valve1 = 1;
        if (valve1 < digital_4.read()) {countValve1++;}                    //счётчик передних фронтов напряжения (срабатывания клапана 1)
        digital_7.write(0);                                                     //valve2 = 0; 
      } else {
        digital_4.write(0);                                                     //valve1 = 0;
        digital_7.write(0);                                                     //valve2 = 0; 
      }
      //--------------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++;
    
  }
}