test

Dependencies:   ad5422_arduino mbed LT1446 ADS1248-1 LM35-1 Flash FT813 PGA280_ADS1259

main.cpp

Committer:
nikmaos
Date:
2020-08-13
Revision:
5:21240fa1ee4c
Parent:
4:d53895f65eb7
Child:
6:cfe7cb0bdb1a

File content as of revision 5:21240fa1ee4c:

#include "PerifConfig.h"
#include "PGA280.h"
#include "ADS1259.h"
#include "PGA280ADS1259.h"
#include "main.h"
#include "ad5422_arduino.h"
#include "lm35.h"
#include "LT1446.h"
#include "ads1248.h"
#include "flashwrapper.h"
#include <cmath>
#include "FT_Platform.h"
#include "display.h"

//коэффициенты по умолчанию температура колонки
#define E_PCOEFF    0.5F    //Пропорциональный коэффициент ПИД регулятора (Из EEPROM)
#define E_ICOEFF    1500.0F //Постоянная времени интегрирования ПИД регулятора в секундах (Из EEPROM) (был 3000)
#define E_DCOEFF    0.1F
#define PID_SAMPLE_TIME 0.25F    //Период ПИД
// --//-- расхода
#define R_PCOEFF    0.11F    //Пропорциональный коэффициент ПИД регулятора (Из EEPROM)
#define R_ICOEFF    3000.0F //Постоянная времени интегрирования ПИД регулятора в секундах (Из EEPROM) (был 3000)
#define R_DCOEFF    0.1F
#define R_PID_SAMPLE_TIME 0.25F

#define CHKD (0x43484B44) //константа для проверки записанных данных (необходима контрольная сумма)
#define TEMP 35


/*Таймер для вызова функции каждые 40 мс*/
Ticker lm_temp;
Ticker adctask;
Ticker PID1; //ПИД для нагрева колонки
Ticker PID2; //ПИД для расхода
/*Конец*/
//InterruptIn button(USER_BUTTON);
InterruptIn ADSRdy(PG_3);

//настройка SPI для дисплея
FT813 TFT (D11, D12, D13, D10, D9, D8); //mosi, miso, sck, ss, int, pd
Display disp(&TFT);
//конец

ADS1248_t ads1;//экземпляр ЦАП 1446 в памяти
LM35_t RAS;
PID_prom_t TempCol;
PID_prom_t Rashod;
PID_defs_t PID_defs={E_PCOEFF,E_ICOEFF,E_DCOEFF,PID_SAMPLE_TIME};
PID_defs_t PID_R_defs={R_PCOEFF,R_ICOEFF,R_DCOEFF,R_PID_SAMPLE_TIME};
volatile uint8_t temp=0;// уставка температуры колонки
volatile float rashod_u=0; //уставка расхода
char mbflag;
unsigned char pga280gain;
char UComandFlag;
volatile unsigned char UComand;
volatile long tempdata=0;
char ch=0;              //адрес на плате ТЭД-2 = 6
float x=0;
float k;
unsigned char str[];

//указатель для подстановки нужной функции
void (*printer_p)(void);

//функция чтения АДС для выполнения в задаче
void readADC()
{
    tempdata=ads1259_readData(5);       //функция может зависать (надо избавиться от бесконечного цикла)          
    x=NormADC(tempdata);
    UART.printf("%08f\r\n",x);
}

void readtemp()
{    
    float t;
    /*Обработка ошибки*/
    //LM35_start(0.25);
     if(ads1.MUX0.MUX_SP!=0)
    {
                 DS1248_START=1;
                 ADS1248WakeupCommand();
                 ads1.MUX0.MUX_SN=1; //AIN1
                 ads1.MUX0.MUX_SP=0; //AIN0
                 ads1.VBIAS.all=0;
                 ADS1248SettingReg(&ads1);
        }
    
    if (LM35_0.ready) //если данные готовы то считать и сбросить флаг (способ многозадачности)
    {
        LM35_0.ready=0;
        t=LM35_0.temp;
        TempCol.Error=temp-t;
        TempCol.Integral += TempCol.Error;
        TempCol.dError = TempCol.Error - TempCol.last_Error;
        TempCol.last_Error = TempCol.Error;
        //временно записать в калиброванное значение (нельзя так делать)
        LT1446_0.dacB.Code=(uint16_t)(PID(&Mem.PID,&TempCol) * 4095);
        LTCwrite(&LT1446_0);        
    }
    
}

