軟件設計開發筆記5:QT開發三參數溫室氣體數據記錄軟件
??最近有一個為三參數溫室氣體分析儀及其多通道換向閥箱編寫數據記錄和控制的需求。所以在這一篇中我們就來分析一下如何使用QT實現這一需求。
1、需求分析
??雖然說傳遞過來的需求只有“實現一個三參數溫室氣體分析儀及其多通道換向閥箱的數據記錄和控制”這樣一句話,但所有人都清楚實際需求并非表達的那么簡單。所以,我們首先還是來分析一下實現這樣一個軟件的具體需求。
??一方面,這個軟件需要獲取三參數溫室氣體分析儀的數據并將其記錄下來。那么我們就需要知道究竟需要哪些數據?這些數據需要記錄成什么樣的格式?這些數據是否需要處理?這些數據是否需要展現?這些數據如果展現需要以什么樣的形式展現?這些問題其實都包含在需求當中,只是沒有直接表達出來,或者說提出需求的人他也不知道該怎么表達出來。但是我們必須考慮這些問題。
??另一方面,這個軟件需要獲取多通道換向閥箱的數據并對其進行控制。同樣存在上述的哪些問題需要解決。此外對于多通道切換閥的控制也要考慮具體的方式。是采用自動控制方式還是手動控制方式。如果手動控制那還要考慮具體怎么操作。如果采用自動控制方式具體的運行邏輯有什么要求。這些問題其實也是需要開率并實現的。
??至于其它如穩定性和可靠性等方面的要求基本就得按工業標準來考慮,再次不做具體討論了。
2、設計與實現
??根據上面的分析我們來考慮如何設計這一軟件。我們考慮需要獲取分析儀和閥箱的數據,但從物理角度來說這是2個獨立的設備,所以我們通過獨立的模塊來實現它。數據記錄下來后,他們可能還需要對數據進行查看,所以我們在增加一個數據查詢的模塊。
??從外觀實現上來說,我們也是在主體框架下采用3個操作頁面來對應上述的3個模塊。這3個界面分別為:“實時數據”、“數據查詢”和“閥箱交互”,具體如下圖:

??上述的界面能夠滿足數據顯示、查詢接操作。但對于與兩臺設備通訊我們還需要配置串口的相關參數,所以我們增加一個參數配置界面,具體如下所示:

??完成界面設計后,我們考慮功能的實現。首先是分析儀數據的獲取,分析儀是RS232接口,通訊協議為廠商自定義。所以我們只需要按照廠商的協議解析數據包就可以實現數據的獲取。關鍵是數據報文不能保證每一幀都是完整無誤的,所以我們解析式需要做一些條件判斷。場上的具體協議不方便發布,這里給出主要代碼:
void AnalyserForm::DataParsing()
{
QString context;
if(rxDatas.indexOf(0x23)>=0)
{
rxDatas.remove(0,rxDatas.indexOf(0x23));
}
else
{
qDebug()<<rxDatas.size();
qDebug()<<rxDatas;
rxDatas.clear();
return;
}
if((rxDatas.indexOf(0x0D)<0)||(rxDatas.indexOf(0x0A)<0))
{
return;
}
if((rxDatas.indexOf(0x0D)<433)||(rxDatas.indexOf(0x0A)<434))
{
rxDatas.remove(0,rxDatas.indexOf(0x0A));
return;
}
QByteArrayList list=rxDatas.split(';');
datetime=list[6].trimmed().mid(14,-1);
co_d_ppb=DataConversion(list[7].trimmed());
co2_d_ppm=DataConversion(list[8].trimmed());
ch4_d_ppm=DataConversion(list[9].trimmed());
co_ppb=DataConversion(list[10].trimmed());
co2_ppm=DataConversion(list[11].trimmed());
ch4_ppm=DataConversion(list[12].trimmed());
h2o_pct=DataConversion(list[13].trimmed());
temp_cav=DataConversion(list[14].trimmed());
pres_cav=DataConversion(list[15].trimmed());
temp_box=DataConversion(list[16].trimmed());
amValues[0]=co_ppb;
amValues[1]=co_d_ppb;
amValues[2]=co2_ppm;
amValues[3]=co2_d_ppm;
amValues[4]=ch4_ppm;
amValues[5]=ch4_d_ppm;
amValues[6]=h2o_pct;
ui->lineEditCO->setText(QString::number(co_ppb));
ui->lineEditCOD->setText(QString::number(co_d_ppb));
ui->lineEditCC->setText(QString::number(co2_ppm));
ui->lineEditCCD->setText(QString::number(co2_d_ppm));
ui->lineEditCH->setText(QString::number(ch4_ppm));
ui->lineEditCHD->setText(QString::number(ch4_d_ppm));
ui->lineEditHO->setText(QString::number(h2o_pct));
if(rxDatas.indexOf(0x23,434)>0)
{
rxDatas.remove(0,rxDatas.indexOf(0x23,434));
}
else
{
rxDatas.clear();
}
}
??在分析儀的數據展示中,我們實際上還是用了曲線的顯示,所以我們需要更新數據顯示,就是在數據到來時,我們更新曲線圖。具體如下:
void AnalyserForm::UpdateCurveShow()
{
bool flagAM[8]={false,false,false,false,false,false,false,false};
QString amName[8]={"CO","CO_d","CO2","CO2_d","CH4","CH4_d","H2O","unkown"};
if(delayNum>0)
{
delayNum--;
return;
}
flagAM[3]=true;
ChartHelper::ChartDisplay(amChart1,amLineSeries1,amValues,flagAM,amName);
ui->graphicsViewCC->setChart(amChart1);
flagAM[3]=false;
flagAM[5]=true;
ChartHelper::ChartDisplay(amChart2,amLineSeries2,amValues,flagAM,amName);
ui->graphicsViewCH->setChart(amChart2);
flagAM[1]=true;
flagAM[5]=false;
ChartHelper::ChartDisplay(amChart3,amLineSeries3,amValues,flagAM,amName);
ui->graphicsViewCO->setChart(amChart3);
flagAM[1]=false;
flagAM[6]=true;
ChartHelper::ChartDisplay(amChart4,amLineSeries4,amValues,flagAM,amName);
ui->graphicsViewHO->setChart(amChart4);
}
??同時,由于存在歷史數據查詢的需求,所以我們還需要向數據庫中寫入實時數據。
??閥箱的控制及數據獲取也是一樣的,廠商定義有專用的通訊協議只需要按照協議發送和解析報文就可以。不過有一個自定義邏輯過程的需求,就是定義一個邏輯序列,這個序列可以設定指定的通道及持續時間,軟件根據這個邏輯序列自動執行。

