Explorar el Código

更新第二版程序,对象化各传感器, 使用串级PID 进行控制

guoqiang hace 2 años
padre
commit
365a936552
Se han modificado 22 ficheros con 1856 adiciones y 1329 borrados
  1. 4 0
      Modbus.h
  2. 5 1
      PageMain.qml
  3. 105 26
      PageTest.qml
  4. 107 0
      PressureSensor.cpp
  5. 17 0
      PressureSensor.h
  6. 670 1040
      TestService.cpp
  7. 29 41
      TestService.h
  8. 8 2
      ValveTest.pro
  9. 4 3
      ValveTest.pro.user
  10. 198 0
      ballvalve.cpp
  11. 35 0
      ballvalve.h
  12. 1 1
      main.cpp
  13. 221 18
      pid.cpp
  14. 19 1
      pid.h
  15. 168 54
      report.cpp
  16. 59 1
      report.h
  17. 9 126
      serialport.cpp
  18. 6 8
      serialui.cpp
  19. 4 4
      tank.cpp
  20. 3 3
      tank.h
  21. 157 0
      valve.cpp
  22. 27 0
      valve.h

+ 4 - 0
Modbus.h

@@ -6,6 +6,10 @@
 //比例调节阀modbus 地址
 #define ADJUSTVALVE_ADDRESS  (0x03)
 
+//比例球阀 modbus 地址
+#define BALLVALVE_BUS_ADDRESS  (0x03)
+
+
 //压力传感器modbus地址
 #define PRESSURESENSOR_ADDRESS     (0x02)
 

+ 5 - 1
PageMain.qml

