智慧城市的建设推动了城市各个领域的智能化发展,消防领域也不例外。智慧消防作为智慧城市的重要组成部分,其建设和发展与智慧城市的建设紧密相连。
在此背景下,ElfBoard团队完成了一个创新性的开源项目——利用ELF 1开发板打造的智慧消防车。该项目展现了物联网、数据处理等前沿技术在消防领域的应用潜力,下面就和各位小伙伴展示一下这个开源项目是怎样实现的。
2、Web可视化界面:用户可以通过Web界面远程控制车的移动。
3、远程控制:通过阿里云物联网平台向车发送指令,实现远程操作和控制。
4、自动灭火:根据火焰传感器检测到的火焰情况,自动触发灭火操作。
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
小车驱动装置主要由TB6612FNG双电机驱动板、TT马达、车轮等组成。
(1)TB6612FNG双电机驱动板
灭火装置主要由火焰传感器、继电器、水泵等组成。
(1)火焰传感器
(2)继电器
(3)水泵
3、整体连接示意图
elf@ubuntu:~/work$ tar -xvf linux-4.1.15-elf1.tar.bz2
elf@ubuntu:~/work$ cd linux-4.1.15-elf1/
elf@ubuntu:~/work/linux-4.1.15-elf1$ vi arch/arm/boot/dts/imx6ull.dtsi
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";
};
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
>;
};
(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
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
(3)编译并替换设备树
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
elf@ubuntu:~/work/linux-4.1.15-elf1$ make imx6ull_elf1_defconfig
elf@ubuntu:~/work/linux-4.1.15-elf1$ make dtbs
root@ELF1:~# cp /run/media/sda1/imx6ull-elf1-emmc.dtb /run/media/mmcblk1p1/
root@ELF1:~# sync
root@ELF1:~# reboot
1、配置阿里云物联网平台
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;
}
/* 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 failedn");
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%04Xnrn", -res);
printf("please check variables like mqtt_host, produt_key, device_name, device_secret in demorn");
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%04Xn", -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: %dn", 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: %dn", res);
return -1;
}
return 0;
}
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线程函数
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: %dn", value);
if (value == -1) {
printf("Error occurred while reading file: %sn", 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线程函数
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;
}
(1)拷贝car.tar.bz2到开发环境/home/elf/work目录下解压
elf@ubuntu:~/work$ tar xvf car.tar.bz2
elf@ubuntu:~/work$ . /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
elf@ubuntu:~/work$ cd car/
elf@ubuntu:~/work/car$ make
root@ELF1:~# cp /run/media/sda1/mqtt_test ./
1、设置Wi-Fi连接
root@ELF1:~# elf1_cmd_wifi.sh -i 8723 -s 账号 -p 密码
root@ELF1:~# ./mqtt_test