【ElfBoard】基于 Linux 的智能家居小项目

news2024/10/6 6:46:12

大家好,我是 Hello阿尔法,这段时间参与了保定飞凌嵌入式技术有限公司举办的 ElfBoard 共创社招募活动,并有幸成为了一名共创官,官方寄来了一块 ELF 1 开发板,开箱看这里 ELF 1 开箱初体验。

作为共创官,我使用 ELF 1 完成了一个智能家居的小项目。除了 ELF 1 开发板之外,还使用了一块其他厂商的 Linux 开发板 IMX6U,主要原因是在多次抽奖中都没有抽中显示屏,只有我的 IMX6U 有屏幕,其实这样也正好符合项目背景,带有屏幕的 IMX6U 作为智能家居的控制面板,ELF 1 作为被控终端设备,它可以是电灯、电扇、空调器,也可以是冰箱、彩电、洗衣机……实现效果如下图所示:

项目简介

IMX6U 模拟智能家居中的主控面板,实时刷新显示时间、天气、空气质量、温湿度等信息,实现对家居设备电灯、窗帘、通风扇的控制,天气数据来自于心知天气;ELF 1 模拟终端设备,三个 LED 分别代表电灯、窗帘、通风扇,ADC 模拟空气质量检测器,温湿度则用来检测环境中的温湿度。IMX6U 和 ELF 1 两者通过以太网实现交互,ELF 1 和 IMX6U 均基于 Linux 系统开发,资源使用情况如下所示:

  • ELF 1 开发板:3 个 LED、ADC、温湿度传感器、以太网口
  • IMX6U 开发板:5inch RGB 显示屏、以太网口

IMX6U 工程

  • IMX6U 源码工程结构如图所示:

  • IMX6U 源码工程以 LVGL 的 Linux 移植工程为基础,具体实现请阅读 嵌入式 Linux 下的 LVGL 移植;
  • app 文件夹存放应用源码;
  • build 文件夹为编译输出目录;
  • ui 文件夹存放 UI 界面源码,具体实现请阅读 基于 LVGL 使用 SquareLine Studio 快速设计 UI 界面。

app

  • app 文件夹包括有 cJSON 解析器、通信协议 Protocol、网络编程接口 Socket、天气获取、按键以及时间、温湿度数据更新等;
  • cJSON 是使用了一个开源的、C 语言编写的超轻量级 JSON 解析器;
  • 关于 Protocol 请阅读 一个简洁实用的自定义通信协议;
  • socket 文件夹主要内容为 TCP 服务端和客户端的创建,请阅读 Linux 下 socket 编程介绍及 TCP 客户端与服务端创建示例
  • 天气数据通过心知天气 API 获取,相关实现代码如下:
// weather.c
int weather_init(void)
{
    weather_client_fd = client_init_socket();
    /* 组合 GET 请求 */
    sprintf(weather_buffer, GET_REQUEST_PACKAGE, DAILY_JSON, API_KEY, WUHAN);
    /* 发送请求 */
    client_send_data(weather_client_fd, weather_buffer, strlen(weather_buffer));
    /* 接收天气数据 JSON 格式*/
    client_receive_data(weather_client_fd, weather_json, &weather_json_size);
    /* 解析天气数据 */
    cJSON_Daily_WeatherParse(weather_json, &Weather_now);
    /* 更新天气显示 */
    memset(weather_buffer, 0, BUFFER_SIZE);
    sprintf(weather_buffer, "%s / %s", Weather_now.text_day[0], Weather_now.text_night[0]);
    lv_label_set_text(ui_TextDay, weather_buffer);
    lv_label_set_text(ui_MinTemp, Weather_now.low[0]);
    lv_label_set_text(ui_MaxTemp, Weather_now.high[0]);
    lv_label_set_text(ui_outHum, Weather_now.humidity[0]);
    /* 更新天气图片 */
    int code = *Weather_now.code_day[0] - 48;
    switch (code)
    {
    case 0: lv_img_set_src(ui_weatherImg, &ui_img_icons_00_png); break;
    ...
    
    ...
    case 99: lv_img_set_src(ui_weatherImg, &ui_img_icons_99_png); break;
    default: break;
    }

    client_close_socket(weather_client_fd);
    return 0;
}
  • 以按键为例,实现数据打包、发送相关代码:
