基於Linux的智慧家居的設計(5)

道亦無名發表於2015-07-26

4  軟體設計

 

軟體設計部分主要包括uboot移植、核心編譯、系統移植、裝置驅動程式設計、應用程式程式設計(QT程式設計、mysql資料庫程式設計、控制系統程式設計)、各個模組的功能函式(部分是在windows下面的IAR中實現)。

軟體部分的結構框圖如圖4-1所示:


圖4-1  軟體結構框圖

4.1  U-boot移植

由於每個作業系統在執行前必須要執行一段小程式,這個就是通常說的Bootloader,類似windows的BIOS的韌體程式[15]。通過這段程式可以初始化硬體裝置、建立記憶體空間對映圖,從而將系統引入一個合適的狀態,以便能夠最終呼叫作業系統核心準備好的正確環境[16]。Bootloader的啟動程式流程圖如圖4-2所示:


圖4-2  Bootloader的啟動程式流程圖

①下載U-boot原始碼,到網站http://www.denx.de/wiki/U-Boot下載需要的原始碼uboot1.1.6-2012-09-25.tar.gz
②建立和ARM板相適應的型別
修改頂層的Makefile工程檔案,修改編譯器的路徑如圖4-3所示:

圖4-3  編譯器的路徑

③修改相關的引數
引數包括目標板的相關的檔案;獨立於處理器體系結構的通用程式碼,例如記憶體大小的探測與故障檢測;與處理器相關的檔案,裝置驅動程式等。
④編譯並測試
執行#make smdk6410_config和#make命令如圖4-4所示

圖4-4  執行#make smdk6410_config和#make命令

編譯的時間比較長,最後生成的一個u-boot檔案,使用file u-boot命令檢視該檔案,判斷是否生成了ARM平臺可以執行的u-boot。

圖4-5  檢視u-boot檔案的屬性

將生成的u-boot檔案拷貝到SD卡上進行,然後開發板通過SD卡啟動,進入putty控制檯設定U-boot環境變數:

圖4-6  設定U-boot環境變數

這裡要檢測能夠ping通虛擬機器才能進行下一步:
使用ping 192.168.12.18

圖4-7  檢測能夠ping通虛擬機器

Linux核心雖然支援多種硬體平臺,但是對於一個嵌入式的裝置,有些功能是沒有必要的,所以要進行一些裁剪[17]。對於這個平臺需要用到的就是觸控式螢幕,GPIO口,乙太網,串列埠,攝像頭,NandFlash這幾個主要驅動程式。只需要將用到的東西裁剪下來就夠了。下面是核心裁剪的基本思路:

①下載並解壓原始碼包,本次課題使用的Linux-3.0.1版本的原始碼;

②配置編譯平臺修改Makefile,主要的是體系結構和交叉編譯變數的定義。如圖4-8所示:

4-8  修改makefile

③裁剪核心

執行命令:

#make menuconfig

圖4-10  核心裁剪介面

進入到Device Drivers上進行配置自己想要的資訊其中空格代表的是不需要編譯,“*”代表的是必須編譯的,“M”是可載入的選項。執行make zImage製作核心映象,生成的核心映象在arch/arm/boot/目錄下:

通過tftp服務燒寫核心映象到NandFlash上。

4.3  根檔案系統的製作

利用OK6410開發提供的工具使用命令:

 #./mkyaffs2image-nand256m   FileSystem-Yaffs2    rootfs.yaffs2

通過tftp服務檔案系統燒寫到NandFlash中。

4.4  QT程式設計

本課題的QT程式設計有兩個部分,一個是在PC機上執行的遠端的客戶端,一個是在開發板的觸屏上執行的Qt程式。Qt開發的框架如圖4-12所示:

嵌入式Qt應用程式從開發到能夠應用的流程如圖4-13所示:


4.4.1  介面設計

OK6410板上執行的程式設計,首先做一個UI介面,這裡使用的是QWidget類設計的。QWidget類是所有使用者介面物件的基類。視窗部件是使用者介面的一個原子:他從視窗系統接受滑鼠、鍵盤、和其他事件(點觸),並且在螢幕上繪製自己的表現[18]。每一個視窗部件都是矩形,視窗部件可以被其他的父視窗蓋住不見或者被前面的部件蓋住一部分。使用qt-disgner進行佈局設計,會得到自己想要的介面效果,本系統在開發板上執行的GUI介面如圖4-14所示。