@@ -346,7 +346,7 @@ Rectangle{
     }
 
     function qmlProcessPressure(id, map){
-        console.log("main.qml qmlProcessPressure  [%d] []",id )
+        //console.log("main.qml qmlProcessPressure ",id )
         //log.show2(str)
         //var textstring = ''
         //var varmap = map
@@ -405,9 +405,13 @@ Rectangle{
         if(id === 0){
             if(bPassed){
                 pagetest.show_selftestResult("通过")
+                //pagetest.show_selftestResult(str)
             }else{
                 pagetest.show_selftestResult("未通过")
+                //pagetest.show_selftestResult(str)
             }
+
+            pagetest.show_selftestDetail(str)
         }
 
     }

+ 105 - 26
PageTest.qml

@@ -16,6 +16,7 @@ Item{
     property bool bSelfTest_Started: false
     property  string selfTest_State_str:""
     property  string selfTest_Result_str:""
+    property  string selfTest_Detail_str:""
 
 
     function show_pressure(pressure_str){
@@ -30,6 +31,10 @@ Item{
         selfTest_Result_str = str
     }
 
+    function show_selftestDetail(str){
+        selfTest_Detail_str = str
+    }
+
     function selftestStop(){
         var ret1 = testService.tstop(0);
         if(ret1){
@@ -89,9 +94,9 @@ Item{
                             //console.log("switch 1 clicked")
 
                             if(switch1.checked){
-                                testService.valve_open(TestService.Valve_ID_ROUGH_0)
+                                testService.valve_open(TestService.Valve_ID_INTAKE)
                             }else{
-                                testService.valve_close(TestService.Valve_ID_ROUGH_0)
+                                testService.valve_close(TestService.Valve_ID_INTAKE)
                             }
 
                         }
@@ -99,52 +104,57 @@ Item{
 
                     UserSwitch{
                         id:switch2
-                        text: "泄气阀关"
+                        text: "真空阀关"
                         onCheckedChanged: {
-                            switch2.text = switch2.checked ? "泄气阀开":"泄气阀关"
+                            switch2.text = switch2.checked ? "真空阀开":"真空阀关"
 
                         }
                         onClicked: {
                             if(switch2.checked){
-                                testService.valve_open(TestService.Valve_ID_ROUGH_1)
+                                testService.valve_open(TestService.Valve_ID_VACUUM)
                             }else{
-                                testService.valve_close(TestService.Valve_ID_ROUGH_1)
+                                testService.valve_close(TestService.Valve_ID_VACUUM)
                             }
                         }
                     }
                     UserSwitch{
                         id:switch3
-                        text: "传感阀关"
+                        text: "泄气阀关"
                         onCheckedChanged: {
-                            switch3.text = switch3.checked ? "传感阀开":"传感阀关"
+                            switch3.text = switch3.checked ? "泄气阀开":"泄气阀关"
 
                         }
 
                         onClicked: {
                             if(switch3.checked){
-                                testService.valve_open(TestService.Valve_ID_ROUGH_2)
+                                //switch3.checked = testService.valve_open(TestService.Valve_ID_VENT) === true? true:false
+                                testService.valve_open(TestService.Valve_ID_VENT)
                             }else{
-                                testService.valve_close(TestService.Valve_ID_ROUGH_2)
+                                //switch3.checked = testService.valve_close(TestService.Valve_ID_VENT) === true? true:false
+                                testService.valve_close(TestService.Valve_ID_VENT)
                             }
                         }
                     }
+
+
                     UserSwitch{
                         id:switch4
-                        text: "校准阀关"
+                        text: "全部关"
                         onCheckedChanged: {
-                            switch4.text = switch4.checked ? "校准阀开":"校准阀关"
+                            switch4.text = switch4.checked ? "全部开":"全部关"
 
                         }
 
                         onClicked: {
                             if(switch4.checked){
-                                testService.valve_open(TestService.Valve_ID_CALIBRATION)
+                                testService.valve_open(TestService.Valve_ID_All)
                             }else{
-                                testService.valve_close(TestService.Valve_ID_CALIBRATION)
+                                testService.valve_close(TestService.Valve_ID_All)
                             }
                         }
                     }
 
+
                 }
 
 
@@ -152,7 +162,7 @@ Item{
 
             DynamicGroupBox{
                 id:adjust_control
-                title: "调节阀控制"
+                title: "电动球阀控制"
 
                 width: 800
                 height: 100
@@ -170,14 +180,14 @@ Item{
                             //anchors.bottom: parent.bottom
                             //anchors.centerIn: parent
                             anchors.verticalCenter: parent.verticalCenter
-                            text: qsTr("调压阀:")
+                            text: qsTr("比例球阀:")
                             font.pixelSize: 20
 
                         }
 
                         UserButton {
                             id: adjustbutton;
-                            text: "调压";
+                            text: "设置开度";
                             font.pixelSize: 20
 
                             anchors.verticalCenter: parent.verticalCenter
@@ -186,13 +196,14 @@ Item{
                             height: 45
 
                             onClicked: {
-                                //var str_number = voltage.text
-                                var num = Number(voltage.text)
-                                if((num>0) && (num<1000)){
-                                    testService.adjust_Pressure(voltage.text)
+                                var num = Number(position.text)
+                                if((num >= 0) && (num <= 1000)){
+                                    if(false === testService.ballvalve_control(position.text)){
+                                        log.show("比例调节失败!!!")
+                                    }
                                 }else{
-                                    console.log("input voltage invalid")
-                                    log.show("Voltage invalid, please retry")
+                                    console.log("input position invalid")
+                                    log.show("开度值非法, 请重新输入")
                                 }
 
                             }
@@ -200,8 +211,8 @@ Item{
 
 
                         InputLine{
-                            id:voltage
-                            paraName: "Voltage:"
+                            id:position
+                            paraName: "开度值(0--1000):"
                             paraLength: 60
 
                             anchors.verticalCenter: parent.verticalCenter
@@ -214,6 +225,46 @@ Item{
                             }
                         }
 
+                        UserButton {
+                            id: status_button;
+                            text: "获取状态";
+                            font.pixelSize: 20
+
+                            anchors.verticalCenter: parent.verticalCenter
+
+                            width: 120
+                            height: 45
+
+                            onClicked: {
+
+                                var jsontmp = testService.ballvalve_status()
+                                status.text = jsontmp.status
+                                value.text = jsontmp.position
+                            }
+                        }
+
+                        Text {
+                            id: status
+                            //anchors.top: parent.top
+                            //anchors.bottom: parent.bottom
+                            //anchors.centerIn: parent
+                            anchors.verticalCenter: parent.verticalCenter
+                            text: ""
+                            font.pixelSize: 16
+
+                        }
+
+                        Text {
+                            id: value
+                            //anchors.top: parent.top
+                            //anchors.bottom: parent.bottom
+                            //anchors.centerIn: parent
+                            anchors.verticalCenter: parent.verticalCenter
+                            text: ""
+                            font.pixelSize: 16
+
+                        }
+
 
                     }
 
@@ -240,7 +291,7 @@ Item{
                         running: false //是否开启定时,默认是false,当为true的时候,进入此界面就开始定时
                         triggeredOnStart: false // 是否开启定时就触发onTriggered,一些特殊用户可以用来设置初始值。
                         onTriggered: {
-                            lcd_pressure.text = testService.read_PressureValue();
+                            lcd_pressure.text = testService.read_PressureValue()
                         }
                         //restart ,start,stop,定时器的调用方式,顾名思义
 
@@ -311,6 +362,20 @@ Item{
                         font.pixelSize: 25
                     }
 
+                    UserButton {
+                    id: zerobutton;
+                    text: "传感器标零";
+                    font.pixelSize: 20
+                    anchors.verticalCenter: parent.verticalCenter
+
+                    implicitWidth: 120
+                    implicitHeight: 45
+
+                    onClicked: {
+                         testService.pressure_zero()
+                    }
+                }
+
                 }
 
             }
@@ -395,6 +460,20 @@ Item{
 
                     }
 
+                    Text {
+                        id: selftest_Detail
+                        anchors.verticalCenter: parent.verticalCenter
+                        text: selfTest_Detail_str
+                        font.pixelSize: 16
+
+                        //lineHeight: Text.ProportionalHeight //设置行间距
+                        lineHeight: 0.5 //行间距比例 最大 1
+                        wrapMode: Text.WordWrap //换行
+
+                        fontSizeMode: Text.Fit //固定 Text 显示大小->字体自动变化的模式选中还有几种看文档
+                        minimumPixelSize: 10 //设置自动变化最小字体大小
+
+                    }
 
 
                 }

+ 107 - 0
PressureSensor.cpp

@@ -0,0 +1,107 @@
+#include "PressureSensor.h"
+#include "Modbus.h"
+
+PressureSensor::PressureSensor(SerialUi* pSerial)
+{
+    m_pSerial = pSerial;
+}
+
+bool PressureSensor::Read(float& pressure)
+{
+    QByteArray tx_buf;
+
+    char zero = 0x00;
+    tx_buf.append(PRESSURESENSOR_ADDRESS);
+    tx_buf.append(0x04);
+    tx_buf.append(zero);
+    tx_buf.append(zero);
+    tx_buf.append(zero);
+    tx_buf.append(0x02);
+
+    unsigned short crc;
+
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());
+
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        if(check_crc(rx_buf)){
+
+            char value[4];
+            value[3] = rx_buf.at(5);
+            value[2] = rx_buf.at(6);
+            value[1] = rx_buf.at(3);
+            value[0] = rx_buf.at(4);
+
+            float* p = (float*)value;
+            pressure = *p;
+
+            return true;
+        }else{
+
+            qDebug("PressureSensor::Read <<< check crc failed");
+            return false;
+        }
+
+    }else{
+
+        qDebug("PressureSensor::Read <<< no data received");
+        return false;
+    }
+}
+
+bool PressureSensor::Set_Zero()
+{
+    QByteArray tx_buf;
+
+    char zero = 0x00;
+    tx_buf.append(PRESSURESENSOR_ADDRESS);
+    tx_buf.append(0x06);
+    tx_buf.append(zero);
+    tx_buf.append(0x1E);
+    tx_buf.append(zero);
+    tx_buf.append(0x01);
+
+    unsigned short crc;
+
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());
+
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        if(check_crc(rx_buf)){
+
+            return true;
+        }else{
+            qDebug("PressureSensor::Set_Zero <<< check crc failed");
+            return false;
+        }
+    }else{
+        qDebug("PressureSensor::Set_Zero <<< no data received");
+        return false;
+    }
+}
+
+bool PressureSensor::check_crc(QByteArray data)
+{
+    int size = data.size();
+    unsigned short crc1 =0, crc2= 0;
+
+    unsigned char crc_h = data.at(size-2);
+    unsigned char crc_l = data.at(size-1);
+
+    crc1 = (crc_h <<8) |crc_l;
+    crc2 = CRC16_MODBUS((unsigned char *)data.data(),data.size()-2);
+
+     if(crc1 == crc2){
+        return true;
+     }else{
+         return false;
+     }
+}

+ 17 - 0
PressureSensor.h

@@ -0,0 +1,17 @@
+#ifndef PRESSURESENSOR_H
+#define PRESSURESENSOR_H
+
+#include "serialui.h"
+
+class PressureSensor
+{
+public:
+    PressureSensor(SerialUi* pSerial);
+    bool Read(float& pressure);
+    bool Set_Zero(); // 零点标定
+private:
+    SerialUi* m_pSerial;
+    bool check_crc(QByteArray data);
+};
+
+#endif // PRESSURESENSOR_H

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 670 - 1040
TestService.cpp


+ 29 - 41
TestService.h

@@ -19,7 +19,7 @@
 #include <QSignalSpy>
 
 //#define MAX_COMPARTMENT_NUM  (4)
-#define AVERAGE_PRESSURE_COUNT (2)   //5个不代表5秒, 要看采样频率
+#define AVERAGE_PRESSURE_COUNT (1)   //5个不代表5秒, 要看采样频率
 
 typedef enum _Ret_Value{
     Ret_Failed = -2,
@@ -58,8 +58,8 @@ enum Test_Direction{
 
 class TestExpect{
 public:
-    int start_voltage;
-    float target;   //pressure value
+    int volume;
+    double target;   //pressure value
     int timeout;       // timeout (s)
 };
 
@@ -74,32 +74,22 @@ public:
     ~TestService();
 
     enum Valve_ID {
-        Valve_ID_ROUGH_0=0,       //粗调阀
-        Valve_ID_ROUGH_1,         //
-        Valve_ID_ROUGH_2,
-        Valve_ID_CALIBRATION,     //压力校准阀
-        Valve_ID_PRESSURESENSOR,  //压力传感阀
-        Valve_ID_VACUUM,          //真空阀
-        Valve_ID_VENT,            //泄气阀
-        Valve_ID_INTAKE,          //进气阀
-        Valve_ID_8,
-        Valve_ID_9,
-        Valve_ID_10,
-        Valve_ID_11,
-        Valve_ID_12,
-        Valve_ID_13,
-        Valve_ID_14,
-        Valve_ID_15,
+        Valve_ID_INTAKE=0,       //进气阀
+        Valve_ID_VACUUM,         //真空阀
+        Valve_ID_VENT,           //泄气阀
+        Valve_ID_4,
         Valve_ID_All,
     };
 
 
     Q_INVOKABLE  void init();
     Q_INVOKABLE  bool setTankinfo(const QVariantList& list);
-    Q_INVOKABLE  void valve_open(Valve_ID id);
-    Q_INVOKABLE  void valve_close(Valve_ID id);
+    Q_INVOKABLE  bool valve_open(Valve_ID id);
+    Q_INVOKABLE  bool valve_close(Valve_ID id);
     Q_INVOKABLE QString read_PressureValue();
-    Q_INVOKABLE void adjust_Pressure(QString voltage_str);
+    Q_INVOKABLE  bool pressure_zero();
+    Q_INVOKABLE bool ballvalve_control(QString position_str);
+    Q_INVOKABLE QJsonObject ballvalve_status();
     Q_INVOKABLE bool tstart(int compartmentid, int direction);  //direction : 0 positive test , 1 negative test
     Q_INVOKABLE bool tselfstart(int compartmentid, int direction);  //direction : 0 positive test , 1 negative test
     Q_INVOKABLE bool tstop(int compartmentid);
@@ -131,15 +121,7 @@ public slots:
    void receive_reportprogress(QString qstr);
 
 private:
-
-    unsigned short Calcrc(const unsigned char *ptr, int count);
-    void SendCmd(QSerialPort* pSerial, QByteArray data);
-    bool check_crc(QByteArray data);
-
-
-    bool Valve_op(Valve_ID id, Valve_OP op);
-    bool Read_pressure(float & pressure);
-    bool Adjust_pressure(unsigned short voltage);
+    //bool Adjust_pressure(unsigned short voltage);
 
     void push_pressurelist(float pressure);
     void clear_pressurelist();
@@ -148,34 +130,39 @@ private:
     bool OpenSerial3();
     bool OpenSerial4();
 
+    bool self_checking();
+    bool test_init();
+
     // 0   ok
     // -1  timeout
     // -2  error
-    Ret_Value  Pressure_Adjust(const TestExpect& expect);
+    Ret_Value  PositivePressure_Add(const TestExpect& expect);
 
     // 0   ok
     // -1  timeout
     // -2  error
-    Ret_Value  Pressure_RoughAdjust(const TestExpect& expect);
+    Ret_Value  PositivePressure_Add_V2(const TestExpect& expect);
 
     // 0   ok
     // -1  timeout
     // -2  error
     Ret_Value  Pressure_Relief(const TestExpect& expect);
+    Ret_Value  Pressure_Relief();
 
+    // 0   ok
+    // -1  timeout
+    // -2  error
+    Ret_Value  Pressure_Keep(int keeptime, float& start_value, float& end_value);
 
-    //0 pass
-    //-1 nopass
-    Ret_Value  Pressure_Keep(int keeptime, float threshold, float& delta);
 
 
     int make_messagebox(Test_Direction direction, Test_Step step, Ret_Value ret_v);
 
 
-   QSerialPort * m_SerialPort3;
-   QSerialPort * m_SerialPort4;
-   QMutex        m_Serial3mutex;
-   QMutex        m_Serial4mutex;
+   //QSerialPort * m_SerialPort3;
+   //QSerialPort * m_SerialPort4;
+   //QMutex        m_Serial3mutex;
+   //QMutex        m_Serial4mutex;
    //QSignalSpy    m_spy3
    SerialUi      m_SerialUi3;
    SerialUi      m_SerialUi4;
@@ -187,7 +174,8 @@ private:
    bool          m_bRunning;
 
    Tanker        m_tank;
-   QString       m_standardname;
+   //QString       m_standardname;
+   Standard      m_standard;
    Report        m_report;
 
    QList<float>  m_pressurelist; //用来计算平均压力

+ 8 - 2
ValveTest.pro

@@ -14,14 +14,17 @@ SOURCES += \
         DLog.cpp \
         Modbus.cpp \
         Msgbox.cpp \
+        PressureSensor.cpp \
         Standard.cpp \
         TestService.cpp \
+        ballvalve.cpp \
         main.cpp \
         pid.cpp \
         report.cpp \
         serialport.cpp \
         serialui.cpp \
-        tank.cpp
+        tank.cpp \
+        valve.cpp
 
 RESOURCES += qml.qrc
 RC_ICONS += $$PWD/valve.ico
@@ -43,12 +46,15 @@ HEADERS += \
     DLog.h \
     Modbus.h \
     Msgbox.h \
+    PressureSensor.h \
     Standard.h \
     TestService.h \
+    ballvalve.h \
     pid.h \
     report.h \
     serialport.h \
     serialui.h \
-    tank.h
+    tank.h \
+    valve.h
 
 DISTFILES +=

+ 4 - 3
ValveTest.pro.user

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 8.0.0, 2023-03-20T14:00:05. -->
+<!-- Written by QtCreator 8.0.0, 2023-05-07T21:43:36. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
@@ -238,8 +238,9 @@
     <valuelist type="QVariantList" key="CustomOutputParsers"/>
     <value type="int" key="PE.EnvironmentAspect.Base">2</value>
     <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
-    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/Code/QTapps/ValveTest/ValveTest.pro</value>
-    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">D:/Code/QTapps/ValveTest/ValveTest.pro</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">ValveTest2</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/Code/QTapps/VRS/ValveTest.pro</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">D:/Code/QTapps/VRS/ValveTest.pro</value>
     <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
     <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
     <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>

+ 198 - 0
ballvalve.cpp

@@ -0,0 +1,198 @@
+#include "ballvalve.h"
+#include "Modbus.h"
+#include <QTimer>
+#include <QElapsedTimer>
+
+BallValve::BallValve(SerialUi* pSerial)
+{
+    m_pSerial = pSerial;
+}
+
+bool BallValve::check_crc(QByteArray data)
+{
+    int size = data.size();
+    unsigned short crc1 =0, crc2= 0;
+
+    unsigned char crc_h = data.at(size-2);
+    unsigned char crc_l = data.at(size-1);
+
+    crc1 = (crc_h <<8) |crc_l;
+    crc2 = CRC16_MODBUS((unsigned char *)data.data(),data.size()-2);
+
+     if(crc1 == crc2){
+        return true;
+     }else{
+         return false;
+     }
+
+
+}
+
+//设置阀门的开度值 A (0--1000) 表示:(A/10)%
+bool BallValve::SetPosition(unsigned short value)
+{
+    QByteArray tx_buf;
+    char zero = 0x00;
+    QElapsedTimer  timer;
+    timer.start();
+
+    tx_buf.append(BALLVALVE_BUS_ADDRESS);
+    tx_buf.append(0x06);
+    tx_buf.append(zero);
+    tx_buf.append(0x02);
+
+    char c_high = (value>>8)&0xff;
+    char c_low = (value)&0xff;
+
+    tx_buf.append(c_high);
+    tx_buf.append(c_low);
+
+    unsigned short crc;
+
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());
+
+    //tx_buf.append(crc&0xff);
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        if(check_crc(rx_buf)){
+            return true;
+        }else{
+            qDebug("SetPosition <<< check crc failed");
+            return false;
+        }
+    }else{
+        qDebug("SetPosition <<< no data received use time: %lld ms", timer.elapsed());
+        return false;
+    }
+
+}
+
+bool BallValve::GetWorkStatus(unsigned char& status)
+{
+    QByteArray tx_buf;
+    char zero = 0x00;
+
+    tx_buf.append(BALLVALVE_BUS_ADDRESS);
+    tx_buf.append(0x04);
+
+    tx_buf.append(zero);
+    tx_buf.append(0x01);
+
+    tx_buf.append(zero);
+    tx_buf.append(0x01);
+
+    unsigned short crc;
+
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());
+
+    //tx_buf.append(crc&0xff);
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        if(check_crc(rx_buf)){
+
+            status = rx_buf.at(4);
+
+            return true;
+        }else{
+            qDebug("GetWorkStatus <<< check crc failed");
+            return false;
+        }
+    }else{
+        qDebug("GetWorkStatus <<< no data received ");
+        return false;
+    }
+}
+
+bool BallValve::GetPosition(unsigned short& value)
+{
+    QByteArray tx_buf;
+    char zero = 0x00;
+
+    tx_buf.append(BALLVALVE_BUS_ADDRESS);
+    tx_buf.append(0x04);
+
+    tx_buf.append(zero);
+    tx_buf.append(0x14);
+
+    tx_buf.append(zero);
+    tx_buf.append(0x01);
+
+    unsigned short crc;
+
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());
+
+    //tx_buf.append(crc&0xff);
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        if(check_crc(rx_buf)){
+
+            unsigned char dath = rx_buf.at(3);
+            unsigned char datl = rx_buf.at(4);
+            value = (dath << 8)|datl;
+
+            return true;
+        }else{
+            qDebug("GetPosition <<< check crc failed");
+            return false;
+        }
+    }else{
+        qDebug("GetPosition <<< no data received ");
+        return false;
+    }
+}
+
+
+bool BallValve::GetSP(unsigned char& status, unsigned short& value)
+{
+    QByteArray tx_buf;
+    char zero = 0x00;
+
+    tx_buf.append(BALLVALVE_BUS_ADDRESS);
+    tx_buf.append(0x04);
+
+    tx_buf.append(zero);
+    tx_buf.append(0x52);
+
+    tx_buf.append(zero);
+    tx_buf.append(0x02);
+
+    unsigned short crc;
+
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());
+
+    //tx_buf.append(crc&0xff);
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        if(check_crc(rx_buf)){
+
+            status = rx_buf.at(4);
+            unsigned char dath = rx_buf.at(5);
+            unsigned char datl = rx_buf.at(6);
+            value = (dath << 8)|datl;
+
+            return true;
+        }else{
+            qDebug("GetSP <<< check crc failed");
+            return false;
+        }
+    }else{
+        qDebug("GetSP <<< no data received ");
+        return false;
+    }
+}