static void led_ryg_turn(int cmd, int code)
{
    /* 组合命令 */
    msg_frame_t led_msg_frame;
    led_msg_frame.type = LED_RYG;
    led_msg_frame.cmd = cmd;
    led_msg_frame.code = code;
    led_msg_frame.datalen = 0;
    /* 打包命令 */
    msg_buf_t *_msg_buf = pkg_frame(&led_msg_frame);
    /* 发送按键命令 */
    server_send_data(client_fd, (char *)_msg_buf->buf_ptr, _msg_buf->buf_size);
}

static void btn1_click_cb(lv_event_t *event) 
{
    printf("Button1 clicked\n");
    static char flag = 0;

    if(flag == 0)
    {
        flag = 1;
        led_ryg_turn(LED_R, LED_ON);
    }
    else
    {
        flag = 0;
        led_ryg_turn(LED_R, LED_OFF);
    }
}

static void btn2_click_cb(lv_event_t *event) 
{
    // ...
}

static void btn3_click_cb(lv_event_t *event) 
{
    // ...
}

int button_init(void)
{
    lv_obj_add_event_cb(ui_Button1, btn1_click_cb, LV_EVENT_CLICKED, NULL);
    lv_obj_add_event_cb(ui_Button2, btn2_click_cb, LV_EVENT_CLICKED, NULL);
    lv_obj_add_event_cb(ui_Button3, btn3_click_cb, LV_EVENT_CLICKED, NULL);
    return 0;
}
  • 数据接收、解析、命令执行相关代码:
static int ctrl_dev_aht20(msg_frame_t *_msg_pack)
{
    // ...
    
    return 0;
}

static int ctrl_dev_adc(msg_frame_t *_msg_pack)
{
    printf("--- ctrl_dev_adc ---\r\n");

    uint16_t adc_raw = (uint16_t)(_msg_pack->data[0] << 8) + _msg_pack->data[1];
    uint8_t pm2_5 = adc_raw / 16;
    char pm2_5_src[4];

    printf("adc raw value: %d, pm2_5 value: %d \r\n", adc_raw, pm2_5);

    lv_arc_set_value(ui_Air, pm2_5);

    snprintf(pm2_5_src, sizeof(pm2_5_src), "%d", pm2_5);
    lv_label_set_text(ui_AirValue, pm2_5_src);

    return 0;
}

static int ctrl_cmd_func(const msg_pkg_t *_msg_pkg)
{
    printf("--- ctrl_cmd_func ---\r\n");
    
    switch(_msg_pkg->pkg->type)
    {
        case AHT20: ctrl_dev_aht20(_msg_pkg->pkg); break;
        case ADC: ctrl_dev_adc(_msg_pkg->pkg); break;
        default: return -1;
    }

    return 0; 
}

static void *recv_thread(void *arg)
{
    recv_msg_buf->buf_ptr=recv_msg_buf->buf;
    while(1)
    {
        if(server_receive_data(client_fd, (char *)recv_msg_buf->buf_ptr, (ssize_t *)&recv_msg_buf->buf_size) == 0)
        {
            printf("thread recv \r\n");
            msg_buf_print(recv_msg_buf);
            /* 解析数据包命令 */
            msg_pkg_t *_msg_pkg = unpkg_frame(recv_msg_buf->buf_ptr, recv_msg_buf->buf_size);
            /* 执行命令 */
            ctrl_cmd_func(_msg_pkg);
        } 
    }
    return NULL;
}

/* 线程创建 */
pthread_create(&recv_thread_id, NULL, recv_thread, NULL);

ELF 1 工程

  • ELF 1 源码工程结构如图所示:

  • src 文件夹存放源文件,inc 文件夹存放头文件,obj 为编译输出目录;
  • 客户端创建、数据打包、发送、接收、命令执行与 IMX6U 工程实现类似,不再介绍,数据采集、LED 控制采用文件操作实现。

功能演示

  • 抖音视频链接

