站内搜索
发作品签到
专业版

基于合宙Air700E的4G环境监测节点(温湿度、气压等数据)

工程标签

6.2k
0
0
4

简介

基于合宙Air700E的4G环境监测节点(温度、湿度、气压等数据),通过MQTT上传阿里云物联网平台。同时ESP32C3通过WiFi连接MQTT服务器订阅数据并显示在LCD上。

简介:基于合宙Air700E的4G环境监测节点(温度、湿度、气压等数据),通过MQTT上传阿里云物联网平台。同时ESP32C3通过WiFi连接MQTT服务器订阅数据并显示在LCD上。

开源协议

CC BY-NC-SA 4.0

(未经作者授权,禁止转载)
创建时间:2023-10-17 11:11:45更新时间:2024-07-30 14:13:33

描述

基于合宙Air700E的4G环境监测节点(温度、湿度、气压等数据),通过MQTT上传阿里云物联网平台。

介绍

合宙Air700E 4G模块读取传感器(温度、湿度、气压等)数据并通过MQTT协议上传阿里云物联网平台,数据也会同时显示在0.96寸的OLED屏幕上,使用了U8g2图形库。

ESP32C3 WiFi模块通过MQTT协议订阅4G节点上传的数据并显示在LCD屏上,使用了LVGL图形库。

这是我的一个课程设计,随便做做的,不是很完善。

题目要求:设计并制作无线通信系统,结合上学期所学知识,将本地采集的温、湿度/超声波测量距离通过无线收发的方式,发送到主机/接收端,并在接收端利用 LCD显示相关信息,具体要求如下:

⑴ 蓝牙无线传输系统设计实现

⑵ WiFi 无线传输系统设计及实现

⑶ ZigBee 无线传输系统设计及实现

⑷ GPRS/GSM 无线传输系统设计及实现

(5) 4G 无线传输系统设计及实现

(6) NBIoT/LoRa 无线传输系统设计及实现

提示:可用 8/16/32 处理器作为主控制器,按照本小组选定的综合部分内容来进行选型,至少完成 2 个小项,其中(1)(2)(3)选 1 个完成,(4)(5)(6)选 1 个完成。

Air700E和ESP32C3我都是使用LuatOS系统+Lua脚本的开发方式来开发的。

LuatOS固件是我使用合宙的云编译生成的。

ESP32C3上自带的4MByte的flash被我换成了8MByte的了,固件也是大于4MB的,因为加了LVGL图形库以及几种字体。

阿里云学生优惠地址:https://www.aliyun.com/daily-act/ecs/activity_share?userCode=jdjc69nf

注意: 由于阿里云物联网平台不同设备间不能订阅对方的主题,只能订阅本设备的主题,所以需要在 消息转发→云产品流转 那里添加一条规则,将4G节点设备的发布的消息转发到WiFi节点设备的一个主题。

电子/单片机技术交流QQ群:820537762

实物图

演示视频: https://www.bilibili.com/video/BV1MH4y1B7Df/

整体图

4G节点

WiFi节点

WiFi连接时:

IMG_20231107_230343_1.jpeg

连接上WiFi后开始连接MQTT服务器和NTP时间同步:

IMG_20231107_230420.jpeg

显示4G节点采集到的数据:

IMG_20231107_211812.jpeg

显示温湿度变化曲线:

IMG_20231107_211856.jpeg

物联网平台

阿里云物联网平台上显示的数据:

image-20231215005346807.png

代码

具体怎么下载代码我就不细说了,自行查看官方文档。

Air700E文档:https://doc.openluat.com/wiki/44?wiki_page_id=4730

LVGL for LuatOS 手册:https://url.zeruns.tech/7z7fN

ESP32-C3文档:https://url.zeruns.tech/497AP

Lua教程:https://url.zeruns.tech/Pc4PA

4G节点

固件下载地址:https://url.zeruns.tech/2G3K7

main.lua文件:

-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "环境监测节点"
VERSION = "1.1.0"

-- 引入必要的库文件(lua编写), 内部库不需要require
sys = require("sys")
aht10 = require "aht10"
bmx = require "bmx"

