天天看點

嵌入式Qt-控制硬體:滑動條控制RGB燈

前面的幾篇文章,介紹Qt例程,都是和硬體無關的,Windows平台和嵌入式平台都能運作。

本篇,來測試一下Qt界面控制嵌入式平台上的硬體,以野火i.MX6ULL闆子上的RGB LED為例,實作Qt界面控制3種顔色LED的不同亮度混合顯示。

1 設計Qt滑條控制LED界面

先來看一下最終設計的界面效果:

嵌入式Qt-控制硬體:滑動條控制RGB燈

有一個按鍵作為LED的總開關,控制LED的點亮與熄滅。下面的3個滑條,控制3種顔色LED以不同的亮度點亮。右邊是一個顔色混合顯示面闆,模拟RGB三種顔色的LED以不同亮度點亮後的混合亮度。

1.1 滑條控件

Qt Creator的UI設定界面中,有水準滑條和豎直滑條控件,可以直接使用:

嵌入式Qt-控制硬體:滑動條控制RGB燈

右側的屬性窗戶可以設定滑條的取值範圍和初始值。

1.2 控件顔色

使用QPalette可以對界面顔色和控件的顔色進行自定義設定

  • QPalete::Window——通常指視窗部件的背景色
  • QPalette::WindowText——通常指視窗不見的前景色
  • QPalette::Base——底色
  • QPalette::Button——指按鈕視窗部件的背景色
  • QPalette::ButtonText——指按鈕視窗部件的前景色
  • QPalette::Text——文本輸入視窗的前景色
  • QPalette::Background——背景色
  • QPalette::Foreground——前景色(界面中文字的統一顔色)
嵌入式Qt-控制硬體:滑動條控制RGB燈

界面的顔色

整個UI界面的顔色可以這樣設定:

QPalette color = palette();//控制窗體顔色
color.setColor(QPalette::Background, QColor(255,255,255));//背景顔色
//color.setColor(QPalette::Foreground, QColor(0,0,255,255));//前景顔色
setPalette(color);      

這裡就是把整個界面的顔色設定為純白色

控件的顔色

例如文本标簽控件(QLabel)的文字顔色可以這樣設定:

QPalette pal;
pal.setColor(QPalette::WindowText,Qt::red);
ui->label_R->setPalette(pal); //設定滑條左側的R字型為紅色
pal.setColor(QPalette::WindowText,Qt::green);
ui->label_G->setPalette(pal);
pal.setColor(QPalette::WindowText,Qt::blue);
ui->label_B->setPalette(pal);      

顔色混合面闆控件(QTextBrowser)的面闆顔色可以這樣設定:

QColor color;
int R = ui->Slider_R->value(); //讀取滑條的目前值
int G = ui->Slider_G->value();
int B = ui->Slider_B->value();
color.setRgb(R, G, B); //顔色混合
QPalette pal;
pal.setColor(QPalette::Base, color);
ui->textBrowser->setPalette(pal); //顯示到面闆上      

1.3 滑條UI界面代碼編寫

構造函數

LedWidget::LedWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::LedWidget)
{
    ui->setupUi(this);
    ui->Value_R->setText(QString::number(ui->Slider_R->value()));
    ui->Value_G->setText(QString::number(ui->Slider_G->value()));
    ui->Value_B->setText(QString::number(ui->Slider_B->value()));

    QPalette color = palette();//控制窗體顔色
    color.setColor(QPalette::Background, QColor(255,255,255));//背景顔色
    setPalette(color);
}      

滑條滑動時的槽函數

void LedWidget::on_Slider_R_valueChanged(int value)
{
    ui->Value_R->setText(QString::number(value));
    UpdateShowColor();
}

void LedWidget::on_Slider_G_valueChanged(int value)
{
    ui->Value_G->setText(QString::number(value));
    UpdateShowColor();
}

void LedWidget::on_Slider_B_valueChanged(int value)
{
    ui->Value_B->setText(QString::number(value));
    UpdateShowColor();
}      

