智慧城市的建設推動了城市各個領域的智能化發展,消防領域也不例外。智慧消防作為智慧城市的重要組成部分,其建設和發展與智慧城市的建設緊密相連。
在此背景下,ElfBoard團隊完成了一個創新性的開源項目——利用ELF 1開發板打造的智慧消防車。該項目展現了物聯網、數據處理等前沿技術在消防領域的應用潛力,下面就和各位小伙伴展示一下這個開源項目是怎樣實現的。
項目簡介
智能消防車通過阿里云平臺實現遠程控制,使得用戶可以遠程控制車到達指定地點進行滅火,或者通過火焰傳感器檢測到火焰時自動響應滅火操作。
功能特性
1、數據監測與顯示:實時監測車運行狀態,并直觀地顯示在Web界面上。
2、Web可視化界面:用戶可以通過Web界面遠程控制車的移動。
3、遠程控制:通過阿里云物聯網平臺向車發送指令,實現遠程操作和控制。
4、自動滅火:根據火焰傳感器檢測到的火焰情況,自動觸發滅火操作。
環境說明
1、開發環境操作系統:Ubuntu18.04 64位版
2、交叉編譯工具鏈:arm-poky-linux-gnueabi-gcc 5.3.0
3、開發板使用Bootloader版本:u-boot-2016.03
4、開發板內核版本:linux-4.1.15
5、開發板移植QT版本:qt5.6.2
硬件配置
1、小車驅動裝置
小車驅動裝置主要由TB6612FNG雙電機驅動板、TT馬達、車輪等組成。
(1)TB6612FNG雙電機驅動板
2、滅火裝置
滅火裝置主要由火焰傳感器、繼電器、水泵等組成。
(1)火焰傳感器
(2)繼電器
(3)水泵
3、整體連接示意圖
內核適配
1、實現正常驅動小車的功能
消防車驅動裝置主要由TB6612FNG雙電機驅動板,驅動板中pwm引腳接受板卡輸出的pwm信號,?通過調整pwm信號的占空比?來控制輸出電壓,?進而控制電機的轉速,從而?控制小車速度,AIN0/AIN1:?連接板卡的IO端口,?用于控制電機的轉動方向。?通過控制這兩個引腳的電平狀態,?可以實現電機的正轉、?反轉或停止。下面來介紹如何使用EFL 1板卡進行pwm復用以及gpio復用。
(1)復用pwm
1)拷貝
ELF1開發板資料包\02-Linux 源代碼\02-0 出廠內核和uboot源碼\內核源碼\linux-4.1.15-elf1.tar.bz2內核源碼到開發環境/home/elf/work/目錄下解壓。
elf@ubuntu:~/work$ tar -xvf linux-4.1.15-elf1.tar.bz2
2)修改頂層設備樹文件arch/arm/boot/dts/imx6ull.dtsi。
elf@ubuntu:~/work$ cd linux-4.1.15-elf1/ elf@ubuntu:~/work/linux-4.1.15-elf1$ vi arch/arm/boot/dts/imx6ull.dtsi
3)修改設備樹文件arch/arm/boot/dts/imx6ull-elf1-emmc.dts。
elf@ubuntu:~/work/linux-4.1.15-elf1$ vi arch/arm/boot/dts/imx6ull-elf1-emmc.dts
添加設備節點
&pwm5 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm5>; status = "okay"; }; &pwm6 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm6>; status = "okay"; }; &pwm7 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm7>; status = "okay"; }; &pwm8 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm8>; status = "okay"; };
在iomux節點下面添加引腳復用
pinctrl_pwm5: pwm5grp { fsl,pins = < MX6UL_PAD_ENET1_TX_DATA1__PWM5_OUT 0x110b0 >; }; pinctrl_pwm6: pwm6grp { fsl,pins = < MX6UL_PAD_ENET1_TX_EN__PWM6_OUT 0x110b0 >; }; pinctrl_pwm7: pwm7grp { fsl,pins = < MX6UL_PAD_CSI_VSYNC__PWM7_OUT 0x110b0 >; }; pinctrl_pwm8: pwm8grp { fsl,pins = < MX6UL_PAD_CSI_HSYNC__PWM8_OUT 0x110b0 >; };
取消其它用到csi、enet1功能的地方
至此pwm已經復用完成。
(2)復用gpio
1)修改設備樹文件arch/arm/boot/dts/imx6ull-elf1-emmc.dts
elf@ubuntu:~/work$ cd linux-4.1.15-elf1/ elf@ubuntu:~/work/linux-4.1.15-elf1$ vi arch/arm/boot/dts/imx6ull-elf1-emmc.dts
在iomux節點下面添加引腳復用
MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x17059 MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x17059 MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x17059 MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x17059 MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x17059 MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x17059 MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x17059 MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x17059 MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0x17059 MX6UL_PAD_UART2_RX_DATA__GPIO1_IO21 0x17059 MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0x17059 MX6UL_PAD_CSI_PIXCLK__GPIO4_IO18 0x17059
取消其它用到csi、uart2功能的地方
至此gpio已經復用完成
(3)編譯并替換設備樹
1)執行環境變量
elf@ubuntu:~/work/linux-4.1.15-elf1$ . /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
2)編譯設備樹和內核
elf@ubuntu:~/work/linux-4.1.15-elf1$ make imx6ull_elf1_defconfig elf@ubuntu:~/work/linux-4.1.15-elf1$ make dtbs
3)將arch/arm/boot/dts/路徑下的imx6ull-elf1-emmc.dtb放到U盤,通過U盤拷貝到開發板
root@ELF1:~# cp /run/media/sda1/imx6ull-elf1-emmc.dtb /run/media/mmcblk1p1/
4)保存并重啟開發板
root@ELF1:~# sync root@ELF1:~# reboot
配基于云平臺的遠程數據監測和設備控制
1、配置阿里云物聯網平臺
(1)注冊并登錄阿里云賬號(2)開通物聯網平臺服務(3)開通公共實例(4)創建產品(5)添加設備(6)發布產品
2、配置IoT Stdio
(1)領取IoT Stdio體驗版免費試用機會(2)新建項目(3)關聯物聯網平臺產品、設備(4)新建Web應用(5)配置Web顯示界面(6)發布應用
3、程序設計
主函數的實現main.cpp
int main(int argc, char *argv[]) { pthread_t gpio_tid, mqtt_tid; // 信號處理 signal(SIGTERM, SignHandler); signal(SIGINT, SignHandler); // 初始化控制參數 if (-1 == init_controller_data()) goto to_end; // 初始化MQTT并建立連接 init_mqtt(); // 將設備數據同步到MQTT服務器 demo_mqtt_send_handler(SET_STRAIGHT_TO_SEND); demo_mqtt_send_handler(SET_LEFT_TO_SEND); demo_mqtt_send_handler(SET_RIGHT_TO_SEND); demo_mqtt_send_handler(SET_BACK_TO_SEND); demo_mqtt_send_handler(SET_STOP_TO_SEND); demo_mqtt_send_handler(SET_WATER_TO_SEND); set_controller(Upperleft, 5.0); set_controller(Lowerleft, 5.0); set_controller(Upperright, 5.0); set_controller(Lowerright, 5.0); set_controller(left, 1.0); set_controller(right, 1.0); set_controller(c8, 1.0); demo_mqtt_send_handler(SET_UPPERLEFT_TO_SEND); demo_mqtt_send_handler(SET_LOWERLEFT_TO_SEND); demo_mqtt_send_handler(SET_UPPERRIGHT_TO_SEND); demo_mqtt_send_handler(SET_LOWERRIGHT_TO_SEND); // 創建GPIO線程 if (pthread_create(&gpio_tid, NULL, gpio_thread, NULL) != 0) { perror("pthread_create for gpio_thread"); goto to_end; } // 創建MQTT線程 if (pthread_create(&mqtt_tid, NULL, mqtt_thread, NULL) != 0) { perror("pthread_create for mqtt_thread"); goto to_end; } pthread_join(gpio_tid, NULL); pthread_join(mqtt_tid, NULL); to_end: // 遇到異常,退出進程前,回收資源 release_mqtt(); release_controller_devices(); sleep(1); exit(1); }
int init_controller_data(void) { controller.left.value = 0; controller.right.value = 0;
controller.Upperleft.value = 0; controller.Upperright.value = 0;
controller.Lowerleft.value = 0; controller.Lowerright.value = 0;
controller.go_straight.value = 0; controller.turn_left.value = 0;
controller.turn_right.value = 0;
controller.go_back.value = 0; controller.go_stop.value = 0;
controller.spray_water.value = 0; controller.left.flag = 0;
controller.right.flag = 0; controller.Upperleft.flag = 0;
controller.Upperright.flag = 0; controller.Lowerleft.flag = 0; controller.Lowerright.flag = 0; controller.go_straight.flag = 0;
controller.turn_left.flag = 0; controller.turn_right.flag = 0;
controller.go_back.flag = 0; controller.go_stop.flag = 0;
controller.spray_water.flag = 0; return 0; }
初始化MQTT
/* init_mqtt, 初始化,跟mqtt服務器建立鏈接,設置訂閱,創建通道管理線程,創建接收處理線程 */ int init_mqtt(void)
{ int32_t res = STATE_SUCCESS; uint16_t port = 443; /* 無論設備是否使用TLS連接阿里云平臺, 目的端口都是443 */
aiot_sysdep_network_cred_t cred; /* 安全憑據結構體, 如果要用TLS, 這個結構體中配置CA證書等參數 */ char sub_topic[100] = {0}; /* 配置SDK的底層依賴 */
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); /* 配置SDK的日志輸出 */
aiot_state_set_logcb(demo_state_logcb); /* 創建SDK的安全憑據, 用于建立TLS連接 */ memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t)); cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA; /* 使用RSA證書校驗MQTT服務端 */ cred.max_tls_fragment = 16384; /* 最大的分片長度為16K, 其它可選值還有4K, 2K, 1K, 0.5K */
cred.sni_enabled = 1; /* TLS建連時, 支持Server Name Indicator */ cred.x509_server_cert = ali_ca_cert; /* 用來驗證MQTT服務端的RSA根證書 */ cred.x509_server_cert_len = strlen(ali_ca_cert);
/* 用來驗證MQTT服務端的RSA根證書長度 */ /* 創建1個MQTT客戶端實例并內部初始化默認參數 */
mqtt_handle = aiot_mqtt_init(); if (mqtt_handle == NULL) { printf("aiot_mqtt_init failed\n"); return -1; } /* TODO: 如果以下代碼不被注釋, 則例程會用TCP而不是TLS連接云平臺 */
{ memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t)); cred.option = AIOT_SYSDEP_NETWORK_CRED_NONE; } /* 配置MQTT服務器地址 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *)mqtt_host); /* 配置MQTT服務器端口 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *)&port); /* 配置設備productKey */
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY, (void *)product_key);
/* 配置設備deviceName */
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME, (void *)device_name);
/* 配置設備deviceSecret */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET, (void *)device_secret); /* 配置網絡連接的安全憑據, 上面已經創建好了 */
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred); /* 配置MQTT默認消息接收回調函數 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_RECV_HANDLER, (void *)demo_mqtt_default_recv_handler); /* 配置MQTT事件回調函數 */
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER, (void *)demo_mqtt_event_handler);
/* 與服務器建立MQTT連接 */
res = aiot_mqtt_connect(mqtt_handle);
if (res < STATE_SUCCESS) { /* 嘗試建立連接失敗, 銷毀MQTT實例, 回收資源 */ aiot_mqtt_deinit(&mqtt_handle); printf("aiot_mqtt_connect failed: -0x%04X\n\r\n", -res); printf("please check variables like mqtt_host, produt_key, device_name, device_secret in demo\r\n"); return -1; }?
/* MQTT 訂閱topic功能示例, 請根據自己的業務需求進行使用 */
{ strcpy(sub_topic, "/sys/k1l0mrfjkHG/control_unit_1/thing/service/property/set"); res = aiot_mqtt_sub(mqtt_handle, sub_topic, NULL, 1, NULL); if (res < 0) { printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res); return -1; } }?
/* 創建一個單獨的線程, 專用于執行aiot_mqtt_process, 它會自動發送心跳保活, 以及重發QoS1的未應答報文 */
g_mqtt_process_thread_running = 1; res = pthread_create(&g_mqtt_process_thread, NULL, demo_mqtt_process_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_process_thread failed: %d\n", res); return -1; } /* 創建一個單獨的線程用于執行aiot_mqtt_recv, 它會循環收取服務器下發的MQTT消息, 并在斷線時自動重連 */ g_mqtt_recv_thread_running = 1; res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_recv_thread failed: %d\n", res); return -1; } return 0; }
同步設備數據到MQTT服務器
demo_mqtt_send_handler(SET_STRAIGHT_TO_SEND); demo_mqtt_send_handler(SET_LEFT_TO_SEND); demo_mqtt_send_handler(SET_RIGHT_TO_SEND); demo_mqtt_send_handler(SET_BACK_TO_SEND); demo_mqtt_send_handler(SET_STOP_TO_SEND); demo_mqtt_send_handler(SET_WATER_TO_SEND); demo_mqtt_send_handler(SET_UPPERLEFT_TO_SEND); demo_mqtt_send_handler(SET_LOWERLEFT_TO_SEND); demo_mqtt_send_handler(SET_UPPERRIGHT_TO_SEND); demo_mqtt_send_handler(SET_LOWERRIGHT_TO_SEND);
設置控制器參數
set_controller(Upperleft, 5.0); set_controller(Lowerleft, 5.0); set_controller(Upperright, 5.0); set_controller(Lowerright, 5.0); set_controller(left, 1.0); set_controller(right, 1.0); set_controller(c8, 1.0);
GPIO線程
// GPIO線程函數 void *gpio_thread(void *arg) { while (1) { int value = 0; set_gpio(c9, 114); value = read_gpio_value(c9_GPIO_VALUE); pthread_mutex_lock(&gpio_mutex); printf("Value: %d\n", value); if (value == -1) { printf("Error occurred while reading file: %s\n", c9_GPIO_VALUE); } if (value == 0) { cspray_water(); } pthread_mutex_unlock(&gpio_mutex); usleep(100000); } return NULL; } // 創建GPIO線程 if (pthread_create(&gpio_tid, NULL, gpio_thread, NULL) != 0) { perror("pthread_create for gpio_thread"); goto to_end; }
MQTT線程
// MQTT線程函數 void *mqtt_thread(void *arg) { while (1) { pthread_mutex_lock(&mqtt_mutex); if (controller.Upperleft.flag == 1) { demo_mqtt_send_handler(SET_UPPERLEFT_TO_SEND); controller.Upperleft.flag = 0; } if (controller.Lowerleft.flag == 1) { demo_mqtt_send_handler(SET_LOWERLEFT_TO_SEND); controller.Lowerleft.flag = 0; } if (controller.Upperright.flag == 1)
{ demo_mqtt_send_handler(SET_UPPERRIGHT_TO_SEND); controller.Upperright.flag = 0; } if (controller.Lowerright.flag == 1) { demo_mqtt_send_handler(SET_LOWERRIGHT_TO_SEND); controller.Lowerright.flag = 0; } if (controller.go_straight.flag == 1)
{ demo_mqtt_send_handler(SET_STRAIGHT_TO_SEND); controller.go_straight.flag = 0;
} if (controller.turn_left.flag == 1) { demo_mqtt_send_handler(SET_LEFT_TO_SEND);
controller.turn_left.flag = 0; } if (controller.turn_right.flag == 1) { demo_mqtt_send_handler(SET_RIGHT_TO_SEND); controller.turn_right.flag = 0;
} if (controller.go_back.flag == 1) { demo_mqtt_send_handler(SET_BACK_TO_SEND);
controller.go_back.flag = 0; } if (controller.go_stop.flag == 1) { demo_mqtt_send_handler(SET_STOP_TO_SEND);
controller.go_stop.flag = 0; } if (controller.spray_water.flag == 1) { demo_mqtt_send_handler(SET_WATER_TO_SEND); controller.spray_water.flag = 0; } pthread_mutex_unlock(&mqtt_mutex); usleep(100000); } return NULL; } // 創建MQTT線程 if (pthread_create(&mqtt_tid, NULL, mqtt_thread, NULL) != 0) { perror("pthread_create for mqtt_thread"); goto to_end; }
4、應用編譯
(1)拷貝car.tar.bz2到開發環境/home/elf/work目錄下解壓
elf@ubuntu:~/work$ tar xvf car.tar.bz2
(2)執行環境變量
elf@ubuntu:~/work$ . /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
(3)編譯
elf@ubuntu:~/work$ cd car/ elf@ubuntu:~/work/car$ make
(4)拷貝mqtt_test到開發板/home/root路徑下
root@ELF1:~# cp /run/media/sda1/mqtt_test ./
設項目測試
1、設置Wi-Fi連接
root@ELF1:~# elf1_cmd_wifi.sh -i 8723 -s 賬號 -p 密碼
2、執行應用
root@ELF1:~# ./mqtt_test
此時可以通過Web界面下發指令控制小車運行
Web界面將實時顯示小車的運行狀態
至此,就已完成了對智能消防車這一開源項目的詳細介紹。衷心希望這份指南能為有志于學習嵌入式技術的小伙伴們提供實質性的幫助與啟發。
-
單片機
+關注
關注
6041文章
44615瀏覽量
637355 -
嵌入式
+關注
關注
5089文章
19169瀏覽量
306757 -
開發板
+關注
關注
25文章
5116瀏覽量
97918 -
智慧城市
+關注
關注
21文章
4273瀏覽量
97541 -
開源項目
+關注
關注
0文章
38瀏覽量
7223
發布評論請先 登錄
相關推薦
評論