+ 35 - 0
ballvalve.h

@@ -0,0 +1,35 @@
+#ifndef BALLVALVE_H
+#define BALLVALVE_H
+
+#include "serialui.h"
+
+
+#define BALLVALVE_STATUS_OPENING (0xAA)
+#define BALLVALVE_STATUS_CLOSING (0xBB)
+#define BALLVALVE_STATUS_OPENEND (0xAC)
+#define BALLVALVE_STATUS_CLOSEEND (0xBC)
+#define BALLVALVE_STATUS_BREAK (0x00)
+#define BALLVALVE_STATUS_FAULT (0xEA)
+
+#define REGADDR_WORKSTATUS      (0X0001)
+#define REGADDR_CONTROL         (0X0002)
+#define REGADDR_POSITION        (0X0014)
+#define REGADDR_STATUS_POSITION (0X0052)
+
+
+class BallValve
+{
+public:
+    BallValve(SerialUi* pSerial);
+    bool SetPosition(unsigned short value);  //设置阀门的开度值 A (0--1000) 表示:(A/10)%
+    bool GetWorkStatus(unsigned char& status);
+    bool GetPosition(unsigned short& value);
+    //bool Break();
+    bool GetSP(unsigned char& status, unsigned short& value);
+
+private:
+    SerialUi* m_pSerial;
+    bool check_crc(QByteArray data);
+};
+
+#endif // BALLVALVE_H