更新RGB三種顔色的混合顯示

void LedWidget::UpdateShowColor()
{
    QColor color;
    int R = ui->Slider_R->value();
    int G = ui->Slider_G->value();
    int B = ui->Slider_B->value();
    color.setRgb(R, G, B);
    QPalette pal;
    pal.setColor(QPalette::Base, color);
    ui->textBrowser->setPalette(pal);
}      

2 闆子上RGB LED的控制

2.1 i.MX6ULL系統燒錄

本篇的RGB LED測試,需要先燒錄野火i.MX6ULL自帶的系統固件,因為該系統已有Qt運作環境,且對應的RGB LED的驅動程式也已配置好了,這樣就不需要再自己寫RGB LED的驅動程式了,我們隻寫好Qt的應用程式,實作對闆子上LED的控制即可。

燒寫方法可參考:​​https://doc.embedfire.com/linux/imx6/quick_start/zh/latest/quick_start/install_debian/install_debian.html#​​

可以燒寫到SD卡中

嵌入式Qt-控制硬體:滑動條控制RGB燈

燒寫到eMMC中

因為在SD卡中運作系統,無法使用WIFI連網,可以通過fire-config工具将SD卡的系統燒寫到eMMC中,刷機過程可參考:

​​https://doc.embedfire.com/linux/imx6/linux_base/zh/latest/linux_basis/fire-config_brief/fire-config_brief.html#id7​​

嵌入式Qt-控制硬體:滑動條控制RGB燈

設定之後,選擇重新開機,重新開機後的系統将自動進行從SD卡到EMMC的刷機。刷機過程大約2分鐘左右。刷機完成後,控制台會重新進入序列槽登入頁面, 此時觀察開發闆的LED燈,如果LED在持續閃爍,說明刷機成功。然後調整撥碼開關為相應啟動方式,重新上電啟動系統即可。

也可以直接通過USB-OTG接口和 MFGTool2軟體燒寫到eMMC。ssh

燒寫到eMMC啟動,可以使用WIFI連網,WIFI配網步驟參考:​​https://doc.embedfire.com/linux/imx6/quick_start/zh/latest/quick_start/wifi/wifi.html​​

Qt系統界面

野火i.MX6ULL自帶的系統固件燒錄後自啟動Qt程式界面如下:

嵌入式Qt-控制硬體:滑動條控制RGB燈

序列槽方式登入時:

普通使用者(帶sudo權限)

  • 賬戶: debian
  • 密碼: temppwd

ROOT使用者

  • 賬戶: root
  • 密碼: root

這個系統第一次運作時,會進行螢幕觸摸校準,若校準的不滿意,可删除掉**/etc/pointercal檔案**後重新開機再進行校準。

rm /etc/pointercal      

2.2 無Qt的RGB LED測試

野火i.MX6ULL的RGB LED的原理圖如下,由于驅動程式不需要自己寫了,實際上我們也不需要關心具體的硬體引腳是哪個,隻需要使用驅動程式提供的裝置描述符進行LED的控制即可。

嵌入式Qt-控制硬體:滑動條控制RGB燈

參考野火的測試代碼:​​https://doc.embedfire.com/linux/imx6/quick_start/zh/latest/quick_start/led_subsystem/led_subsystem.html#id4​​

測試代碼

編寫自己的沒有Qt界面的RGB LED測試代碼:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>
#include <stdlib.h>

#define RLED_DEV_PATH "/sys/class/leds/red/brightness"
#define GLED_DEV_PATH "/sys/class/leds/green/brightness"
#define BLED_DEV_PATH "/sys/class/leds/blue/brightness"