--添加硬狗防止程序卡死
if wdt then
    wdt.init(9000)--初始化watchdog设置为9s
    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
end

print(_VERSION)

log.info(mobile.ipv6(true)) --开启ipv6

local ProductKey= "xxxxxx"                         --产品key
local DeviceName= "xxxxxx"                --改为你自己的设备名
local DeviceSecret = "xxxxxx" --改为你自己的设备密钥
local client_id, user_name, password = iotauth.aliyun(ProductKey, DeviceName ,DeviceSecret) --生成MQTT三元组
log.info("MQTT参数", client_id, user_name, password)

local softI2C = i2c.createSoft(29, 31, 2)   --初始化软件I2C
local aht10_data,bmx_data
local RH,Temp,Press,High,distance,BAT_Voltage,CPU_T = 0,0,0,0,0,0,0                 --平均值,湿度、温度、气压、海拔、距离、电池电压、CPU温度
local RH_C,Temp_C,Press_C,High_C,distance_C,BAT_Voltage_C,CPU_T_C = 0,0,0,0,0,0,0   --当前值
local AHT10_flag,BMP180_flag,US100_flag,BAT_Voltage_flag,CPU_T_flag = false,false,false,false,false
all_data = {params = {CurrentVoltage = 0,CurrentTemperature = 0, CurrentHumidity = 0,Atmosphere = 0, Altitude = 0,DetectDistance = 0,CPUTemperature = 0}}

function US_100()   --US-100超声波测距模块读取数据
    uart.write(1, string.char(0x55))  --发送16进制0x55
    sys.wait(50)    --延时50毫秒
    local hData,lData  = string.byte(uart.read(1, 2),1,2)   --串口接收2字节
    uart.rxClear(1) --清空接收缓存
    if hData and lData then --判断是否接收到数据
        local Distance_mm = tonumber((hData * 256 ) + lData)    --将高8位左移8位后和低8位数据相加
        if Distance_mm > 4500 then  --判断是否超出测量范围
            Distance_mm = 4500
        end
        --log.info("超声波:"..Distance_mm.."mm")     --日志输出距离
        return (Distance_mm / 10)                  --算出cm并返回
    end
