99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

  • 回復
  • 收藏
  • 點贊
  • 分享
  • 發新帖

【 DigiKey DIY原創大賽】基于樹莓派的 Modbus網關

引言

在工業控制中,Modbus 是十分普遍的一個通信協議,這里借此次比賽的機會,使用樹莓派4開發板來制作一個Modbus網關

開箱、點亮

活動過程中出了點小插曲,樹莓派的內存不知道怎么的壞了,然后換了一下,立馬給它打印了個外殼穿上防止再次受傷

然后為了方便操作,用HDMI采集器和鍵鼠KVM工具把樹莓派連接到電腦,插上系統卡開機

硬件設計

Modbus協議一般不是常用的TTL電平標準,一般會使用RS232和RS485電平標準,所以做了個USB轉RS232/RS485的一個模塊,原理圖如下

PCB的3D仿真圖

到手焊好的樣子

下面的撥動開關用來切換RS485還是RS232

軟件開發

對于Modbus這個已經有了幾十年壽命的通信協議,在各個系統中都有各式各樣的開源軟件庫了,由于樹莓派也是基于Linux系統的,所以這里使用libmodbus來完成Modbus網關的開發

編譯安裝 libmodbus

使用終端工具和 SSH 連接到樹莓派,我這里使用的是 Tabby,安裝需要的工具包

sudo apt-get install automake autoconf libtool cmake git

進到 libmodbus 的文件夾,然后執行自動初始化

./autogen.sh

./configure 完成自動化配置

然后執行 make 和 sudo make install 命令

至此 libmodbus 就完成了編譯安裝

測試 libmodbus

硬件連接

硬件使用了兩個 Modbus 溫濕度傳感器,其中一個站號設置為 0x1,另一個設置成了 0x2,將兩個Modbus 溫濕度模塊和制作的 USB 轉 RS485/RS232 模塊連接到一條 Modbus 總線的 A、B上面,樹莓派通過 USB 連接到 USB 轉 RS485/RS232 模塊

測試例程

系統中已經安裝好了 libmodbus 的庫,硬件也完成了連接,現在寫一個例程去調用 libmodbus 用 modbus RTU 協議讀取溫濕度傳感器的數據,代碼如下,因為是 USB 轉 RS485,所以在系統中是 /dev/ttyUSB0

include <modbus/modbus.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main() {
    // 創建并初始化 Modbus 連接
    modbus_t *ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
    if (ctx == NULL) {
        fprintf(stderr, "Unable to create the libmodbus context\n");
        return -1;
    }

    // 設置從站地址(例如,從站地址為 0x01)
    modbus_set_slave(ctx, 0x01);

    // 嘗試打開串口
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    // 讀取保持寄存器的數量和起始地址
    uint16_t reg[6];  // 用于存儲讀取到的6個保持寄存器的值
    int addr = 0;     // 從寄存器地址 0 開始讀取
    int num_regs = 6; // 讀取 6 個寄存器

    int rc = modbus_read_registers(ctx, addr, num_regs, reg);
    if (rc == -1) {
        fprintf(stderr, "Failed to read registers: %s\n", modbus_strerror(errno));
        modbus_close(ctx);
        modbus_free(ctx);
        return -1;
    }

    // 輸出讀取到的寄存器值
    for (int i = 0; i < num_regs; i++) {
        printf("Register %d: %d\n", addr + i, reg[i]);
    }

    // 關閉并釋放 Modbus 連接
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}

執行命令如下,就可以讀取到站號為1的溫濕度傳感器數據了,其中0和1地址的保持寄存器就是溫度和濕度數據

gcc test.c -o test -lmodbus
./test

適配 SDL2 和 LVGL

SDL2 是一個跨平臺的開發庫,用于簡化游戲和多媒體應用程序的開發,LVGL是近些年十分流行的 GUI 開發框架,在本項目中使用了 SDL2 來作為 HMI 的驅動層,同時使用 LVGL 來作為應用層的框架來使用

首先安裝好 SDL2 的庫

sudo apt install libsdl2-dev

然后 clone 下來 lvgl-sdl 開源代碼

git clone https://github.com/Ryzee119/lvgl-sdl.git

進入倉庫修改 lv_conf.h 文件,使能 LV_USE_DEMO_WIDGETS 這個宏,然后修改 main.c 中的代碼,調用 lv_demo_widgets();

在 example 目錄中使用 cmake 來編譯工程

cmake -Bbuild
cmake --build build

編譯完成的樣子

進入到樹莓派的桌面環境,然后進入到 build 目錄中執行 ./lv_examples,可以看到

LVGL 也適配完成了,然后就可以基于 LVGL 庫繪制屬于自己的 HMI 界面了

搭建網關 HMI

繪制網關 HMI

方才已經完成了 libmodbus、SDL2、LVGL 的適配,接下來就是 HMI 界面的開發了,因為我連接的是兩個溫濕度傳感器,所以這里做了一個對于兩個從站的數據采集界面,如果按照商用網關的標準是需要實現增刪改查的功能,提供給用戶自己對從站的數量、HMI界面的自定義,本項目從簡之后的界面如下

使用的是 GUI Guider 進行的可視化設計,生成代碼后復制到樹莓派中

在 CMakeLists.txt 中添加 GUI Guider 生成的代碼和包含路徑

file(GLOB LVGL_DRIVER_FILES
    "${PROJECT_DIR}/main.c"
    "${PROJECT_DIR}/example.c"
    "${PROJECT_DIR}/assets/*.c"
    "${PROJECT_DIR}/gui/generated/*.c"
    "${PROJECT_DIR}/gui/generated/images/*.c"
    "${PROJECT_DIR}/gui/generated/guider_fonts/*.c"
    "${PROJECT_DIR}/gui/custom/*.c"
)
include_directories(${PROJECT_DIR}/gui/custom)
include_directories(${PROJECT_DIR}/gui/generated)
include_directories(${PROJECT_DIR}/gui/generated/images)
include_directories(${PROJECT_DIR}/gui/generated/guider_fonts)
include_directories(${PROJECT_DIR}/gui/generated/guider_customer_fonts)