圖4-14  GUI介面

4.4.2  訊號與槽

訊號與槽機制是Qt的核心機制,訊號與槽式一種高階介面,用於物件之間的通訊[19]。當物件改變時,訊號就由該物件發射(emit)出去,指導物件所要做的全部事情,通過呼叫 QObject物件的 connect函式來將某個物件的訊號與另外一個物件的槽函式相關聯,這樣當發射者發射訊號時,接收者的槽函式將被呼叫[20]。該函式的定義如下:

bool QObject::connect ( constQObject * sender, const char * signal, const QObject * receiver, const char *member )

本課題中的電燈泡和溫溼度的觸發就是使用的這個機制,當觸屏上的一個事件電燈泡被按下的瞬間就會傳送一個訊號,呼叫電燈泡點亮的函式。訊號與槽的機制流程圖如圖4-15所示:


使用的一些訊號如下:

signals:

    void isLight(bool states);        //燈泡控制訊號

    void setTempSignal(int temp);    //溫度訊號

    void setHumSignal(int hum);     //溼度訊號

使用的槽函式如下:

private slots:

    void on_btnLed4_clicked();

    void on_btnLed3_clicked();

    voidon_btnLed2_clicked();

    void on_btnLed1_clicked();

    void readMyCom();

    void all_Led_on_writeCom();

    void all_Led_off_writeCom();

    void temphum_writeCom();

    void setLightStates(bool states);

    void setTempSlot(int temp);

void setHumSlot(int hum);

訊號與槽的連線函式如下:

MainWin::MainWin(QWidget*parent) :

    QWidget(parent),

    ui(new Ui::MainWin)

{

    ui->setupUi(this);

    startInit();

    ……

    connect(tempTimer, SIGNAL(timeout()), this,SLOT(temphum_writeCom()));

    connect(this,SIGNAL(isLight(bool)),this,SLOT(setLightStates(bool)));

   connect(this,SIGNAL(setTempSignal(int)),this,SLOT(setTempSlot(int)));

   connect(this,SIGNAL(setHumSignal(int)),this,SLOT(setHumSlot(int)));

……

}

4.5  智慧電器的控制設計

本課題的以室內的空調作為一個智慧電器,設定一個溫度閾值,當溫度到達這個閾值的時候啟動空調,比如一般夏天室內的溫度為25攝氏度,如果溫度超過了25攝氏度,那麼空調就會自動開啟。通過週期性的獲取室內當前的溫度,並且對接受的資訊與設定的值進行比對當溫度到達適宜的溫度的時候自動停止,這樣可以節約用電。這裡的資料處理是DHT11獲取環境中的溫度,傳送到OK6410開發板,與設定的溫度進行對比,如果溫度超出了閾值,那麼就傳送相應的指令。同時在觸控式螢幕的介面上可以看到空調相應的狀態。圖4-16是溫度控制的一個流程圖。


4.5.1  智慧家居Zigbee閘道器的程式設計

由於ARM閘道器和Zigbee協調器之間是基於RS232串列埠通訊,所以為了解決串列埠通訊的問題,本課題採用的是波特率為115200,資料位為8,停止位為1,無校驗資料位。涉及到資料通訊就得設計一個資料的幀格式,這裡的幀格式設定為:幀頭+節點ID碼+模組的ID碼+資料(CommandH + CommandL)+幀尾。

這個資料幀的詳細說明可以用DHT11溫溼度感測器來描述,例如一個溫度資料幀為:

0xCC,0xEE,0x01,0x03,0x01,0x00,0x00,0xFF


模組ID用於區別是那個模組由燈的模組、溫溼度模組、電機模組等。這些資料只是傳送的命令,那麼接受資料幀格式有些區別的在於幀頭,資料為0xEE 0xCC例如接收到一個資料幀為:

0xEE,0xCC,0x01,0x03,0x01,0x01,0x01,0xFF