void readRashod()
{
    float r;
    //Если не настроен, то настраиваем нужный канал чтения
    if(ads1.MUX0.MUX_SP!=2)
    {
                 DS1248_START=1;
                 ADS1248WakeupCommand();
                 ads1.MUX0.MUX_SN=3; //AIN3
                 ads1.MUX0.MUX_SP=2; //AIN2
                 ads1.VBIAS.VBIAS3=1;
                 ADS1248SettingReg(&ads1);
        }
    //используем тот же тип из-за схожести
    if(RAS.ready)//Если данные готовы для считывания..
    {RAS.ready=0;
        r=RAS.temp; 
        Rashod.Error=rashod_u-r;
        Rashod.Integral += Rashod.Error;//
        Rashod.dError = Rashod.Error - Rashod.last_Error;
        Rashod.last_Error = Rashod.Error;
        LT1446_0.dacA.Code=(uint16_t)(PID(&Mem.PID_R,&Rashod) * 4095);
        LTCwrite(&LT1446_0);        
    //Pressure.write(PID(&Mem.PID_R,&Rashod));
    }
}

void printtemp()
//отобразить температуру 1 раз
{
    if (LM35_0.ready||RAS.ready) //если данные готовы то считать
    {
    UART.printf("TempCol %0.2f\t|\tRashod %0.4f ml (%0.4fV)\r\n",LM35_0.temp,RAS.temp,RAS.volts);
    }
    
    }

void printPID()
{
    /*функция отобображает в терминале значения не в момент расчёта ПИДа,
    но этого по идее достаточно для оценки результата работы, 
    так как отображаются последние записанные в переменную данные*/
    if ((Mem.PID.enabled==1)&&(Mem.PID_R.enabled==0)) //Если включен только первый ПИД
    {
        UART.printf("PID_t: Power %04d temp %0.2f\r\n",LT1446_0.dacB.Code,LM35_0.temp);
        }
    else if ((Mem.PID_R.enabled==1)&&(Mem.PID.enabled==0)) //Если включен только второй ПИД
    {
    UART.printf("PID_R: Power %04d rashod %0.4f ml (%0.4fV)\r\n",LT1446_0.dacA.Code,RAS.temp,RAS.volts);    
        }
    else if ((Mem.PID_R.enabled==1)&&(Mem.PID.enabled==1)) //Если включены оба ПИД    
        {
    UART.printf("PID_t: Power %04d temp %0.2f | ",LT1446_0.dacB.Code,LM35_0.temp);
    UART.printf("PID_R: Power %04d rashod %0.4f ml (%0.4fV)\r\n",LT1446_0.dacA.Code,RAS.temp,RAS.volts);    
            }    
}

float inline NormADC(long data)
{
    x=data*2.5/0x800000;
    //x=x*8/(1<<pga280gain);
    return x;
}


 /*Собственно сам расчёт ПИД. В аргумент подставляется
 конкретный ПИД (температура или расход) и его промежуточные значения (вклады)*/
 float PID (PID_t *pidx, PID_prom_t *prom)
    {         
    float P = pidx->kP * prom->Error;
    float I = pidx->kP / pidx->kI * pidx->sampleTime * prom->Integral;
    float D = pidx->kP * pidx->kD / pidx->sampleTime * prom->dError;
    float control = P + I + D;
    if (control > 1.0) return 1.0;
    if (control < 0.0) return 0.0;
    return control;
    }

//включить пид1
void pressed()
{
    /*Включить АЦП*/
    DS1248_START=1;
    ADS1248WakeupCommand();
    /*Выключить постоянное оторажение температуры*/
    
    //запустить ПИД
    PID1.attach(&readtemp,0.25);
    Mem.PID.enabled=1;
    UART.printf("PID is ON\r\n");
}