更多内容

  • CSDN博客:@Hello阿尔法
  • 哔哩哔哩:@Hello阿尔法
  • 知乎:@Hello阿尔法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1476839.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

❤ git操作Github、git操作github

❤ git操作Github 1、设置用户名和邮件地址 git config --global user.name "nexuslin" git config --global user.email "2455067339qq.com"2、生成本地密钥 ssh-keygen -t rsa -C 2455067339qq.com3、接下来就一直回车&#xff0c;然后再去 C:\Users…

VR危险环境模拟介绍|VR虚拟现实设备

VR危险环境模拟是指利用虚拟现实技术来模拟和展现各种危险环境&#xff0c;以便训练人员应对紧急情况、提高安全意识和应急反应能力。这种模拟可以涉及到工业、医疗、紧急救援等多个领域&#xff0c;旨在帮助人们在真实环境中面对危险时能够做出正确的应对和决策。 VR危险环境…

进销存是什么意思?如何开发一款进销存管理系统?

这篇给大家详细介绍一下&#xff0c;进销存到底是什么&#xff0c;进销存管理系统有什么用&#xff1f;企业如何开发一款进销存管理系统&#xff1f; 以下内容示例工具均来自于JDY——https://www.jiandaoyun.com 一、进销存是什么&#xff1f; 1、基本概念 进销存&#xff0…

Redis 协议与异步方式

redis pipeline 模式 redis pipeline 是一个客户端提供的机制&#xff0c;与 redis 无关。pipeline 不具备事务性。目的&#xff1a;节约网络传输时间。通过一次发送多条请求命令&#xff0c;从而减少网络传输时间。 时间窗口限流 系统限定某个用户的某个行为在指定的时间范围…

华为HCIP Datacom H12-821 卷2

1.单选题 下面关于 OSPF 中的 ABR&#xff0c;描述措误的是 A、ABR 不能够产生三类、四类、五类 LSA B、将连接的非骨干区域内的一类、二类 LSA 转换成三类 LSA,发布到骨干区域中 C、ABR 格骨干区城内的一类、二类 LSA.三类 LSA 转换成三类 LSA, 发布到连接的非骨干区域中 …

【系统分析师】-软件工程

1、信息系统的生命周期 1、四阶段划分 立项阶段&#xff1a;企业全局、形成概念、需求分析。包含【系统分析师】-系统规划-CSDN博客开发阶段&#xff1a;总体规划--系统分析--设计--实施--验收运维阶段&#xff1a;通过验收、移交之后消亡阶段&#xff1a;更新改造、功能扩展…

【Excel PDF 系列】iText 库直接实现表格 PDF

你知道的越多&#xff0c;你不知道的越多 点赞再看&#xff0c;养成习惯 如果您有疑问或者见解&#xff0c;欢迎指教&#xff1a; 企鹅&#xff1a;869192208 文章目录 前言生成表格 PDF 效果引入 pom 配置代码实现定义 CreateExcelToPdfModel 对象主方法 前言 最近遇到生成 E…

web学习笔记(二十一)

目录 1.构造函数创建对象 1.1规则 1.2 new关键字调用构造函数时&#xff0c;函数内部做了什么事情&#xff1f; 1.3总结 2.混合模式创建对象 3.JavaScript 继承---借助构造函数 4.原型链 4.1原型链实现方法继承 5.完美的组合继承 6.call方法的使用 1.构造函数创建对象…

1、docker入门

文章目录 1、tocker简介2、tocker的安装&环境配置2、配置阿里云镜像3、基本命令1、镜像命令2、docker基本命令3、镜像基本命令4、Docker 容器常用命令 1、tocker简介 新一代的虚拟化技术 2、tocker的安装&环境配置 uname -r1、首先查看liunx的内核 yum update -y2、更…

Nginx----高性能的WEB服务端(四)

一、http 协议反向代理 1、反向代理&#xff1a;缓存功能 ​ proxy_cache zone_name | off; 默认off #指明调用的缓存&#xff0c;或关闭缓存机制;Context:http, server, location #zone_name 表示缓存的名称.需要由proxy_cache_path事先定义proxy_cache_key string; #缓存中…