end
-- https://blog.zeruns.tech
sys.taskInit(function() -- 创建一个线程,读取各个传感器数据

    sys.wait(500)       -- 延时500毫秒
    aht10.init(softI2C) -- 初始化AHT10,传入i2c_id
    bmx.init(softI2C)   -- 初始化BMP180,传入i2c_id
    uart.setup(1, 9600, 8, 1, uart.NONE)    --初始化串口1
    adc.open(0)         -- 打开adc通道0,并读取
    adc.open(adc.CH_CPU)-- 打开ADC通道-CPU内部温度通道
    --adc.setRange(adc.ADC_RANGE_3_8) -- 开启ADC0,1分压电阻,范围0~3.8V
    sys.wait(500)       -- 延时500毫秒

    local RH_sum, Temp_sum, Press_sum, High_sum, distance_sum,BAT_Voltage_sum,CPU_T_sum = 0,0,0,0,0,0,0 --总和,求平均值用
    local avg_count, avg_count2,avg_count3,avg_count4,avg_count5 = 0,0,0,0,0

    while 1 do
        aht10_data = aht10.get_data()   --读取AHT10的数据
        bmx_data = bmx.get_data()       --读取BMP10的数据
        distance_C = US_100()           --读取US-100的数据
        -- 电池电压采样,分压电阻比例:4.7K/10K
        BAT_Voltage_C = ((adc.get(0) / 1000 / 1007) * 1473) -- 读取AD0电压值,计算电池电压
        CPU_T_C = adc.get(adc.CH_CPU) / 1000                -- 读取CPU温度

        -- AHT10温湿度平均值计算
        if aht10_data.RH and aht10_data.T then  --判断AHT10是否读取到数据
            all_data.params.CurrentTemperature = aht10_data.T
            all_data.params.CurrentHumidity = aht10_data.RH*100
            if avg_count < 6 then       --判断是否小于3,累加计平均值
                RH_C,Temp_C = aht10_data.RH*100, aht10_data.T   --读取温度和湿度的当前值
                RH_sum = RH_C + RH_sum
                Temp_sum = Temp_C + Temp_sum
                avg_count = avg_count + 1
            elseif avg_count == 6 then
                RH = RH_sum / 6         -- 算出湿度平均值
                Temp = Temp_sum / 6     -- 算出温度平均值
                log.info("AHT10_data.RH: "..(string.format("%.2f", RH)).." %"," AHT10_data.T: "..(string.format("%.2f", Temp)).." ℃")    --日志输出
                AHT10_flag = true       -- 标志位置位,数据采集完毕
                sys.publish("MQTT_P")   -- 发布消息,数据采集计算完毕,MQTT可以上报了
                avg_count,RH_sum,Temp_sum = 0,0,0   --计数值和总和清零
            end
        end

        --BMP180气压和高度平均值计算
        if bmx_data.press and bmx_data.high then
            all_data.params.Atmosphere = bmx_data.press
            all_data.params.Altitude = bmx_data.high
            if avg_count2 < 10 then       --判断是否小于10,累加计平均值
                Press_C,High_C = bmx_data.press, bmx_data.high  --读取气压和高度的当前值
                Press_sum = Press_C + Press_sum
                High_sum = High_C + High_sum
                avg_count2 = avg_count2 + 1
            elseif avg_count2 == 10 then
                Press = Press_sum / 10
                High = High_sum / 10
                log.info("BMP180_data.press: "..(string.format("%.2f", Press)).." hPa"," BMP180_data.high: "..(string.format("%.2f", High)).." m")
                BMP180_flag = true
                sys.publish("MQTT_P")
                avg_count2,Press_sum,High_sum=0,0,0
            end
        end

        -- US-100超声波测距 距离平均值计算
        if distance_C then    --判断是否读取到数据
            all_data.params.DetectDistance = distance_C
            if avg_count3 < 3 then
                distance_sum = distance_C + distance_sum
                avg_count3 = avg_count3 + 1
            elseif avg_count3 == 3 then
                distance = distance_sum / 3
                log.info("US-100: "..(string.format("%.1f", distance)).." cm")
                US100_flag = true
                sys.publish("MQTT_P")
                avg_count3,distance_sum = 0,0
            end
        end

        -- 电池电压
        if BAT_Voltage_C then    --判断是否读取到数据
            all_data.params.CurrentVoltage = BAT_Voltage_C
            if avg_count4 < 20 then
                BAT_Voltage_sum = BAT_Voltage_C + BAT_Voltage_sum
                avg_count4 = avg_count4 + 1
            elseif avg_count4 == 20 then
                BAT_Voltage = BAT_Voltage_sum / 20
                log.info("BAT_Voltage: "..(string.format("%.2f", BAT_Voltage)).." V")
                BAT_Voltage_flag = true
                sys.publish("MQTT_P")
                avg_count4,BAT_Voltage_sum = 0,0
            end
        end

        -- CPU温度
        if CPU_T_C then    --判断是否读取到数据
            all_data.params.CPUTemperature = CPU_T_C
            if avg_count5 < 20 then
                CPU_T_sum = CPU_T_C + CPU_T_sum
                avg_count5 = avg_count4 + 1
            elseif avg_count5 == 20 then
                CPU_T = CPU_T_sum / 20
                log.info("CPU_T: "..(string.format("%.2f", CPU_T)).." ℃")
                CPU_T_flag = true
                sys.publish("MQTT_P")
                avg_count5,CPU_T_sum = 0,0
            end
        end

        sys.wait(500)
    end
end)

--[[sys.taskInit(function() --创建一个任务,超声波测距,1.5秒一次
    uart.setup(1, 9600, 8, 1, uart.NONE)    --初始化串口1
    sys.wait(1000)
    while 1 do
        distance = US_100() --读取US-100的数据
        if distance then    --判断是否读取到数据
            log.info("US-100: "..(string.format("%.1f", distance)).." cm")
            US100_flag = true
            sys.publish("MQTT_P")
        end
        sys.wait(1500)
    end
end)]]