int main(int argc,int *argv[])
{
    int r_fd;
    int g_fd;
    int b_fd;

    r_fd = open(RLED_DEV_PATH,O_WRONLY);
    if(r_fd < 0)
    {
        perror(RLED_DEV_PATH);
        exit(1);
    }
    
    g_fd = open(GLED_DEV_PATH,O_WRONLY);
    if(r_fd < 0)
    {
        perror(GLED_DEV_PATH);
        exit(1);
    }
    
    b_fd = open(BLED_DEV_PATH,O_WRONLY);
    if(r_fd < 0)
    {
        perror(BLED_DEV_PATH);
        exit(1);
    }

    while(1)
    {
        write(r_fd,"255",3);
        sleep(1);
        write(r_fd,"0",3);
        sleep(1);
        
        write(g_fd,"255",3);
        sleep(1);
        write(g_fd,"0",3);
        sleep(1);
        
        write(b_fd,"255",3);
        sleep(1);
        write(b_fd,"0",3);
        sleep(1);
    }

    close(r_fd);
    close(g_fd);
    close(b_fd);
}      

将該程式在Ubuntu進行交叉編譯

arm-linux-gnueabihf-gcc led_noqt.c -o led_noqt      

測試效果

運作效果如下,3種顔色的燈每隔1s依次點亮熄滅:

嵌入式Qt-控制硬體:滑動條控制RGB燈

對于亮度的控制,可以先參考教程中的指令行點燈測試:​​https://doc.embedfire.com/linux/imx6/linux_base/zh/latest/linux_basis/led_key_command_line_testing/led_key_command_line_testing.html​​

實際測試,序列槽指令無法控制燈的亮度,隻能控制亮滅,亮度為1和亮度為255的效果一樣,都是同樣的亮度,不知道是硬體的問題還是軟體驅動的問題。

2.3 Qt中移植RGB LED控制代碼

在滑條UI界面代碼工程的基礎上,添加一個自定義的類,名字可起為regled:

嵌入式Qt-控制硬體:滑動條控制RGB燈

然後在這個類中,将無Qt的RGB LED測試用到的代碼移植進來,并結合Qt的滑動條對三種顔色的燈進行控制。

這個是構造函數,先打開3個LED燈的檔案描述符:

rgbled::rgbled(QObject *parent) : QObject(parent)
{
    r_fd = open(RLED_DEV_PATH,O_WRONLY);
    if(r_fd < 0)
    {
        return;
    }

    g_fd = open(GLED_DEV_PATH,O_WRONLY);
    if(r_fd < 0)
    {
        return;
    }

    b_fd = open(BLED_DEV_PATH,O_WRONLY);
    if(r_fd < 0)
    {
        return;
    }
}      

編寫一個RGB燈的顔色和亮度的控制函數,供外部調用:

void rgbled::SetRGBLedValue(LED_TYPE type, int val)
{
    if (val > 255)
    {
        val = 255;
    }
    else if (val < 0)
    {
        val = 0;
    }

    std::string value = std::to_string(val);

    switch (type)
    {
        case T_R_LED:
            write(r_fd, value.c_str(), 3);
        break;

        case T_G_LED:
            write(g_fd, value.c_str(), 3);
        break;

        case T_B_LED:
            write(b_fd, value.c_str(), 3);
        break;

        default:break;
    }
}      

在UI界面類中,可以對RGB LED進行控制:

//LedWidget類中定義一個rgbled成員變量
rgbled *m_pRGBLed;

//LedWidget構造函數中執行個體化一個rgbled對象
m_pRGBLed = new rgbled(this);      

在更新UI界面上的模拟顔色面闆的同時,也将闆子上的RGB LED的亮度進行同步控制:

void LedWidget::UpdateShowColor()
{
    QColor color;
    int R = ui->Slider_R->value();
    int G = ui->Slider_G->value();
    int B = ui->Slider_B->value();
    color.setRgb(R, G, B);
    QPalette pal;
    pal.setColor(QPalette::Base, color);
    ui->textBrowser->setPalette(pal);

    //控制闆子上的RGB LED的亮度
    m_pRGBLed->SetRGBLedValue(T_R_LED, R);
    m_pRGBLed->SetRGBLedValue(T_G_LED, G);
    m_pRGBLed->SetRGBLedValue(T_B_LED, B);
}      

2.4 編譯時遇到的問題