Qt串列埠程式設計使用的是庫函式程式設計,使用QextSerialPort類,QextSerialPort類讀取串列埠資料的方式有兩種:Polling即輪詢方式、EventDriven是指事件驅動方式[21]。但是在Linux系統中只能使用Polling方式,這種方式下串列埠讀/寫是同步的,訊號在這種狀態下是無法使用。這種方式的優點是系統開銷小,但是需要自己定義一個定時器去讀取串列埠的資料。

使用QextSerialPort實現串列埠通訊,實現串列埠資料通訊的配置工作在下面程式碼中可以集中的體現。

void MainWin::openCom()
{
    myCom = new Posix_QextSerialPort(COM, QextSerialBase::Polling);
    //這裡QextSerialBase::QueryMode應該使用QextSerialBase::Polling
    isOpen = myCom->open(QIODevice::ReadWrite);
    if(isOpen){
       // QMessageBox::information(this, tr("開啟成功"), tr("已成功開啟串列埠 ") + COM, QMessageBox::Ok);
}else{
        QMessageBox::critical(this, tr("開啟失敗"), tr("未能開啟串列埠 ") + COM + tr("\n該串列埠裝置不存在或已被佔用"), QMessageBox::Ok);
        return;
    }
    //設定波特率:115200
    myCom->setBaudRate(BAUD115200);
    //設定資料位:8位
    myCom->setDataBits(DATA_8);
    //設定校驗:無
    myCom->setParity(PAR_NONE);
    //設定停止位
    myCom->setStopBits(STOP_1);
    //開啟讀取定時器
    timer->start(timerdly);
    //設定資料流控制
    myCom->setFlowControl(FLOW_OFF);
    //設定延時
    myCom->setTimeout(TIME_OUT);
}

4.5.2  Zigbee的程式設計

Zigbee的程式設計使用了IARworkbench開發工具,實現了串列埠的通訊、燈泡的控制、風扇空調的控制、窗簾的控制、感測器的資料傳輸功能。

串列埠的使用基本步驟:

①初始化串列埠,其中包含波特率、校驗位、中斷、時脈頻率等。具體的程式碼如下:

/**************************************************************** 
   串列埠初始化函式     
***********************************************************/
void InitUart()
{
    CLKCONCMD &= ~0x40; // 設定系統時鐘源為 32MHZ晶振
    while(CLKCONSTA & 0x40);                     // 等待晶振穩定 
    CLKCONCMD &= ~0x47;                 // 設定系統主時脈頻率為 32MHZ
    PERCFG = 0x00;        //位置1 P0口 
    P0SEL = 0x3c;        //P0_2,P0_3,P0_4,P0_5用作串列埠,第二功能 
    P2DIR &= ~0XC0;      //P0 優先作為UART0 ,優先順序
    U0CSR |= 0x80;       //UART 方式 
    U0GCR |= 11;           //U0GCR與U0BAUD配合     
    U0BAUD |= 216;       // 波特率設為115200 
    UTX0IF = 0;          //UART0 TX 中斷標誌初始置位0 
    U0CSR|=0x40;            //允許接收
    IEN0|=0x84;           //開總中斷,接收中斷
}

②向傳送緩衝區傳送資料或者從接收緩衝區讀取資料。具體的程式碼如下:

/**************************************************************** 
串列埠傳送資料函式    
****************************************************************/ 
void Uart_Send_String(uchar *Data,int len) 
{
    int j; 
    for(j=0;j<len;j++) 
    { 
      U0DBUF = *Data++; 
      while(UTX0IF == 0); 
      UTX0IF = 0; 
    } 
}
/*******************串列埠接收函式***********************/
#pragma vector = URX0_VECTOR 
  __interrupt void UART0_ISR(void) 
 { 
    URX0IF = 0;    // 清中斷標誌 
    command = U0DBUF; 
    Rxdata[p]=command;
    p++;
    if ( p == 8)
    {
      p = 0;
    }
}

感測器模組、電機模組、電燈的控制主要用到的是IO口控制程式設計,使用的配置方式類似STM32的配置方式,具體的步驟如下:

①功能設定暫存器P1SEL,預設是普通IO口。0表示普通IO口,1表示第二功能

②輸入輸出配置P1DIR,0表示輸入,1表示輸出

③IO口的輸入時的電路模式配置,0表示上拉/下拉,1表示高阻態。