然后將 main 函數中的的 lv_demo_widgets 替換為

    setup_ui(&guider_ui);
    custom_init(&guider_ui);

編譯運行

對接數據接口

使用 Linux 的 RT 庫來創建一個定時器如下

    timer_t timer_id;
    struct sigevent sev;
    struct itimerspec ts;

    // 設置定時器的事件通知方式為信號通知,指定回調函數
    sev.sigev_notify = SIGEV_THREAD;      // 使用線程回調
    sev.sigev_notify_function = timer_handler; // 定時器到期時調用的回調函數
    sev.sigev_notify_attributes = NULL;   // 默認屬性
    sev.sigev_value.sival_ptr = &timer_id; // 傳遞給回調函數的參數

    // 創建定時器
    if (timer_create(CLOCK_REALTIME, &sev, &timer_id) == -1) {
        perror("timer_create");
        exit(EXIT_FAILURE);
    }

    // 設置定時器:首次觸發延遲 1 秒,周期為 1 秒
    ts.it_value.tv_sec = 1; // 初始延遲 1 秒
    ts.it_value.tv_nsec = 0;
    ts.it_interval.tv_sec = 1; // 周期 1 秒
    ts.it_interval.tv_nsec = 0;

    // 設置定時器
    if (timer_settime(timer_id, 0, &ts, NULL) == -1) {
        perror("timer_settime");
        exit(EXIT_FAILURE);
    }

在定時器的回調函數中去更新界面的顯示

// 定時器回調函數
void timer_handler(union sigval arg) {
    // 這里寫定時器每次觸發時執行的代碼
    printf("定時器觸發,執行任務...\n");

    {
        // 讀取保持寄存器的數量和起始地址
        uint16_t reg[2]= {0, 0};  // 用于存儲讀取到的6個保持寄存器的值
        int addr = 0;     // 從寄存器地址 0 開始讀取
        int num_regs = 2; // 讀取 2 個寄存器
        // 設置從站地址(例如,從站地址為 0x01)
        modbus_set_slave(ctx, 0x1);
        modbus_read_registers(ctx, addr, num_regs, reg);

        t1 = reg[0] / 10.0f;
        h1 = reg[1] / 10.0f;
    }
    usleep(5000);
    {
        // 讀取保持寄存器的數量和起始地址
        uint16_t reg[2] = {0, 0};  // 用于存儲讀取到的6個保持寄存器的值
        int addr = 0;     // 從寄存器地址 0 開始讀取
        int num_regs = 2; // 讀取 2 個寄存器
        // 設置從站地址(例如,從站地址為 0x02)
        modbus_set_slave(ctx, 0x2);
        modbus_read_registers(ctx, addr, num_regs, reg);

        t2 = reg[0] / 10.0f;
        h2 = reg[1] / 10.0f;
    }

    printf("T1: %02.1f H1: %02.1f\n", t1, h1);
    printf("T2: %02.1f H2: %02.1f\n", t2, h2);

    char buff[512];
    lv_ui *ui = &guider_ui;
    sprintf(buff, "從站 1: 溫度: %02.1f℃ 濕度: %02.1f%%", t1, h1);
 lv_label_set_text(ui->screen_label_1, buff);
    sprintf(buff, "從站 2: 溫度: %02.1f℃ 濕度: %02.1f%%", t2, h2);
 lv_label_set_text(ui->screen_label_2, buff);

    static int times = 0;
    if(times++ > 100)
        exit(0);
}

在這個回調函數中就實現了溫濕度的采集和對于 HMI 界面的數據更新任務,編譯運行結果如下

程序源碼

lv_modbus_master.zip

以下為視頻演示:

 

全部回復(0)
正序查看
倒序查看
現在還沒有回復呢,說說你的想法
主站蜘蛛池模板: 亚洲麻豆av肉丝网站一区二区 | 日本成人综合 | 一级黄色日本 | 日韩黄色大片在线观看 | 亚洲欧洲专线一区 | 免费看黄色一级大片 | 99热这里只有精品久久 | 播放灌醉水嫩大学生国内精品 | 久久久久人妻精品区一三寸 | 国产精品免费人成网站 | av久久伊人精品中文字幕 | 亚洲Aⅴ天堂Av天堂无码麻豆 | 免费人成又黄又爽又色 | 亚洲AⅤ无码精品色情午在线 | 国产熟女一区二区三区四区五区 | 五十度灰2在线观看 | 久久精品国产欧美 | 亚洲日韩色在线影院性色 | 国产被窝福利一区二区 | 色偷偷色噜噜狠狠网站久久 | 久久久日韩精品一区二区 | 欧美视频精品全部免费观看 | 强壮公弄得小薇高潮 | 国内不卡的一区二区三区中文字幕 | 别揉我奶头~嗯~啊~视频免费网站 | momsxxxxfreemilf图片 | 国产精品扒开腿做爽爽爽A片唱戏 | 国产亚洲综合一区柠檬导航 | 直接看片的av网址在线看片 | 色噜噜一区二区三区 | 亚洲影视网 | 九九在线免费视频 | 三级网在线观看 | 亚洲AV无码国产在丝袜线观看 | 最新免费av| 九九热精品视频在线免费观看 | 91爱在线观看 | 九九九九网站 | 一区二区三区资源 | 国产精品久久久久久人妻精品 | 求个毛片网站 |