刚刚:阿里云服务器降价了!2024云服务器优惠价格表曝光!

2024阿里云服务器优惠活动政策整理&#xff0c;轻量2核2G3M服务器61元一年、2核4G4M带宽165元1年&#xff0c;云服务器4核16G10M带宽26元1个月、149元半年&#xff0c;阿里云ECS云服务器2核2G3M新老用户均可99元一年续费不涨价&#xff0c;企业用户2核4G5M带宽199元一年&#x…

如何开展有效的绩效面谈

绩效面谈作为绩效管理的核心环节&#xff0c;其重要性不容忽视。它不仅是评价员工过去一段时间工作表现的环节&#xff0c;更是为下一阶段绩效管理设定目标和方向的环节。然而&#xff0c;许多企业在实施绩效面谈时&#xff0c;往往仅停留在形式上&#xff0c;没有真正地发挥其…

16. QML中的一些粒子特效

1.说明 在使用unity开发游戏时&#xff0c;都会涉及到一些特效的开发。实际上在QML中也提供了一些可以做特效的控件&#xff0c;称之为粒子系统。本篇博客主要记录一些使用粒子做特效的方式。 特效–火焰效果&#xff1a; 2. 案例汇总 2.1 案例1 效果展示&#xff1a; 粒子…

仿牛客网项目---用户注册登录功能的实现

从今天开始我们来写一个新项目&#xff0c;这个项目是一个完整的校园论坛的项目。主要功能模块&#xff1a;用户登录注册&#xff0c;帖子发布和热帖排行&#xff0c;点赞关注&#xff0c;发送私信&#xff0c;消息通知&#xff0c;社区搜索等。这篇文章我们先试着写一下用户的…

风速预测(七)VMD-CNN-BiLSTM预测模型

目录 往期精彩内容&#xff1a; 前言 1 风速 VMD 分解与可视化 1.1 导入数据 1.2 VMD分解 2 数据集制作与预处理 3 基于Pytorch的VMD CNN-BiLSTM 预测模型 3.1 定义VMD CNN-BiLSTM预测模型 3.2 设置参数&#xff0c;训练模型 4 模型评估与可视化 4.1 结果可视化 4.2…

蓝桥杯-常用STL(三)

常用STL &#x1f388;1.映射&#x1f388;2.map的基础使用&#x1f52d;2.1引入库&#x1f52d;2.2构造一个映射&#x1f52d;2.3插入一对映射&#x1f52d;2.4判断关键字是否存在&#x1f52d;2.5遍历映射&#x1f52d;2.6清空 &#x1f388;1.映射 &#x1f50e;映射是指两个…

[spark] RDD 编程指南(翻译)

Overview 从高层次来看&#xff0c;每个 Spark 应用程序都包含一个driver program&#xff0c;该程序运行用户的main方法并在集群上执行各种并行操作。 Spark 提供的主要抽象是 resilient distributed dataset&#xff08;RDD)&#xff0c;它是跨集群节点分区的元素集合&…

多个版本的Python如何不冲突?

转载文章&#xff0c;防止忘记或删除 转载于&#xff1a;电脑中存在多个版本的Python如何不冲突&#xff1f; - 知乎 (zhihu.com) 如何安装多版本的Python并与之共存&#xff1f; 如果你的工作涉及到Python多版本之间开发或测试&#xff0c;那么请收藏本文&#xff0c; 如果你…

RabbitMQ讲解与整合

RabbitMq安装 类型概念 租户 RabbitMQ 中有一个概念叫做多租户&#xff0c;每一个 RabbitMQ 服务器都能创建出许多虚拟的消息服务器&#xff0c;这些虚拟的消息服务器就是我们所说的虚拟主机&#xff08;virtual host&#xff09;&#xff0c;一般简称为 vhost。 每一个 vhos…

【Java程序设计】【C00331】基于Springboot的驾校预约学习系统(有论文)

基于Springboot的驾校预约学习系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的驾校预约学习系统&#xff0c;本系统有管理员、用户和教练三种角色&#xff1b; 管理员&#xff1a;个人中心、管理员管理、教练…