+ 1 - 1
main.cpp

@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
 #endif
     QApplication app(argc, argv);
 
-    //qInstallMessageHandler(myMsgOutput);
+    qInstallMessageHandler(myMsgOutput);
     DLog_Init();
 
     //QMessageBox::critical(NULL, "critical", "Content", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);

+ 221 - 18
pid.cpp

@@ -8,12 +8,21 @@
 
 using namespace std;
 
+#define STAGE_INIT (0)
+#define STAGE_LOW  (1)
+#define STAGE_MID  (2)
+#define STAGE_HIGH (3)
+
 class PIDImpl
 {
     public:
-        PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki );
+        PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki);
+        PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI);
+        PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep);
         ~PIDImpl();
         double calculate( double setpoint, double pv );
+        double calculate_v2( double setpoint, double pv );
+        void reset();
 
     private:
         double _dt;
@@ -24,16 +33,45 @@ class PIDImpl
         double _Ki;
         double _pre_error;
         double _integral;
+        double _maxI;
+        double _maxStep;
+        double _pre_output;
+
+        double _start_pv;
+        double _critical_output;
+        int    _stage;
 };
 
-PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki )
+PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki)
 {
     pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki);
 }
+
+PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI)
+{
+    pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI);
+}
+
+PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep)
+{
+    pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI, maxStep);
+}
+
 double PID::calculate( double setpoint, double pv )
 {
     return pimpl->calculate(setpoint,pv);
 }
+
+double PID::calculate_v2( double setpoint, double pv )
+{
+    return pimpl->calculate_v2(setpoint,pv);
+}
+
+void PID::reset()
+{
+    return pimpl->reset();
+}
+
 PID::~PID()
 {
     delete pimpl;
@@ -43,7 +81,7 @@ PID::~PID()
 /**
  * Implementation
  */
-PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki ) :
+PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki) :
     _dt(dt),
     _max(max),
     _min(min),
@@ -53,8 +91,58 @@ PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, doubl
     _pre_error(0),
     _integral(0)
 {
+    _maxI = 0;
+    _maxStep = 0;
+
+    _pre_output = 0;
+    _start_pv = 0;
+    _critical_output = 0;
+    _stage = STAGE_INIT;
 }
 