//включить пид2
void pid2_start()
{
    DS1248_START=1;
    ADS1248WakeupCommand();    
    PID2.attach(&readRashod,0.25);
    Mem.PID_R.enabled=1;
    UART.printf("PID_R is ON\r\n");
}

void readads()
/*чтение АЦП в режиме
-только первый канал
-только второй канал
-оба канала
или как вариант: позиция бита означает какие каналы считываются если их больше чем 2*/
{    
    double v=0;
    v=2.048*ADS1248ReadData(&ads1)/0x800000;    
    if(ads1.MUX0.MUX_SP==0)
    {    
    LM35_0.temp=v*100;    
    LM35_0.ready=1;
    }
    if (ads1.MUX0.MUX_SP==2)
    {
        RAS.volts=v;
        RAS.temp=v*26.316-0.263;// мл/мин (сделать уставку)
        RAS.ready=1;
        }
    
    }
    
void Mem_write()
{
    flashWrite(0,Mem.w,(sizeof(Mem.w)/sizeof(uint32_t)));
}

float BufToFloat(unsigned char *buf)
/*Преобразование строки из 16 символов в float*/
/*Нельзя первым символом вводить точку, перед неей обязательно нужна цифра
Числа вводятся в формате 1.0 или 1,0 (точка обяательна даже если дробной части нет)*/
{    
    int8_t n=-1; //начало (при старте его нет)
    uint8_t i=0;
    int8_t j=-1; //счётчик символов до точки
    uint8_t p=0; //позиция точки
    float result=1;  //временно используем чтобы определить знак числа
    
    //while(str[i]!=)    
    //команда выглядит как "/v0=-123.456" поэтому считаем с символа "-" позиция которого 3 (4 знак в массиве)    
    //проверка на отрицательность и первый знак            
    for (i=0;i<16;i++)
    {
        if(buf[i]=='-'){
            result=-result;
            n=i;
            i++;                    
            break;
            }
        if((buf[i]>=0x30)&&(buf[i]<=0x39))
        {
            n=i;            
            break;
        }            
    }
    if(n<0) return 0;
    //до тех пор, пока поступают нужные символы и нет превышения длины строки
    while((i<16)&&(buf[i]>=0x30)&&(buf[i]<=0x39)||((buf[i]=='.')||(buf[i]==',')||(buf[i]=='-')))
        {            
            i++;            
        //проверять на наличие точки или запятой
            if((buf[i]=='.')||(buf[i]==','))
            {
                if(p==0){               //если точка ещё не попадалась
                p=i;                    //запоминаем позицию плавающей запятой
                if (result>=0)
                j=i-n;                  //цифр до точки (3 начало)
                else j=i-n-1;}          //на 1 символ больше из-за "-"
                else break;             //если попалась ещё одна точка
            }        
       }
        
    /*Добавить проверку на целое число!!
    Добавить проверку на первый символ "точка"
    */
    
    //ниже преобразуем информацию в число
    if (result>=0){
        result=0;
        i=i-j-n-1; //знаки после запятой
        while(i--){
            result+=(buf[p+i+1]-0x30)*powf(10,-i-1);
        }
        while(j--){
        result+=(buf[p-j-1]-0x30)*powf(10,j);        
        }
    }            
    else {//строка на 1 знак больше
        result=0;
        i=i-j-n-2; //знаки после запятой         
        while(i--){
            result+=(buf[p+i+1]-0x30)*powf(10,-i-1);
        }
        while(j--){            
        result+=(buf[p-j-1]-0x30)*powf(10,j);        
        }
        result=-result;
    }
    if (result>-9999.9&&result<9999.99)//заменить на проверку адекватности
    return result;
    else if (result<=-9999.99)
    return (-9999.99);
    else if (result>=9999.99)//заменить на проверку адекватности
    return (9999.99);
    else return 0;
}    