sys.taskInit(function() --创建一个线程,MQTT初始化和数据上报
    mqttc = mqtt.create(nil, "a1sJbDQiEqr.iot-as-mqtt.cn-shanghai.aliyuncs.com", 1883,true,true)
    mqttc:auth(client_id, user_name, password)
    mqttc:keepalive(120) -- 默认值240s
    mqttc:autoreconn(true, 3000) -- 自动重连机制
    mqttc:on(function(mqtt_client, event, data, payload)
        if event == "conack" then
            sys.publish("mqtt_conack")
            log.info("mqtt", "mqtt已连接")
            mqtt_client:subscribe("/sys/"..ProductKey.."/"..DeviceName.."/thing/service/property/set")
        elseif event == "recv" then
            log.info("mqtt", "收到消息", data, payload)
            local mqtt_date = json.decode(payload)
        elseif event == "sent" then
            log.info("mqtt", "sent", "pkgid", data)
        end
    end)
    mqttc:connect()
    while true do
        sys.waitUntil("MQTT_P", 3000)
        if AHT10_flag then
            local json_str = json.encode({params = {CurrentTemperature = Temp, CurrentHumidity = RH}}, "2f") -- 数据改成JSON格式,保留2位小数
            mqttc:publish("/sys/"..ProductKey.."/".. DeviceName.."/thing/event/property/post", json_str)  -- MQTT上报属性
            mqttc:publish("/"..ProductKey.."/".. DeviceName.."/user/update", json.encode(all_data,"2f"))  -- MQTT上报属性
            AHT10_flag = false
        end
        if BMP180_flag then
            local json_str = json.encode({params = {Atmosphere = Press, Altitude = High}}, "2f") -- 数据改成JSON格式,保留2位小数
            mqttc:publish("/sys/"..ProductKey.."/"..DeviceName.."/thing/event/property/post", json_str)  -- MQTT上报属性
            mqttc:publish("/"..ProductKey.."/".. DeviceName.."/user/update", json.encode(all_data,"2f"))  -- MQTT上报属性
            BMP180_flag = false
        end
        if US100_flag then
            local json_str = json.encode({params = {DetectDistance = distance}}, "1f") -- 数据改成JSON格式,保留2位小数
            mqttc:publish("/sys/"..ProductKey.."/"..DeviceName.."/thing/event/property/post", json_str)  -- MQTT上报属性
            mqttc:publish("/"..ProductKey.."/".. DeviceName.."/user/update", json.encode(all_data,"2f"))  -- MQTT上报属性
            US100_flag = false
        end
        if BAT_Voltage_flag then
            local json_str = json.encode({params = {CurrentVoltage = BAT_Voltage}}, "2f") -- 数据改成JSON格式,保留2位小数
            mqttc:publish("/sys/"..ProductKey.."/"..DeviceName.."/thing/event/property/post", json_str)  -- MQTT上报属性
            mqttc:publish("/"..ProductKey.."/".. DeviceName.."/user/update", json.encode(all_data,"2f"))  -- MQTT上报属性
            BAT_Voltage_flag = false
        end
        if CPU_T_flag then
            local json_str = json.encode({params = {CPUTemperature = CPU_T}}, "2f") -- 数据改成JSON格式
            mqttc:publish("/sys/"..ProductKey.."/"..DeviceName.."/thing/event/property/post", json_str)  -- MQTT上报属性
            mqttc:publish("/"..ProductKey.."/".. DeviceName.."/user/update", json.encode(all_data,"2f"))  -- MQTT上报属性
            CPU_T_flag = false
        end
    end
end)