+/**
+ * Implementation
+ */
+PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI) :
+    _dt(dt),
+    _max(max),
+    _min(min),
+    _Kp(Kp),
+    _Kd(Kd),
+    _Ki(Ki),
+    _pre_error(0),
+    _integral(0),
+    _maxI(maxI)
+{
+    _maxStep = 0;
+    _pre_output = 0;
+    _start_pv = 0;
+    _critical_output = 0;
+    _stage = STAGE_INIT;
+}
+
+/**
+ * Implementation
+ */
+PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep) :
+    _dt(dt),
+    _max(max),
+    _min(min),
+    _Kp(Kp),
+    _Kd(Kd),
+    _Ki(Ki),
+    _pre_error(0),
+    _integral(0),
+    _maxI(maxI),
+    _maxStep(maxStep)
+{
+    _pre_output = 0;
+    _start_pv = 0;
+    _critical_output = 0;
+    _stage = STAGE_INIT;
+}
+
+
 double PIDImpl::calculate( double setpoint, double pv )
 {
 
@@ -65,33 +153,76 @@ double PIDImpl::calculate( double setpoint, double pv )
     double Pout = _Kp * error;
 
     // Integral term
-    if(abs(error) > 3.0){
-        _integral = 0;
-    }else{
-        double _error = 0;
-        if(_integral > 30){
-            if(error >=0 )
-                _error = 0;
-            else
-                _error = error;
-        }else{
-            _error = error;
+    _integral += error * _dt;
+
+    double Iout = _Ki * _integral;
+
+    //积分限幅
+    if(_maxI > 0){
+        if(Iout > _maxI){
+            Iout = _maxI;
+        }else if(Iout < -_maxI){
+            Iout = -_maxI;
         }
+    }
+
+
+    // Derivative term
+    double derivative = (error - _pre_error) / _dt;
+    double Dout = _Kd * derivative;
 
-        _error = error;
+     qDebug("calculate : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
+    // Calculate total output
+    //double output = Pout + Iout + Dout;
+    double output = Pout + Iout ;//+ Dout;
+
+    // Restrict to max/min
+    if( output > _max )
+        output = _max;
+    else if( output < _min )
+        output = _min;
+
+    // Save error to previous error
+    _pre_error = error;
+
+    if(_maxStep > 0){
+
+        if(output - _pre_output > _maxStep){
+            output = _pre_output + _maxStep;
+        } else if(_pre_output - output > _maxStep){
+            output = _pre_output - _maxStep;
+        }
 
-        _integral += _error * _dt;
     }
 
+
+    _pre_output = output;
+
+    return output;
+}
+
+double PIDImpl::calculate_v2( double setpoint, double pv )
+{
+
+    // Calculate error
+    double error = setpoint - pv;
+
+    // Proportional term
+    double Pout = _Kp * error;
+
+    // Integral term
+    _integral += error * _dt;
+
     double Iout = _Ki * _integral;
 
     // Derivative term
     double derivative = (error - _pre_error) / _dt;
     double Dout = _Kd * derivative;
 
-     //qDebug("calculate : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
+     qDebug("calculate_V2 : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
     // Calculate total output
-    double output = Pout + Iout + Dout;
+    //double output = Pout + Iout + Dout;
+    double output = Pout + Iout ;//+ Dout;
 
     // Restrict to max/min
     if( output > _max )
@@ -102,9 +233,81 @@ double PIDImpl::calculate( double setpoint, double pv )
     // Save error to previous error
     _pre_error = error;
 
+    //belows add by avansguo
+    if(STAGE_INIT == _stage){
+        _start_pv = pv;
+        _stage = STAGE_LOW;
+    }else{
+        if(pv < _start_pv){
+            _start_pv = pv;
+            qDebug("calculate _start_pv: %f ", _start_pv);
+        }
+    }
+
+    if(_critical_output < 1.0){
+        if(derivative <= (-0.02)){ //压力开始增加了,记录前值作为临界值
+            _critical_output = _pre_output;
+            qDebug("calculate _critical_output: %f ", _critical_output);
+        }
+    }
+
+    double _distance = 0;
+    if(setpoint - _start_pv < 0.5){
+        _distance = 1;
+    }else{
+        _distance = error/(setpoint - _start_pv);
+    }
+
+
+    if(_distance <= 0.2){
+        output = _critical_output + (_distance+0.1)*( _pre_output - _critical_output);
+    }else if((_distance > 0.2) &&(_distance <= 0.5)){
+
+        if(derivative > (-0.02)){ //压力不变或在下降
+
+        }else if(derivative < (-0.2)){
+            output = _pre_output+Dout;
+            _integral = output;
+        }{
+            output = _pre_output;
+            _integral = output;
+        }
+
+    }else{
+
+        if(derivative < (-0.2)){
+            output = _pre_output+Dout;
+            _integral = output;
+        }else if(derivative > (-0.02)){ //压力不变或在下降
+            //解决当 开始压力与初始压力差距太小, 积分太慢的问题
+            if(output-_pre_output < 2){
+                output = _pre_output+2;
+                _integral = output;
+            }
+        }else{
+            output = _pre_output;
+            _integral = output;
+        }
+
+        //
+
+    }
+
+    _pre_output = output;
+
     return output;
 }
 
+void PIDImpl::reset()
+{
+    _pre_error = 0;
+    _integral = 0;
+    _pre_output = 0;
+    _start_pv = 0;
+    _critical_output = 0;
+    _stage = STAGE_INIT;
+}
+
 PIDImpl::~PIDImpl()
 {
 }

+ 19 - 1
pid.h

@@ -12,10 +12,28 @@ class PID
         // dt -  loop interval time
         // max - maximum value of manipulated variable
         // min - minimum value of manipulated variable
-        PID( double dt, double max, double min, double Kp, double Kd, double Ki );
+        PID( double dt, double max, double min, double Kp, double Kd, double Ki);
+
+        // Kp -  proportional gain
+        // Ki -  Integral gain
+        // Kd -  derivative gain
+        // dt -  loop interval time
+        // max - maximum value of manipulated variable
+        // min - minimum value of manipulated variable
+        //maxI - maximum value of Intergrate
+        PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI);
+
+        PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep);
+
 
         // Returns the manipulated variable given a setpoint and current process value
         double calculate( double setpoint, double pv );
+
+        // Returns the manipulated variable given a setpoint and current process value
+        double calculate_v2( double setpoint, double pv );
+
+        //
+        void reset();
         ~PID();
 
     private:

+ 168 - 54
report.cpp

@@ -23,10 +23,27 @@ QString g_bookmark_test_picture[MAX_COMPARTMENT_NUM] = {BOOKMARK_TEST_PICTURE_1,
 QString g_bookmark_systest_picture[MAX_COMPARTMENT_NUM] = {BOOKMARK_SYSTEST_PICTURE_1,BOOKMARK_SYSTEST_PICTURE_2,BOOKMARK_SYSTEST_PICTURE_3, BOOKMARK_SYSTEST_PICTURE_4};
 QString g_bookmark_valvetest_picture[MAX_COMPARTMENT_NUM] = {BOOKMARK_VALVETEST_PICTURE_1,BOOKMARK_VALVETEST_PICTURE_2,BOOKMARK_VALVETEST_PICTURE_3, BOOKMARK_VALVETEST_PICTURE_4};
 
-
+QString g_bookmark_vrs_check[VRS_VISUAL_INSPECTION_ITEMS_NUM][3]={
+    {BOOKMARK_VRS_CHECK_ITEMS_1_0, BOOKMARK_VRS_CHECK_ITEMS_1_1, BOOKMARK_VRS_CHECK_ITEMS_1_2},
+    {BOOKMARK_VRS_CHECK_ITEMS_2_0, BOOKMARK_VRS_CHECK_ITEMS_2_1, BOOKMARK_VRS_CHECK_ITEMS_2_2},
+    {BOOKMARK_VRS_CHECK_ITEMS_3_0, BOOKMARK_VRS_CHECK_ITEMS_3_1, BOOKMARK_VRS_CHECK_ITEMS_3_2},
+    {BOOKMARK_VRS_CHECK_ITEMS_4_0, BOOKMARK_VRS_CHECK_ITEMS_4_1, BOOKMARK_VRS_CHECK_ITEMS_4_2},
+    {BOOKMARK_VRS_CHECK_ITEMS_5_0, BOOKMARK_VRS_CHECK_ITEMS_5_1, BOOKMARK_VRS_CHECK_ITEMS_5_2},
+    {BOOKMARK_VRS_CHECK_ITEMS_6_0, BOOKMARK_VRS_CHECK_ITEMS_6_1, BOOKMARK_VRS_CHECK_ITEMS_6_2},
+    {BOOKMARK_VRS_CHECK_ITEMS_7_0, BOOKMARK_VRS_CHECK_ITEMS_7_1, BOOKMARK_VRS_CHECK_ITEMS_7_2},
+    {BOOKMARK_VRS_CHECK_ITEMS_8_0, BOOKMARK_VRS_CHECK_ITEMS_8_1, BOOKMARK_VRS_CHECK_ITEMS_8_2}
+};
+
+QString g_bookmark_bls_check[BLS_VISUAL_INSPECTION_ITEMS_NUM][3]={
+    {BOOKMARK_BLS_CHECK_ITEMS_1_0, BOOKMARK_BLS_CHECK_ITEMS_1_1, BOOKMARK_BLS_CHECK_ITEMS_1_2},
+    {BOOKMARK_BLS_CHECK_ITEMS_2_0, BOOKMARK_BLS_CHECK_ITEMS_2_1, BOOKMARK_BLS_CHECK_ITEMS_2_2},
+    {BOOKMARK_BLS_CHECK_ITEMS_3_0, BOOKMARK_BLS_CHECK_ITEMS_3_1, BOOKMARK_BLS_CHECK_ITEMS_3_2},
+    {BOOKMARK_BLS_CHECK_ITEMS_4_0, BOOKMARK_BLS_CHECK_ITEMS_4_1, BOOKMARK_BLS_CHECK_ITEMS_4_2},
+    {BOOKMARK_BLS_CHECK_ITEMS_5_0, BOOKMARK_BLS_CHECK_ITEMS_5_1, BOOKMARK_BLS_CHECK_ITEMS_5_2}
+};
 
 #define REPORT_TEMPLATES_PATH  "D:/VaporRecoverySystemTest/Templates/"
-#define REPORT_TEMPLATES_NAME  "report.dotx"
+#define REPORT_TEMPLATES_NAME  "report_v2.dotx"
 
 Report::Report()
 {
@@ -96,6 +113,47 @@ bool Report::make_Word(Tanker& tanker, QString word_path, QString pic_dir)
         bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
     }
 
+    //外观检查项
+    for(int i=0; i<VRS_VISUAL_INSPECTION_ITEMS_NUM; i++){
+        int check_value = tanker.vrs_results[i];
+        if(check_value > 2 ) check_value = 2;
+        if(check_value < 0 ) check_value = 0;
+        //qDebug()<<g_bookmark_vrs_check[i][check_value];
+
+        bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_vrs_check[i][check_value]);
+        if(!bookmark->isNull())
+        {
+            QChar cc = 0x2611;
+            QString sText;
+            sText.insert(0, cc);
+            //int volume = m_tank.m_comparts[i].m_volume;
+            //QString sText=codec->toUnicode(QString::number(comp.m_volume).toStdString().c_str());                          //此处为替换内容
+            //qDebug()<<"sText";
+
+            bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+            bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+        }
+    }
+
+    for(int i=0; i<BLS_VISUAL_INSPECTION_ITEMS_NUM; i++){
+        int check_value = tanker.bls_results[i];
+        if(check_value > 2 ) check_value = 2;
+        if(check_value < 0 ) check_value = 0;
+        //qDebug()<<g_bookmark_bls_check[i][check_value];
+        bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_bls_check[i][check_value]);
+        if(!bookmark->isNull())
+        {
+            QChar cc = 0x2611;
+            QString sText;
+            sText.insert(0, cc);
+            //int volume = m_tank.m_comparts[i].m_volume;
+            //QString sText=codec->toUnicode(QString::number(comp.m_volume).toStdString().c_str());                          //此处为替换内容
+            //qDebug()<<sText;
+            bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+            bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+        }
+    }
+
     //填写每仓容量
    for(int i=0; i< tanker.compartment_num; i++){
 
@@ -110,7 +168,7 @@ bool Report::make_Word(Tanker& tanker, QString word_path, QString pic_dir)
            bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
        }
 
-       if(comp.m_result.sys_test_ok){  //完成了系统密闭性检测
+       if(comp.m_result.sys_test_finished){  //完成了系统密闭性检测
 
            //密闭性检测的初始表压
            bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_systest_startpressure[i]);
@@ -162,7 +220,7 @@ bool Report::make_Word(Tanker& tanker, QString word_path, QString pic_dir)
 
        }
 
-       if(comp.m_result.valve_test_ok){  //完成了阀门密闭性检测
+       if(comp.m_result.valve_test_finished){  //完成了阀门密闭性检测
 
            //密闭性检测的初始表压
            bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_valvetest_startpressure[i]);
@@ -312,7 +370,7 @@ bool Report::make_Word(Tanker& tanker, QString word_path, QString pic_dir)
    for(int i=0; i<tanker.compartment_num; i++){
 
        Compartment& comp = tanker.get_compartment(i);
-       if(comp.m_result.sys_test_ok){
+       if(comp.m_result.sys_test_finished){
            if(!comp.m_result.pass_sys_pressure){
                systest_pass = false;
            }
@@ -320,7 +378,7 @@ bool Report::make_Word(Tanker& tanker, QString word_path, QString pic_dir)
            nosys_testcount++;
        }
 
-       if(comp.m_result.valve_test_ok){
+       if(comp.m_result.valve_test_finished){
            if(!comp.m_result.pass_valve_pressure){
                valvetest_pass = false;
            }
@@ -331,37 +389,48 @@ bool Report::make_Word(Tanker& tanker, QString word_path, QString pic_dir)
 
    if(nosys_testcount != tanker.compartment_num){
        //系统检测结果
-       bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_SYSTEST_RESULT);
-       if(!bookmark->isNull())
-       {
-           QString sText;
-           if(systest_pass){
-               sText=codec->toUnicode("合格");
-           }else{
-               sText=codec->toUnicode("超标");
+       QChar cc = 0x2611;
+       QString sText;
+       sText.insert(0, cc);
+       if(systest_pass){
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_SYSTEST_PASS);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+           }
+       }else{
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_SYSTEST_EXCEEDED);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
            }
-           qDebug()<<sText;
-           bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
-           bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
        }
    }
 
 
    if(novalve_testcount != tanker.compartment_num){
        //阀门检测结果
-       bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_VALVETEST_RESULT);
-       if(!bookmark->isNull())
-       {
-           QString sText;
-           if(valvetest_pass){
-               sText=codec->toUnicode("合格");
-           }else{
-               sText=codec->toUnicode("超标");
+       QChar cc = 0x2611;
+       QString sText;
+       sText.insert(0, cc);
+       if(valvetest_pass){
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_VALVETEST_PASS);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+           }
+       }else{
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_VALVETEST_EXCEEDED);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
            }
-
-           bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
-           bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
        }
+
    }
 
 