void setPIDdefault(PID_t *pidx,PID_defs_t *defs)
/*Установка для нужного пида его настроек по умолчанию*/
{
        pidx->kP=defs->kp;
        pidx->kI=defs->ki;
        pidx->kD=defs->kd;
        pidx->sampleTime=defs->st;
        pidx->chkd=CHKD;
    }
  
int main()
{       
    UART.printf("SystemClock %d\r\n",SystemCoreClock);
    //считывание данных настроек из памяти
    for (int i=0;i<sizeof(Mem.w)/sizeof(uint32_t);i++)
    {    
    Mem.w[i]=flashRead(i*4);//sizeof(uint32_t)=4;
    }
    if ((Mem.PID.chkd!=CHKD)||(Mem.PID_R.chkd!=CHKD))
    {
    //если метки данных нет то записать настройки ПИД по умолчанию
    UART.printf("PID is default\r\n");
        setPIDdefault(&Mem.PID,&PID_defs);
        setPIDdefault(&Mem.PID_R,&PID_R_defs);
        Mem_write();
        }
    UART.printf("PID:\r\nKp=%0.3f\r\nkI=%0.3f\r\nkD=%0.3f\r\n",Mem.PID.kP,Mem.PID.kI,Mem.PID.kD);
    UART.printf("PID_R:\r\nKp=%0.3f\r\nkI=%0.3f\r\nkD=%0.3f\r\n",Mem.PID_R.kP,Mem.PID_R.kI,Mem.PID_R.kD);
    UART.printf("%08X\r\n",Mem.PID.chkd);
    
    //Инициализация периферийных устройств
    SPI1_MasterInitMode(1);//работают режимы 1 и 2 для платы ТЭД2
     //SPI3_MasterInitMode(1);
   //запустить задачу проверки команды по прерыванию УАРТ
    UART.attach(&ComandCheck,Serial::RxIrq);
    /*EN1=1;
    
     ch=5;
    pga280_setAdress(ch);    
    pga280_ads1259_init(ch); //инициализировать АЦП по адресу на плате ТЭД-2 = 5 (4)
    printf("\r\n");
    tempdata=pga280_readOneRegisterDevice(PGA280_BUF_TIMEOUT_ADR,ch);
    printf("Timeout %X\n",tempdata);
    wait_ms(20);
    pga280_setGAIN(GAIN_1_PGA280,ch);
    pga280_setMUX(2,ch);
    pga280gain=3; //   gain=1 (0x03)
    tempdata=pga280_readOneRegisterDevice(PGA280_ERROR_ADR,ch);//чтение ошибок
    printf("Errors %X\n",tempdata);
    /*Конец*/
    

    
    
    /*Инициализация внешнего АПЦ для LM35*/
    //создадим экземпляр АЦП если их несколько
    UART.printf("Configuring ADC\r\n");
    DS1248_START=0;
    wait_ms(20);
    DS1248_START=1;
    wait_ms(20);
    /*Настройка регистров в ОЗУ (описание в заголовочном файле)*/
    ads1.MUX0.MUX_SN=1; //AIN1
    ads1.MUX0.MUX_SP=0; //AIN0
    ads1.MUX0.BCS=0;
    
    ads1.VBIAS.all=0;
    ads1.VBIAS.VBIAS0=0;
    
    ads1.SYS0.DR=DR20;
    ads1.SYS0.PGA=PGA_1; //=log2(PGA) пример: PGA=16 значит значение будет log2(16)=4;
    
    ads1.MUX1.MUXCAL=0;
    ads1.MUX1.REFSELT=2;
    ads1.MUX1.VREFCON=1;
    
    ads1.IDAC0.all=0;
        
    ads1.IDAC1.all=0xFF;
    
    ads1.FSC.all=1*(0x400000); //масштаб АЦП (наверное не коэффициент усиления)
    /*Конец*/
     //Записать в чип
    ADS1248SettingReg(&ads1);
    if(ads1.SYS0.all==ADS1248ReadRegister(DS1248_REGISTER_SYS0,1))  //30.07.2020/8:40
    UART.printf("ADS is configured\r\n");
    ADSRdy.fall(&readads);//виснет без платы (решение - закомментить)
    wait_ms(20);
    //ADS1248SleepCommand();//временно отключаем чтобы при старте не началось считывание
    DS1248_START=0;
    
    /*Инициализация внещнего ЦАП*/
    LT1446_0.dacA.Code=0;
    LT1446_0.dacA.Code=0;
    LTCwrite(&LT1446_0);
    UART.printf("DAC is configured\r\n");
    
    //обнуление режима работы ПИД
    Mem.PID.enabled=0;
    Mem.PID_R.enabled=0;
    /*Тестовая кнопка для включения PID*/
    //button.fall(&pressed);
    //Калибрануть если есть дисплей
    if(TFT.IsOn()){
    UART.printf("Process of calibration\r\n");
    disp.Calibration(Mem.calibration,0);    
    Mem_write();
    UART.printf("Calibrated\r\n");}    
    disp.activeScreen = PID_SCREEN;
    disp.pressedButton = NONE_PRESS;
    disp.str_edit[0]='_';
    disp.cursor=0;
    
    //ADS1248CalibrateSoft(&ads1,BufToFloat); //эксперимент
    
    // change active screen depending on pressed area
    while(1) {
        
        if(TFT.IsOn())//проверка включения дисплея
        {
        disp.pressedButton = disp.GetTouch();
        
        //-------------------------------ChromTestScreen------------------------
        if (disp.activeScreen == TEST_CHROM_SCREEN) {
            disp.ChromTest(LM35_0.temp,RAS.temp,temp,rashod_u);
            if(disp.pressedButton){
                wait_ms(100);
                if(disp.pressedButton==CHROM_TEMP_PRESS){
                     disp.pressedButton = NONE_PRESS;
                    disp.activeScreen=MENU_SCREEN;
                    }
                }
            }
        // ---------------------------------------------------------------------
        //=------------------------------PID Screen-----------------------------
        if (disp.activeScreen == PID_SCREEN) {
            if(disp.pressedButton>=SEL_P1&&disp.pressedButton<=SEL_D2)            
            disp.selectedEditor=(selectedEditor_t)disp.pressedButton;            
           // else disp.selectedEditor=(selectedEditor_t)NONE_PRESS;
                disp.PidScreen(&BufToFloat,LM35_0.temp,RAS.temp,LT1446_0.dacB.Code,LT1446_0.dacA.Code,&Mem.PID,&Mem.PID_R);}
                wait_ms(100);
        
        //=---------------------------------------------------------------------
        
        // Main menu screen
        if (disp.activeScreen == MENU_SCREEN) {
            disp.MainMenu(LM35_0.temp, LM35_0.temp);//сюда писать значения (наверное) (расход/температура)
            if (disp.pressedButton) {
                wait_ms(150);
                if (disp.pressedButton == CURR_TEMP_PRESS) {
                    disp.activeScreen = CURR_TEMP_SCREEN;
                } else if (disp.pressedButton == CURR_HUM_PRESS) {
                    disp.activeScreen = CURR_HUM_SCREEN;
                } 
                disp.pressedButton = NONE_PRESS;
            }
 
        // ---------------------------------------------------------------------
        // Any other screen
        } else {
            // ----------------------------------------------------------------------------------------------
            // You can back to main menu from any screen
            if (disp.pressedButton == MENU_PRESS) {
                disp.pressedButton = NONE_PRESS;
                disp.activeScreen = MENU_SCREEN;
            } else {
                // ----------------------------------------------------------------------------------------------
                // Screen with current temperature / humidity
                if (disp.activeScreen == CURR_TEMP_SCREEN) {
                    disp.CurrentTemperature(LM35_0.temp);//и сюда тоже
                } else if (disp.activeScreen == CURR_HUM_SCREEN) {
                    disp.CurrentHumidity(LM35_0.temp);//и сюда
                } 
            }
        }
    }//Проверка включения дисплея
    }
}