具體的程式碼以電燈泡為例說明:

void LEDABCD_INIT(void)
{
  P1SEL &= ~0x30; //選擇埠
  P1DIR |= 0x30;  //設定為輸出模式
  P1INP &= ~0x30;  //開啟上拉
}

4.6  製作嵌入式平臺Qt程式

由於OK6410開發板上的螢幕與PC機上的螢幕不一樣,大小和字型都要設定需要設定。因為用到的觸控式螢幕是480*272的解析度,這裡支援的中文字型為“wenquanyi”所以在main.cpp中加入以下的程式碼:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
……
    MainWin w;
#if defined(_WS_QWS) || defined(Q_WS_QWS)
    w.showFullScreen();
    QFont font("wenquanyi",12,QFont::Bold);
    a.setFont(font);
#else
    w.resize(480, 272);
#endif
……
w.show();
……
}

在終端中使用交叉編譯工具編譯並結合指令碼語言製作一個shell指令碼,使用命令:

#vim myshell.sh

在檔案中新增以下的內容:

#/bin/bash

qmake -project

/opt/qt-4.7.1/bin/qmake

make

cp SmartLife /nfsroot/FileSystem-Yaffs2/

然後更改myshell.sh的屬性使用命令:

#chmod +777 myshell.sh

執行myshell.sh就可以實現交叉編譯並將生成的可在ARM上執行的檔案。

這樣生成的SmartLife是一個ARM平臺上可以執行的檔案在putty中使用./SmartLife –qws 即可執行生成SmartLife。

4.7  遠端客戶端的程式

使用者需要使用使用者名稱和密碼才能登入,可愛的企鵝作為背景圖片,實時查詢家居中的所有情況,這樣可以通過網路遠端控制家居中的情況。

登入的介面使用對話方塊的模式來寫的呼叫了Dialog類,使用者名稱和密碼的校驗使用的是密文方式進行的,具體的程式碼如下:

void Dialog::on_loginbtn_clicked()
{
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
    if(ui->usredit->text()==tr("zhanghao")&&ui->pwdedit->text()==tr("123456"))
    {
        accept();
    }
    else
    {
    QMessageBox::warning(this,tr("warning"),tr("user name or passwd wrong"),tr("yes"),tr("no"));
    //如果不正確,彈出警告對話方塊
    ui->usredit->clear();//清空使用者名稱輸入框
    ui->pwdedit->clear();//清空密碼輸入框
    ui->usredit->setFocus();//將游標轉到使用者名稱輸入框
    }
}

背景圖片的新增使用繪圖工具將背景圖片放到工程目錄的image下,通過呼叫paintEvent()函式來時實現,具體的程式碼:

void Dialog::paintEvent(QPaintEvent *)     //介面圖片的載人,要在標頭檔案裡宣告此成員
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/image/8.JPG");
    painter.drawPixmap(0,0,400,350,pix);
}

客戶端相關的UI設計圖如圖4-17、4-18、4-19、4-20所示:


5  除錯和總結

 

5.1  家居閘道器的除錯

除錯的思路是:使用USB轉TTL串列埠,將USB轉TTL串列埠的RX與OK6410開發上的上的TXD,將USB轉串列埠的TX與OK6410開發板上的RXD,特別要注意的是要將OK6410開發板上的GND和USB轉TTL串列埠的GND要接在一起(共地很重要),之前因為這個問題浪費了很多的時間,後來實驗室的同學跟我說這個一定要共地,否則大多數時候資料傳輸會出現誤碼。然後使用串列埠除錯助手在PC機上看傳送的命令是否與自己在觸控式螢幕上的操作一致,將接收到的資料儲存在txt文件中,用記事本開啟儲存的txt文件,然後再與之前的操作所對應的命令進行比對發現這個txt文件進行比對發現完全一樣。可以得出結論1:智慧家居的ARM閘道器的串列埠可以向外界傳送指令。

同樣的在串列埠除錯助手中傳送相應的資料,如果在TFT屏上能夠實現相應的顯示結果那麼ARM閘道器串列埠可以接收外界傳送的資料。可以得出結論2:智慧家居ARM閘道器的串列埠可以正確的接受資料並做出相應的應答。