@@ -470,6 +539,41 @@ bool Report::make_PDF(Tanker& tanker, QString word_path, QString pic_dir)
         bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
     }
 
+    //外观检查项
+    for(int i=0; i<VRS_VISUAL_INSPECTION_ITEMS_NUM; i++){
+        int check_value = tanker.vrs_results[i];
+        if(check_value > 2 ) check_value = 2;
+        if(check_value < 0 ) check_value = 0;
+
+        bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_vrs_check[i][check_value]);
+        if(!bookmark->isNull())
+        {
+            QChar cc = 0x2611;
+            QString sText;
+            sText.insert(0, cc);
+
+            bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+            bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+        }
+    }
+
+    for(int i=0; i<BLS_VISUAL_INSPECTION_ITEMS_NUM; i++){
+        int check_value = tanker.bls_results[i];
+        if(check_value > 2 ) check_value = 2;
+        if(check_value < 0 ) check_value = 0;
+
+        bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_bls_check[i][check_value]);
+        if(!bookmark->isNull())
+        {
+            QChar cc = 0x2611;
+            QString sText;
+            sText.insert(0, cc);
+
+            bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+            bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+        }
+    }
+
     //填写每仓容量
    for(int i=0; i< tanker.compartment_num; i++){
 
@@ -484,7 +588,7 @@ bool Report::make_PDF(Tanker& tanker, QString word_path, QString pic_dir)
            bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
        }
 
-       if(comp.m_result.sys_test_ok){  //完成了系统密闭性检测
+       if(comp.m_result.sys_test_finished){  //完成了系统密闭性检测
 
            //密闭性检测的初始表压
            bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_systest_startpressure[i]);
@@ -536,7 +640,7 @@ bool Report::make_PDF(Tanker& tanker, QString word_path, QString pic_dir)
 
        }
 