??我們使用一個計時器來計算持續的時間,每當計時到則判斷是否進入下一步,陸續進入下一步則啟動下一步,同時間計時器的時間跨度修改為該步驟需要持續的時長。
void ValveBoxForm::CycleSendData()
{
if(!ui->checkBoxEnable->isChecked())
{
if(currentChannel==0)
{
ReadCurrentPosition();
}
ui->lineEditCurrentStep->setText(QString::number(0));
return;
}
for (int i=0;i<72;i++)
{
stepIndex=stepIndex>=72?0:stepIndex;
if(((0<preChannel[stepIndex])&&(preChannel[stepIndex]<9))&&((0<preTime[stepIndex])&&(preTime[stepIndex]<1666)))
{
WriteSerialData(stepIndex);
ui->lineEditCurrentStep->setText(QString::number(stepIndex+1));
break;
}
stepIndex++;
}
stepIndex++;
ReadCurrentPosition();
}
??上述邏輯中最多可以執行72步的預設過程。每次從頭開始執行直至最后,然后再循環執行。
3、測試與改進
??軟件的實現并不復雜,我們都只需要實現廠商定義的通訊協議就可以實現操作和數據獲取。接下來我們測試一下這個軟件。我們需要先配置好通訊的參數,然后點擊“分析儀連接”和“閥箱連接”按鈕,如果串口成功打開則會顯示藍色的“分析儀已連接”和“閥箱已連接”。
??接收到的分析儀數據解析后會顯示到數據框和數據曲線。這里我們連接分析儀一段時間后其結果如下:

??界面從上到下是二氧化碳的曲線和數值、甲烷的曲線和數值、一氧化碳的曲線和數字值以及水含量的曲線和數值。可以看出軟件實現了獲取分析儀數據的需求,并且運行良好。
??運行一段時間后我們就可以查看歷史數據,選擇起始時間和結束時間,然后點擊“數據查詢”按鈕即可檢索歷史數據,結果如下所示:

??數據查詢的時間跨度限定在一個小時以內,如果設置的時間超過1小時則只會顯示從起始時間開始的1小時的數據,余下的數據不會顯示在數據表中。
??閥箱在建立連接后,軟件會獲取閥箱的數據,并顯示在界面當中。我們在“目標通道”輸入框中輸入1~8的任意數字,然后點擊“手動切換”按鈕可實現閥門通道切換。如我們在目標通道”輸入框中輸入1,然后點擊“手動切換”按鈕將閥門切換到通道1,具體如下圖顯示:

??上圖的表格中顯示的是預置的運行邏輯,用于自動狀態時操作。選中“自動循環”復選框會啟動自動操作,按照表格中設定的邏輯運行。我們在這里選中“自動循環”復選框,軟件次序按照表中的排序進行。
4、開發總結
??這一篇中,我們設計了一個可以實現三參數溫室氣體分析儀數據獲取和閥箱操作及數據獲取的軟件。該軟件涉及到串口通訊、文件操作、數據庫操作、曲線顯示及定時器操作等主要功能。
??我們在開發之后對軟件進行的實際應用,功能上基本以及實現了用戶提出的所有需求,但性能上還是可以提高的。比如對異常數據的處理,對曲線顯示的處理等還是可以進一步細化的。
歡迎關注:

如果閱讀這篇文章讓您略有所得,還請點擊下方的【好文要頂】按鈕。
當然,如果您想及時了解我的博客更新,不妨點擊下方的【關注我】按鈕。
如果您希望更方便且及時的閱讀相關文章,也可以掃描上方二維碼關注我的微信公眾號【木南創智】

浙公網安備 33010602011771號