-- https://blog.zeruns.tech
sys.taskInit(function()
    u8g2.begin({ic = "ssd1306",direction = 0,mode="i2c_hw",i2c_id=1,i2c_speed = i2c.FAST}) -- direction 可选0 90 180 270
    u8g2.ClearBuffer()  --清屏
    u8g2.SetFont(u8g2.font_opposansm10)  --切换字体
    u8g2.DrawUTF8("IMEI:", 0, 16)
    u8g2.DrawUTF8(mobile.imei(), 0, 32)
    u8g2.SendBuffer()

    --ntp同步时间
    --socket.sntp()
    socket.sntp({"ntp.aliyun.com","ntp1.aliyun.com","ntp2.aliyun.com"}) --sntp自定义服务器地址
    --socket.sntp(nil, socket.ETH0) --sntp自定义适配器序号
    sys.subscribe("NTP_UPDATE", function()
        log.info("sntp", "time", os.date())
        sys.publish("NTP_OK")
    end)
    sys.subscribe("NTP_ERROR", function()
        log.info("socket", "sntp error")
        socket.sntp()
    end)

    sys.wait(1000)

    sys.waitUntil("NTP_OK", 3000)
    u8g2.ClearBuffer()  --清屏
    u8g2.SetFont(u8g2.font_opposansm10)  --切换字体
    u8g2.DrawUTF8(os.date("%Y-%m-%d"), 0, 16) --显示时间
    u8g2.DrawUTF8(os.date("%H:%M:%S"), 0, 32) --显示时间
    local IP = socket.localIP()     --显示IP地址
    if IP then
        u8g2.DrawUTF8("IP:"..IP, 0, 63)
    end
    u8g2.SendBuffer()
    sys.wait(2500)

    while true do
        u8g2.ClearBuffer()  --清屏
        u8g2.SetFont(u8g2.font_sarasa_m10_ascii)
        if Temp_C then
            u8g2.DrawUTF8("T:"..(string.format("%.2f", Temp_C)).."°C", 0, 16)
        end
        if RH_C then
            u8g2.DrawUTF8("RH:"..(string.format("%.2f", RH_C)).."%", 0, 32)
        end
        if Press_C then
            u8g2.DrawUTF8("P:"..(string.format("%.2f", Press_C)).."hPa", 0, 48)
        end
        if distance_C then
            u8g2.DrawUTF8("D:"..(string.format("%.1f", distance_C)).."cm", 0, 63)
        end
        if High_C then
            u8g2.DrawUTF8("H:"..(string.format("%.2f", High_C)).."m", 61, 16)
        end
        if BAT_Voltage_C then
            u8g2.DrawUTF8("B:"..(string.format("%.2f", BAT_Voltage_C)).."V", 66, 32)
        end
        if CPU_T_C then
            u8g2.DrawUTF8("CPUT:"..(string.format("%d", CPU_T_C)).."°C", 63, 63)
        end
        u8g2.SendBuffer()   --显示数据更新到屏幕
        sys.wait(200)
    end
end)

sys.taskInit(function() --创建一个线程,500毫秒闪一次LED
    gpio.setup(27, 0)   -- 设置gpio27为输出,且初始化电平为低,使用硬件默认上下拉配置
    while true do
        gpio.toggle(27) --gpio翻转电平
        sys.wait(500)
    end
end)

--[[
    支持字体
    ["unifont_t_symbols","open_iconic_weather_6x_t","opposansm8","opposansm10","opposansm12","opposansm16","opposansm20",
    "opposansm24","opposansm32","sarasa_m8_ascii","sarasa_m10_ascii","sarasa_m12_ascii","sarasa_m14_ascii",
    "sarasa_m16_ascii","sarasa_m18_ascii","sarasa_m20_ascii","sarasa_m22_ascii"]
]]
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!

WiFi节点

固件下载地址:https://url.zeruns.tech/a7eXJ

main.lua文件:

由于描述超字数限制了,请到这篇文章看:https://blog.zeruns.tech/archives/747.html

用到的硬件

用到的硬件模块和购买地址:

元器件购买推荐立创商城,优惠注册链接:https://activity.szlcsc.com/invite/D03E5B9CEAAE70A4.html

板上所有元器件都可以在立创商城买到,在开源链接里的BOM表那点立即到立创商城下单可将用到的元器件一键导入到购物车。

物联网平台设置说明

具体看教程:https://blog.zeruns.tech/archives/747.html

其他开源项目推荐

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
暂无数据
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

评论

全部评论(1
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航