-       if(comp.m_result.valve_test_ok){  //完成了阀门密闭性检测
+       if(comp.m_result.valve_test_finished){  //完成了阀门密闭性检测
 
            //密闭性检测的初始表压
            bookmark = document->querySubObject("Bookmarks(QVariant)",g_bookmark_valvetest_startpressure[i]);
@@ -686,7 +790,7 @@ bool Report::make_PDF(Tanker& tanker, QString word_path, QString pic_dir)
    for(int i=0; i<tanker.compartment_num; i++){
 
        Compartment& comp = tanker.get_compartment(i);
-       if(comp.m_result.sys_test_ok){
+       if(comp.m_result.sys_test_finished){
            if(!comp.m_result.pass_sys_pressure){
                systest_pass = false;
            }
@@ -694,7 +798,7 @@ bool Report::make_PDF(Tanker& tanker, QString word_path, QString pic_dir)
            nosys_testcount++;
        }
 
-       if(comp.m_result.valve_test_ok){
+       if(comp.m_result.valve_test_finished){
            if(!comp.m_result.pass_valve_pressure){
                valvetest_pass = false;
            }
@@ -705,36 +809,46 @@ bool Report::make_PDF(Tanker& tanker, QString word_path, QString pic_dir)
 
    if(nosys_testcount != tanker.compartment_num){
        //系统检测结果
-       bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_SYSTEST_RESULT);
-       if(!bookmark->isNull())
-       {
-           QString sText;
-           if(systest_pass){
-               sText=codec->toUnicode("合格");
-           }else{
-               sText=codec->toUnicode("超标");
+       QChar cc = 0x2611;
+       QString sText;
+       sText.insert(0, cc);
+       if(systest_pass){
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_SYSTEST_PASS);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+           }
+       }else{
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_SYSTEST_EXCEEDED);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
            }
-           qDebug()<<sText;
-           bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
-           bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
        }
    }
 
 
    if(novalve_testcount != tanker.compartment_num){
        //阀门检测结果
-       bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_VALVETEST_RESULT);
-       if(!bookmark->isNull())
-       {
-           QString sText;
-           if(valvetest_pass){
-               sText=codec->toUnicode("合格");
-           }else{
-               sText=codec->toUnicode("超标");
+       QChar cc = 0x2611;
+       QString sText;
+       sText.insert(0, cc);
+       if(valvetest_pass){
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_VALVETEST_PASS);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
+           }
+       }else{
+           bookmark = document->querySubObject("Bookmarks(QVariant)",BOOKMARK_VALVETEST_EXCEEDED);
+           if(!bookmark->isNull())
+           {
+               bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
+               bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
            }
-
-           bookmark->dynamicCall("Select(void)");                             //选中要选中的区域
-           bookmark->querySubObject("Range")->setProperty("Text",sText);      //进行替换操作
        }
    }
 

+ 59 - 1
report.h

@@ -13,6 +13,61 @@
 #define BOOKMARK_VOLUME_3    "bm_volume_3"
 #define BOOKMARK_VOLUME_4    "bm_volume_4"
 
+
+// bookmarks for  vrs inspection check
+#define BOOKMARK_VRS_CHECK_ITEMS_1_0   "bm_vrs_check_1_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_1_1   "bm_vrs_check_1_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_1_2   "bm_vrs_check_1_2"
+
+#define BOOKMARK_VRS_CHECK_ITEMS_2_0   "bm_vrs_check_2_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_2_1   "bm_vrs_check_2_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_2_2   "bm_vrs_check_2_2"
+
+#define BOOKMARK_VRS_CHECK_ITEMS_3_0   "bm_vrs_check_3_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_3_1   "bm_vrs_check_3_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_3_2   "bm_vrs_check_3_2"
+
+#define BOOKMARK_VRS_CHECK_ITEMS_4_0   "bm_vrs_check_4_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_4_1   "bm_vrs_check_4_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_4_2   "bm_vrs_check_4_2"
+
+#define BOOKMARK_VRS_CHECK_ITEMS_5_0   "bm_vrs_check_5_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_5_1   "bm_vrs_check_5_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_5_2   "bm_vrs_check_5_2"
+
+#define BOOKMARK_VRS_CHECK_ITEMS_6_0   "bm_vrs_check_6_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_6_1   "bm_vrs_check_6_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_6_2   "bm_vrs_check_6_2"
+
+#define BOOKMARK_VRS_CHECK_ITEMS_7_0   "bm_vrs_check_7_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_7_1   "bm_vrs_check_7_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_7_2   "bm_vrs_check_7_2"
+
+#define BOOKMARK_VRS_CHECK_ITEMS_8_0   "bm_vrs_check_8_0"
+#define BOOKMARK_VRS_CHECK_ITEMS_8_1   "bm_vrs_check_8_1"
+#define BOOKMARK_VRS_CHECK_ITEMS_8_2   "bm_vrs_check_8_2"
+
+// bookmarks for  bls inspection check
+#define BOOKMARK_BLS_CHECK_ITEMS_1_0   "bm_bls_check_1_0"
+#define BOOKMARK_BLS_CHECK_ITEMS_1_1   "bm_bls_check_1_1"
+#define BOOKMARK_BLS_CHECK_ITEMS_1_2   "bm_bls_check_1_2"
+
+#define BOOKMARK_BLS_CHECK_ITEMS_2_0   "bm_bls_check_2_0"
+#define BOOKMARK_BLS_CHECK_ITEMS_2_1   "bm_bls_check_2_1"
+#define BOOKMARK_BLS_CHECK_ITEMS_2_2   "bm_bls_check_2_2"
+
+#define BOOKMARK_BLS_CHECK_ITEMS_3_0   "bm_bls_check_3_0"
+#define BOOKMARK_BLS_CHECK_ITEMS_3_1   "bm_bls_check_3_1"
+#define BOOKMARK_BLS_CHECK_ITEMS_3_2   "bm_bls_check_3_2"
+
+#define BOOKMARK_BLS_CHECK_ITEMS_4_0   "bm_bls_check_4_0"
+#define BOOKMARK_BLS_CHECK_ITEMS_4_1   "bm_bls_check_4_1"
+#define BOOKMARK_BLS_CHECK_ITEMS_4_2   "bm_bls_check_4_2"
+
+#define BOOKMARK_BLS_CHECK_ITEMS_5_0   "bm_bls_check_5_0"
+#define BOOKMARK_BLS_CHECK_ITEMS_5_1   "bm_bls_check_5_1"
+#define BOOKMARK_BLS_CHECK_ITEMS_5_2   "bm_bls_check_5_2"
+
 #define BOOKMARK_SYSTEST_STARTPRESSURE_1    "bm_sysPS_1"
 #define BOOKMARK_SYSTEST_STARTPRESSURE_2    "bm_sysPS_2"
 #define BOOKMARK_SYSTEST_STARTPRESSURE_3    "bm_sysPS_3"
@@ -34,7 +89,8 @@
 #define BOOKMARK_SYSTEST_THRESHOLD_4    "bm_sysPT_4"
 
 #define BOOKMARK_SYSTEST_RESULT  "bm_sys_result"
-
+#define BOOKMARK_SYSTEST_PASS  "bm_sys_pass"
+#define BOOKMARK_SYSTEST_EXCEEDED  "bm_sys_exceeded"
 
 #define BOOKMARK_VALVETEST_STARTPRESSURE_1    "bm_valvePS_1"
 #define BOOKMARK_VALVETEST_STARTPRESSURE_2    "bm_valvePS_2"
@@ -57,6 +113,8 @@
 #define BOOKMARK_VALVETEST_THRESHOLD_4    "bm_valvePT_4"
 
 #define BOOKMARK_VALVETEST_RESULT  "bm_valve_result"
+#define BOOKMARK_VALVETEST_PASS    "bm_valve_pass"
+#define BOOKMARK_VALVETEST_EXCEEDED  "bm_valve_exceeded"
 
 #define BOOKMARK_DATE_YEAR   "bm_year"
 #define BOOKMARK_DATE_MONTH  "bm_month"

+ 9 - 126
serialport.cpp

@@ -19,55 +19,6 @@ void SerialPort::receiveInit()
     //connect(m_serial,&QSerialPort::readyRead,this,&SerialPort::recieveData);
 }
 
-#if 0
-
-void SerialPort::recieveData()
-{
-    mData.clear();
-
-    //QSignalSpy spy(m_serial, SIGNAL(readyRead()));
-    //bool ret = spy.wait(600);
-    //if(ret == true){
-        mData = m_serial->readAll();
-        //while (1){
-        QThread::msleep(30);
-        mData += m_serial->readAll();
-
-        qDebug()<<"modbus received data length is : "<< mData.length();
-
-        //}
-   // }
-   // else{
-   //     qDebug()<<"modbus time out";
-   //     emit sendTimeout();
-   // }
-
-    sendReceiveData();
-
-}
-
-
-void SerialPort::crcCheck(uint8_t *data, int length, uint8_t *crc_h, uint8_t *crc_l)
-{
-    int j;
-    uint16_t reg_crc=0xFFFF;
-
-    while(length--)
-    {
-        reg_crc ^= *data++;
-        for(j=0;j<8;j++)
-        {
-            if(reg_crc & 0x01) /* LSB(b0)=1 */
-                reg_crc=(reg_crc>>1) ^ 0xA001;
-            else
-                reg_crc=reg_crc >>1;
-        }
-    }
-    *crc_h = (reg_crc>>8)&0x00ff;
-    *crc_l = reg_crc&0x00ff;
-}
-#endif
-
 
 SerialPort::~SerialPort()
 {
@@ -166,74 +117,7 @@ void SerialPort::closeConnect()
     // m_serial->deleteLater();
 }
 
-/*
-bool SerialPort::serialWriteReponse(QString sendStr)
-{
 
-//    if(m_serial->isOpen() == false)
-//        return false;
-
-//    QByteArray responseData;
-//    responseData.clear();
-
-//    m_serial->readAll(); //clear buffer
-
-//    QStringList strList = sendStr.split(" ");
-//    strList.removeAll("");
-
-//    if(strList.length() == 0)
-//        return 0;
-
-//    char *sendData  = (char *) malloc(128);
-
-//    int cnt=0;
-//    QStringListIterator strIterator(strList);
-//    while (strIterator.hasNext()){
-//        QString str = strIterator.next();
-//        char value = str.toInt(nullptr, 16);
-//        sendData[cnt++] = value;
-//    }
-//    uint8_t crc_h;
-//    uint8_t crc_l;
-//    crcCheck((uint8_t *)sendData, cnt, &crc_h, &crc_l);
-//    sendData[cnt++] = crc_l;
-//    sendData[cnt++] = crc_h;
-
-//    m_serial->write(sendData,cnt);
-
-//    QSignalSpy spy(m_serial, SIGNAL(readyRead()));
-//    bool ret = spy.wait(500);
-//    if(ret == true){
-//        QByteArray responseData = m_serial->readAll();
-//        while (spy.wait(10) == true){
-//            responseData += m_serial->readAll();
-//        }
-
-//        if(responseData.length() > 2){
-//            for(int i=0 ;i<responseData.length(); i++){
-//                uint8_t value = responseData.at(i);
-//                sendData[i] = value;
-//            }
-//            crcCheck((uint8_t *)sendData, responseData.length(), &crc_h, &crc_l);
-//            if(crc_h !=0 || crc_l !=0  ){
-//                qDebug()<<"crc  error";
-//            }
-//            else{
-//                emit sendReceiveData(responseData);
-//            }
-//        }
-
-//       // emit sendReceiveData(responseData);
-//    }
-//    else{
-//        qDebug()<<"time out";
-//    }
-
-//    free(sendData);
-    return 1;
-
-}
-*/
 QByteArray SerialPort::serialRead()
 {
     return mData;
@@ -296,16 +180,10 @@ void SerialPort::receiveOnlyWrite(QByteArray sendData)
 void SerialPort::receiveWrite(QByteArray sendData)
 {
 
-   // qDebug() << QThread::currentThreadId() << "SerialPort";
-   // QList<int> data;
-    //qDebug()<<sendStr;
-
     mData.clear();
-    //QByteArray responseData;
-    //responseData.clear();
 
     if(m_serial->isOpen() == false){
-        sendReceiveData();
+        emit sendReceiveData();
         return  ;
     }
 
@@ -329,11 +207,16 @@ void SerialPort::receiveWrite(QByteArray sendData)
         }
     }
     else{
-        qDebug()<<"modbus time out";
-        emit sendTimeout();
+        //qDebug()<<"modbus time out";
+        mData = m_serial->readAll();
+        if(0 == mData.size()){
+            qDebug()<<"modbus time out";
+            emit sendTimeout();
+        }
+
     }
 
-    sendReceiveData();
+    emit sendReceiveData();
 
 #endif
 

+ 6 - 8
serialui.cpp

@@ -58,9 +58,11 @@ void SerialUi::closeConnect()
 
 QByteArray SerialUi::serialWriteReponse(QByteArray sendData)
 {
-   // QMutexLocker locker(&mutex);
+    QMutexLocker locker(&mutex);
+
+    //qDebug() << __TIME__;
+    //qDebug("serialWriteReponse enter addr:0x%x ", sendData.at(0));
 
-    //qDebug() << QThread::currentThreadId() << "SerialUi";
     QByteArray data;
     if(mSerialPort->getOpenStatus() == false)
         return  data;
@@ -71,12 +73,8 @@ QByteArray SerialUi::serialWriteReponse(QByteArray sendData)
     if(ret == true)
         data = mSerialPort->serialRead();
 
-    //    emit sendWrite(sendStr);
-    //    //void sendReponse(QList<int> data);
-    //    QSignalSpy spy(mSerialWrite, SIGNAL(sendReponse()));
-    //    bool ret = spy.wait(800);
-    //    if(ret == true)
-    //        QList<int> data = mSerialWrite->readAll();
+    //qDebug() << __TIME__;
+    //qDebug("serialWriteReponse leave data.size: %d ", data.size());
 
     return  data;
 }

+ 4 - 4
tank.cpp

@@ -43,7 +43,7 @@ Compartment::~Compartment()
 
 }
 