程式首先在Windows的Qt Creator上進行編譯,遇到了一些問題,記錄下解決方法。

  • 找不到unistd.h

    在Windows中編譯時,Qt Creater提示找不到unistd.h,這個其實是Visual Stidio編譯器找不這個頭檔案。

    這個頭檔案都是Linux系統中常用的,Windows中一般用不到,要消除這個編譯錯誤,可以在VS的安裝目錄手動添加一個這個檔案。

    我的目錄是:

D:\Tools1\vs2015\VC\include      

建立一個unistd.h:

//for qt creater, 2022/8/13
#ifndef _UNISTD_H
#define _UNISTD_H
#include <io.h>
#include <process.h>
#endif      
  • open、write等函數的警告提示

    這些也是Linux中用到的函數,在Window平台編譯隻是警告資訊,沒有報錯,可以不用管

  • 嵌入式Qt-控制硬體:滑動條控制RGB燈

3 實驗示範

3.1 交叉編譯

和之前一樣,将Windows的Qt Creator中的源碼複制到Ubuntu中進行交叉編譯,具體操作過程可參考之前的文章:

​​嵌入式Qt-動手編寫并運作自己的第1個ARM-Qt程式​​

這裡僅記錄下編譯指令:

/home/xxpcb/myTest/imx6ull/otherlib/qt/qt-everywhere-src-5.12.9/arm-qt/bin/qmake      

3.2 檔案複制到闆子中

由于這次測試使用的是野火的系統固件,不能和之前用網絡位置挂載根檔案系統的方式,在Ubuntu中直接将檔案複制到闆子中(Ubuntu中的網絡挂載位置),是以本篇需要使用其它的方法将Ubuntu中編譯的檔案複制到闆子中。

這裡使用SSH的方式進行拷貝,首先要在Ubuntu中和i.MX6ULL闆子中配置SSH功能,配置方法如下:

配置ssh

sudo apt update
sudo apt install openssh-server -y
sudo systemctl status ssh #檢視狀态
# 如果你的防火牆開啟了,使用下面語句
sudo ufw allow ssh      

連接配接方式

基本的ssh連接配接方法是:

ssh username@ip      
  • username表示該機器的使用者名,ip表示對應的ip位址
  • ssh方式檔案複制

從Ubuntu拉取檔案到闆子中

# 從伺服器拉取檔案
# scp 伺服器上的某個使用者@伺服器IP::/伺服器檔案存放路徑 拉取檔案儲存路徑
scp [email protected]:server_file_path local_path

# 我的闆子的拉取指令
cd /usr/local/qt-app/mytest/
scp [email protected]:~/myTest/imx6ull/qt-test/4-led/led ./      
嵌入式Qt-控制硬體:滑動條控制RGB燈

3.3 測試效果

在測試自己的例程之前,需要先将野火的自啟動Qt例程kill掉,否則兩個Qt程式會同步運作互相遮擋。

kill掉自啟動Qt程式

通過ps 、top 等指令查詢到ebf-qtdemo的pid,然後通過kill指令停止App運作

#879 為目前 App 的 PID 值,每次可能不一樣
sudo kill 879      

運作自己的Qt程式

野火的系統中,提供了一個運作腳本run_myapp.sh,需要調用這個腳本來運作自己的Qt程式

sudo /usr/local/qt-app/run_myapp.sh /usr/local/qt-app/Control_1      
嵌入式Qt-控制硬體:滑動條控制RGB燈

實際測試效果如下:

​​https://www.bilibili.com/video/BV1kF411w7YN​​

嵌入式Qt-控制硬體:滑動條控制RGB燈
  • 闆子上的LED的亮度其實不能調節,隻能亮或滅,需要确認下是不是LED驅動的問題
  • 觸摸的方式拖動闆子上的滑條,不太靈活,可能是觸摸和滑鼠都在起作用,兩者幹擾了
  • Qt界面中模拟的顔色混合面闆,顔色混合顯示正常

4 總結

繼續閱讀