/*команды*/
void ComandCheck()
{      
        UART_gets(16); //моя функция на время        
        if(str[0]=='/')              
        {
        UART.printf("%c\r\n",str[1]);
        switch (str[1]){
             /*Проверка платы SB-1 SWEN*/
             case 'i':{
                 if (str[2]=='1')
                 {SB1_SWEN=1;
                 UART.printf("SW is ON\r\n");}
                 else if (str[2]=='0')
                 {SB1_SWEN=0;
                 UART.printf("SW is OFF\r\n");}
                 else if (str[2]=='a')
                 {
                     PosAw=1;
                     PosBw=0;
                     wait_ms(50);
                     PosAw=0;
                     PosBw=0;
                     }
                 else if (str[2]=='b')
                 {
                     PosAw=0;
                     PosBw=1;
                     wait_ms(50);
                     PosAw=0;
                     PosBw=0;
                     }
                 else if (str[2]=='r')
                 {
                     char a='0';
                     if (PosAr)
                     a='a';
                     else if (PosBr)
                     a='b';                    
                     UART.printf("POS is %c",a);
                     }
                 break;}
             case 'k':{//настройки ПИДа температуры колонки
                 PID1.detach();
                 LT1446_0.dacB.Code=0;
                 LT1446_0.dacA.Code=0;                 
                 LTCwrite(&LT1446_0);
                 switch (str[2]){
                 case 'P':{
                 Mem.PID.kP=BufToFloat(str);
                 Mem_write();
                 UART.printf("P=%f\r\n",Mem.PID.kP);
                 break;
                 }
                 case 'I':{
                 Mem.PID.kI=BufToFloat(str);
                 Mem_write();
                 UART.printf("I=%f\r\n",Mem.PID.kI);
                 break;
                 }
                 case 'D':{
                 Mem.PID.kD=BufToFloat(str);
                 Mem_write();
                 UART.printf("D=%f\r\n",Mem.PID.kD);
                 break;
                 }
                 case 'f':{
                     setPIDdefault(&Mem.PID,&PID_defs);
                     Mem_write();
                     UART.printf("PID is default\r\n");
                     break;}
                 default:break;
                 }
                 //задание уставки температуры
                 if ((str[2]>='0')&&(str[2]<='9')){
                 temp=(str[2]-'0')*10+(str[3]-'0');                 
                 UART.printf("temp= %d\r\n",temp); }                    
                 break;}
                 
             case 't':{
                 //начать чтение температуры
                 //отключаем отображение для перенастройки, настраиваем, записываем, включаем обратно отображение с новым параметром
                 lm_temp.detach();      
                 DS1248_START=1;
                 ADS1248WakeupCommand();
                 ads1.MUX0.MUX_SN=1; //AIN1
                 ads1.MUX0.MUX_SP=0; //AIN0
                 ads1.VBIAS.all=0;
                 ADS1248SettingReg(&ads1);
                 UART.printf("Temperature reading started.\r\n");
                 //снять показания термодатчика
                 //LM35_start(0.25);
                 printer_p=&printtemp;
                 lm_temp.attach(printer_p,0.1);
                 break;}
                 
             case 'p':{                
                pga280gain=str[2]; //присваиваем числовое значение команды взятое из символа цифры
                pga280gain-=0x30;
                ch=5;
                pga280_setGAIN(pga280gain,ch);
                ch=0;               
                break;}
                
            case 'g': {      //включить нужный ПИД         
                if(str[2]=='p')
                {
                    switch(str[3])
                    {//gp1
                    case '1'://первый - температура
                    {
                        lm_temp.detach();
                        pressed();
                        printer_p=&printPID;
                        lm_temp.attach(printer_p,0.25);
                        break;}
                    case '2'://второй - расход
                    {//gp2
                        lm_temp.detach();
                        pid2_start();
                        printer_p=&printPID;
                        lm_temp.attach(printer_p,0.25);
                        break;}
                    
                    //остановить работу ПИД регуляторов.
                    case 's'://  /gps
                    {
                        lm_temp.detach();                        
                        PID1.detach();
                        PID2.detach();
                        Mem.PID.enabled=0;
                        Mem.PID_R.enabled=0;
                        LT1446_0.dacB.Code=0;
                        LT1446_0.dacA.Code=0;
                        LTCwrite(&LT1446_0);
                        UART.printf("PIDs is stopped\r\n");
                        break;}
                    }
                }
                //запустить задачу чтения АЦП каждые 40 мс (25 герц)
                //adctask.attach(&readADC,0.04);
                break;}
                
            case's':  {//остановить постоянное отображение
                //adctask.detach();
                lm_temp.detach();
                Mem.PID.enabled=0;
                Mem.PID_R.enabled=0;
                //LM35_stop();
                ADS1248SleepCommand();
                DS1248_START=0;
                break;}
                
            case 'd':{//LTC1446 задание значений на ЦАП оба канала
                //MBFlagRegister.DAC=1;
                if (str[2]=='a')//команда = "da=xxxx" где хххх - код ЦАП
                {
                    LT1446_0.dacA.Code=(str[3]-0x30)*1000+(str[4]-0x30)*100+(str[5]-0x30)*10+(str[6]-0x30);
                    UART.printf("%d\r\n",LT1446_0.dacA.Code);
                    }
                if (str[1]=='b')
                {
                    LT1446_0.dacB.Code=(str[3]-0x30)*1000+(str[4]-0x30)*100+(str[5]-0x30)*10+(str[6]-0x30);
                    UART.printf("%d\r\n",LT1446_0.dacB.Code);
                    }
                 LTCwrite(&LT1446_0);
                break;}
            case 'e':{
                tempdata=pga280_readOneRegisterDevice(PGA280_ERROR_ADR,5);//чтение ошибок                
                printf("ERRORS %X\n",tempdata);                               
                break;}            
            case 'r':{//выключить ПИД 2 перед манипуляциями с ним
                 PID2.detach();
                 //задающее воздействие =0;
                 LT1446_0.dacA.Code=0;
                 LT1446_0.dacB.Code=0;
                 LTCwrite(&LT1446_0);
                 //обработка команд
                 switch (str[2]){
                 case 'P':{
                 Mem.PID_R.kP=BufToFloat(str);
                 Mem_write();
                 UART.printf("P=%f\r\n",Mem.PID_R.kP);
                 break;
                 }
                 case 'I':{
                 Mem.PID_R.kI=BufToFloat(str);
                 Mem_write();
                 UART.printf("I=%f\r\n",Mem.PID_R.kI);
                 break;
                 }
                 case 'D':{
                 Mem.PID_R.kD=BufToFloat(str);
                 Mem_write();
                 UART.printf("D=%f\r\n",Mem.PID_R.kD);
                 break;
                 }
                 case 'f':{//  /rf
                     setPIDdefault(&Mem.PID_R,&PID_defs);
                     Mem_write();
                     UART.printf("PID is default\r\n");
                     break;}
                 case 'g':{//запуск чтения расхода /rg
                 lm_temp.detach();
                     DS1248_START=1;
                 ADS1248WakeupCommand();
                 ads1.MUX0.MUX_SN=3; //AIN3
                 ads1.MUX0.MUX_SP=2; //AIN2
                 ads1.VBIAS.VBIAS3=1;
                 ADS1248SettingReg(&ads1);
                 UART.printf("Rashod reading started.\r\n");
                 printer_p=&printtemp;
                 lm_temp.attach(printer_p,0.1);
                     break;}
                     
                     case 'u':{ // ru=xx.xx; точка обязательна
                         //задание уставки расхода
                 rashod_u=BufToFloat(str);
                 UART.printf("Rashod = %0.3f\r\n",rashod_u);
                         break;}
                 default:break;
                 }
                 
                if((str[2]=='e')&&(str[3]=='s')&&(str[4]=='e')&&(str[5]=='t')){
                //перезагрука
                printf("System Reset\r\n");
                NVIC_SystemReset();}
                if ((str[2]=='e')&&(str[3]=='c')&&(str[4]=='a')&&(str[5]=='l')){
                    disp.Calibration(Mem.calibration,1);
                    UART.printf("Recalibrated\r\n");
                    };
                break;}
            default:                                
                //MBFlagRegister.TMLS=0; //починка зависания (не работает)
                break;
        }        
       }    
}