-int Compartment::get_Roughadjust_timeout()
+int Compartment::get_addpressure_timeout()
 {
     int timeout = 0;
 
@@ -93,8 +93,8 @@ void Compartment::clear_result()
 {
     m_result.pass_sys_pressure = false;
     m_result.pass_valve_pressure = false;
-    m_result.sys_test_ok = false;
-    m_result.valve_test_ok = false;
+    m_result.sys_test_finished = false;
+    m_result.valve_test_finished = false;
     m_bpicReady = false;
 }
 
@@ -215,7 +215,7 @@ bool Tanker::set_item_result(const QString& jsonStr )
         for(int i=0; i<BLS_VISUAL_INSPECTION_ITEMS_NUM; i++){
            if(item_name_str == bls_visual_inspection_items[i]){
                if(value >= RESULT_QUALIFIED && value <= RESULT_NOITEM){
-                   vrs_results[i] = value;
+                   bls_results[i] = value;
                    qDebug() << "item_name:" << item_name_str;
                    qDebug() << "value:" << value;
                }

+ 3 - 3
tank.h

@@ -27,13 +27,13 @@ public:
     double sysend_pressure;
     double delta_sys_pressure;
     bool  pass_sys_pressure;
-    bool  sys_test_ok;
+    bool  sys_test_finished;
 
     double valvestart_pressure;
     double valveend_pressure;
     double delta_valve_pressure;
     bool  pass_valve_pressure;
-    bool  valve_test_ok;
+    bool  valve_test_finished;
 };
 
 class Compartment{
@@ -42,7 +42,7 @@ public:
     ~Compartment();
 
 
-    int get_Roughadjust_timeout();
+    int get_addpressure_timeout();
     int get_adjust_timeout();
     void clear_result();
 

+ 157 - 0
valve.cpp

@@ -0,0 +1,157 @@
+#include "valve.h"
+#include "Modbus.h"
+
+Valve::Valve(SerialUi* pSerial, int id)
+{
+    m_pSerial = pSerial;
+    m_id = id;
+}
+
+bool Valve::check_crc(QByteArray data)
+{
+    int size = data.size();
+    unsigned short crc1 =0, crc2= 0;
+
+    unsigned char crc_h = data.at(size-2);
+    unsigned char crc_l = data.at(size-1);
+
+    crc1 = (crc_h <<8) |crc_l;
+    crc2 = CRC16_MODBUS((unsigned char *)data.data(),data.size()-2);
+
+     if(crc1 == crc2){
+        return true;
+     }else{
+         return false;
+     }
+}
+
+bool Valve::Open()
+{
+    QByteArray tx_buf;
+
+    char zero = 0x00;
+    tx_buf.append(RELAY_ADDRESS);
+
+    if(ALL_VALVE == m_id){
+        tx_buf.append(0x0F);
+        tx_buf.append(zero);
+        tx_buf.append(zero);
+        tx_buf.append(zero);
+        tx_buf.append(0x04);
+        tx_buf.append(0x01);
+        tx_buf.append(0xFF);
+    }else{
+        tx_buf.append(0x05);
+        tx_buf.append(zero);
+        tx_buf.append(static_cast<char>(m_id));
+        tx_buf.append(0xFF);
+        tx_buf.append(zero);
+    }
+
+
+    unsigned short crc;
+
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());
+
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        if(check_crc(rx_buf)){
+            //qDebug("Valve_op ok  valve_id[%d], op[%d] ", id, op);
+            return true;
+        }else{
+            qDebug("Valve Open crc failed  valve_id[%d]", m_id);
+            return false;
+        }
+    }else{
+        qDebug("Valve Open no data received  valve_id[%d]", m_id);
+        return false;
+    }
+}
+
+bool Valve::Close()
+{
+    QByteArray tx_buf;
+
+    char zero = 0x00;
+    tx_buf.append(RELAY_ADDRESS);
+
+    if(ALL_VALVE == m_id){
+
+        tx_buf.append(0x0F);
+        tx_buf.append(zero);
+        tx_buf.append(zero);
+        tx_buf.append(zero);
+        tx_buf.append(0x04);
+        tx_buf.append(0x01);
+        tx_buf.append(zero);
+    }else{
+        tx_buf.append(0x05);
+        tx_buf.append(zero);
+        tx_buf.append(static_cast<char>(m_id));
+        tx_buf.append(zero);
+        tx_buf.append(zero);
+    }
+
+    unsigned short crc;
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(), tx_buf.size());
+
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+
+        if(check_crc(rx_buf)){
+            return true;
+        }else{
+            qDebug("Valve close crc failed  valve_id[%d]", m_id);
+            return false;
+        }
+    }else{
+        qDebug("Valve close no data received  valve_id[%d]", m_id);
+        return false;
+    }
+}
+
+bool Valve::ReadStatus()
+{
+    QByteArray tx_buf;
+
+    char zero = 0x00;
+    tx_buf.append(RELAY_ADDRESS);
+
+    tx_buf.append(0x04);
+    tx_buf.append(0x03);
+    tx_buf.append(0xE8);
+    tx_buf.append(zero);
+    tx_buf.append(0x14);
+
+    unsigned short crc;
+    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(), tx_buf.size());
+
+    tx_buf.append((crc>>8)&0xff);
+    tx_buf.append(crc&0xff);
+
+    QByteArray rx_buf;
+    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
+    if(rx_buf.size() > 0){
+        for(int i=0; i<rx_buf.size(); i++){
+            qDebug("ReadStatus rx_buf[%d]: 0x%X", i, rx_buf.at(i));
+        }
+
+        if(check_crc(rx_buf)){
+            return true;
+        }else{
+            qDebug("Valve ReadStatus crc failed  valve_id[%d]", m_id);
+            return false;
+        }
+    }else{
+        qDebug("Valve ReadStatus no data received  valve_id[%d]", m_id);
+        return false;
+    }
+}

+ 27 - 0
valve.h

@@ -0,0 +1,27 @@
+#ifndef VALVE_H
+#define VALVE_H
+
+#include "serialui.h"
+
+#define  VALVE_INTAKE  (0)
+#define  VALVE_VACUUM  (1)
+#define  VALVE_VENT    (2)
+
+#define  ALL_VALVE     (99)
+
+
+class Valve
+{
+public:
+    Valve(SerialUi* pSerial, int id);
+    bool Open();
+    bool Close();
+    bool ReadStatus();
+
+private:
+    SerialUi* m_pSerial;
+    int  m_id;
+    bool check_crc(QByteArray data);
+};
+
+#endif // VALVE_H