綜合結論1和結論2可以得出ARM閘道器的串列埠程式是正確的。

5.2  Zigbee除錯

在Zigbee上的串列埠要確定資料是正確的,這裡傳送的資料是每都是通過串列埠的,首先得確定傳送的資料是正確的,這裡使用的串列埠除錯助手,將傳送的資料與串列埠除錯助手上顯示的資料進行比對,如果沒有錯誤,那麼這個串列埠的傳送資料是沒有問題的。經過幾番的除錯和修改程式碼發現串列埠的資料傳送終於可以按所需要的格式的傳送資料了。接下來的便是接收資料,使用的方法是將接收到的資料傳送出來在串列埠除錯助手上顯示。但是在使用串列埠函式的時候就得給傳送處理的資料遮蔽掉,不然傳送處理的資料是無法預測的。

5.3  Zigbee與ARM之間的通訊除錯

Zigbee與ARM之間的除錯出現的問題了一些問題,用無線傳輸資料會傳送出錯誤的資訊,這裡的原因可能是程式碼的問題,因為使用無線傳輸要使用協議棧,而這個Zigbee並沒有跑協議棧,如此用無線傳輸肯定會出現問題。使用的無線串列埠數傳輸模組CC1101進行除錯發現還是有問題,其中的原因可能是時序的問題,如果要完全解決這個問題,還是有很大的困難,這個課題做到的僅僅是有線的資料傳輸。於是這個無線的傳輸失敗告終了,只能使用有線的資料傳輸來進行除錯,這樣達到了預期的效果。

5.4  實物執行的效果

智慧家居模型是使用PVC板製作而成的,在模型中有:LED做成的燈具、直流電機和PVC材料做成的空調模型、減速電機和布條做成的窗簾、光照度採集模組(光敏電阻)、溫溼度採集模組(DHT11)、門禁模組(微控制器+RFID+舵機+蜂鳴器)。

智慧家居執行(燈具全部開啟,門禁刷卡成功,溫溼度在設定的範圍內)效果圖1。如圖5-1所示:


開發板上執行的效果(4個LED燈全部亮起,可以看到溫溼度正常當前的顯示:26攝氏度,溼度為35%,設定的溫度閾值為27攝氏度,溼度為70%,當前的溫溼度均沒有超過閾值,所以空調沒有開啟)如圖5-2所示:




結 論

 

本設計中對目前國內外物聯網智慧家居系統的發展現狀和未來的發展趨勢,以及相關技術進行了詳細的分析。在現有的智慧家居系統解決方案的基礎上,提出了處理器和無線技術相結合的設計方案,並且融合了網際網路通訊技術,實現了真正意義上的物聯網,以及遠端對智慧家居系統進行實時的監控和管理。本文中主要完成了以下工作:

(1)在現有的智慧家居系統解決方案的基礎上,提出了智慧家居系統的設計方案,主要包括家庭閘道器主控制器、終端受控裝置、家庭內部控制網路、外部通訊網路四個部分。

(2)對家庭閘道器及其核心功能模組進行了詳細的分析,並且完成了電源模組、系統復位電路、序列介面電路、介面、介面、乙太網介面電路、儲存電路、介面電路的硬體設汁。

(3)在軟體設計方面主要是進行了載入程式的移植,接著在此基礎上進行了核心的移植與相應的配置工作,最後,完成了檔案系統的製作與移植以及嵌入式伺服器的移植。

(4)對家庭內部控制網路模組進行了分析,完成了客廳燈具的開關控制、家居中溫溼度監測及控制、智慧窗簾的控制。

(5)在無線網路技術的協議棧和應用開發介面函式等基礎上,實現了家庭內部控制網路之間的通訊,並在此基礎上進行了遠端控制和查詢功能的初步實現。

(6)在無線射頻(RFID)的基礎上,實現了智慧門禁的控制功能。

本文中很多可以擴充套件的地方,可以通過資料庫實現家庭中環境的儲存查詢統計等功能。同時可以通過手機簡訊接受的方式對家中的異常情況進行報警,另外還可以進行Android開發和IOS的開發。

由於本人的水平有限,在文中出現一些不足和疏忽,希望不吝賜教,歡迎批評和交流。




















相關文章