ESP32移植Openharmony外设篇(9)NB-IOT

NB-IOT(窄带物联网)

模块介绍

NB-IoT(Narrowband Internet of Things)是一种低功耗广域物联网(LPWAN)技术,专为低功耗、低数据速率和大规模连接的物联网应用而设计。它采用窄带宽信道和低复杂度的调制方案,以实现长距离传输、室内外覆盖范围广和强鲁棒性等特点。

技术原理

NB-IoT是在LTE(Long Term Evolution)技术标准下的一种窄带物联网技术,它利用LTE网络的空闲资源,在现有LTE基础设施上进行部署,提供一种低功耗、长距离通信的解决方案。

NB-IoT采用窄带信道,每个信道带宽只有180 kHz,使其能够更好地穿透建筑物和障碍物,提供广阔的覆盖范围。

NB-IoT采用低复杂度的调制和编码方案,以降低终端设备的功耗,并支持大规模连接,可以同时连接大量的设备。

特点和优势

  • 低功耗:NB-IoT在待机和通信状态下都具有低功耗特性,可以延长设备的电池寿命。
  • 长距离传输:NB-IoT具有良好的传输性能,可以在长距离范围内进行通信,适用于广域覆盖的应用场景。
  • 室内外覆盖广:NB-IoT信号穿透能力强,可以有效地覆盖室内和室外环境,为物联网应用提供全面的覆盖。
  • 低成本:由于NB-IoT利用现有的LTE基础设施进行部署,无需建立单独的物联网网络,降低了网络部署和运营成本。
  • 大规模连接:NB-IoT支持大规模设备连接,每个基站可以同时处理大量的设备连接请求,适用于物联网中大量设备的应用场景。

应用领域

  • 城市智能化:NB-IoT可应用于智慧城市项目,如智能照明、智能交通、智能停车等。
  • 工业自动化:NB-IoT可用于监测和控制工业设备、机器健康监测、环境监测等。
  • 农业和环境监测:NB-IoT可用于农业领域的土壤湿度监测、气象数据收集、农作物灌溉控制等,以及环境监测领域的空气质量监测、水质监测等。
  • 物流和供应链管理:NB-IoT可以用于物流跟踪和监控,实现货物的追踪、温湿度监测、运输过程中的安全监控等。
  • 智能电表和能源管理:NB-IoT可用于智能电表的远程抄表和能源消耗监测,提供精确的用电数据和能源管理功能。
  • 健康医疗:NB-IoT可以应用于健康监测设备,如远程心率监测、血压监测等,实现远程医疗和健康管理。
  • 安全监控:NB-IoT可用于安防监控系统,如远程视频监控、智能门禁等,实现安全监控和报警功能。

原理图

我们这里通过使用AT指令集来控制NBIOT模块连接公网的TCP服务器

这里推荐一个免费的公网测试服务器:TCP服务端调试

我们使用的NBIOT模块是果云科技的GA7,相关AT指令集在网上能搜到,我们这里给出几个比较常见的AT指令

常见AT指令

  1. 命令回显
  1. 网络注册
  1. 获取信号质量
  1. 设置当前日期和时间
  1. 设置通讯波特率
  1. 指示sim卡状态
  1. 创建SOCKET套接字
  1. 连接远程服务器
  1. 发送数据
  1. 接收数据

参考代码

BUILD.gn

复制代码
# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name){
    sources = [
        "uart_example.c",
    ]
    include_dirs = [
        "//drivers/hdf_core/framework/include/platform/",
        "//drivers/hdf_core/framework/include/utils/",
        "//drivers/hdf_core/framework/support/platform/include/uart",
        "//drivers/hdf_core/adapter/khdf/liteos_m/osal/include/",
        "//drivers/hdf_core/framework/include/core/",
        "//drivers/hdf_core/framework/include/osal/",
        "//device/soc/esp/esp32/components/driver/include",
        "//device/soc/esp/esp32/components/esp_adc_cal/include",
        "//device/soc/esp/esp32/components/driver/esp32/include",
    ]
}

uart_example.c

复制代码
/*
 * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include "cmsis_os2.h"
#include "ohos_run.h"
#include <stdio.h>
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"

#define SYS_DELAY_TICKS 200
#define TASK_STACK_SIZE 4096
#define TASK_PRIO 25
#define BUFF_MAX_SIZE 128
#define UART_BAUDRATE 115200

#define UART_INDEX 0 // 串口号

osThreadId_t g_taskID = NULL;

// 定义串口的引脚
#define ECHO_TEST_TXD (GPIO_NUM_32)
#define ECHO_TEST_RXD (GPIO_NUM_33)
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)

#define ECHO_UART_PORT_NUM (UART_NUM_1)
#define ECHO_UART_BAUD_RATE (115200)

#define BUF_SIZE (1024)

static void uart_test(void)
{
    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = ECHO_UART_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
    };
    int intr_alloc_flags = 0;

#if CONFIG_UART_ISR_IN_IRAM
    intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif

    ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE, BUF_SIZE, 0, NULL, intr_alloc_flags));
    ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));

    // Configure a temporary buffer for the incoming data
    uint8_t *data = (uint8_t *)malloc(BUF_SIZE);

    printf("start recv nbiot!\n");

    // Write data back to the UART
    uart_write_bytes(ECHO_UART_PORT_NUM, "AT\r\n", strlen("AT\r\n"));

    // Read data from the UART
    int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);

    if (len)
    {
        data[len] = '\0';
        printf("Recv str: %s\r\n", (char *)data);
    }

    // 取消回显
    uart_write_bytes(ECHO_UART_PORT_NUM, "ATE0\r\n", strlen("ATE0\r\n"));

    // 询问SIM卡激活情况
    uart_write_bytes(ECHO_UART_PORT_NUM, "AT+CPIN?\r\n", strlen("AT+CPIN?\r\n"));
    len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
    if (len)
    {
        data[len] = '\0';
        printf("%s\r\n", (char *)data);
    }

    // 询问模块注册情况
    uart_write_bytes(ECHO_UART_PORT_NUM, "AT+CREG?\r\n", strlen("AT+CREG?\r\n"));
    len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
    if (len)
    {
        data[len] = '\0';
        printf("%s\r\n", (char *)data);
    }

    // 此处需要休眠10秒,等待模块初始化完成
    sleep(10);
    // 询问模块注册情况
    uart_write_bytes(ECHO_UART_PORT_NUM, "AT+CREG?\r\n", strlen("AT+CREG?\r\n"));
    len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
    if (len)
    {
        data[len] = '\0';
        printf("%s\r\n", (char *)data);
    }

    // 创建链接
    uart_write_bytes(ECHO_UART_PORT_NUM, "AT+SKTCREATE=1,1,6\r\n", strlen("AT+SKTCREATE=1,1,6\r\n"));
    // 等待2秒
    sleep(2);
    // 链接到TCP服务器 AT+SKTCONNECT=0,8.135.10.183,31217
    uart_write_bytes(ECHO_UART_PORT_NUM, "AT+SKTCONNECT=0,8.135.10.183,31217\r\n", strlen("AT+SKTCONNECT=0,8.135.10.183,31217\r\n"));
    len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
    if (len)
    {
        data[len] = '\0';
        printf("%s\r\n", (char *)data);
    }

    // 这里可以接受TCP数据了
    while (1)
    {
        // Read data from the UART
        len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);

        if (len)
        {
            data[len] = '\0';
            printf("Recv str: %s\r\n", (char *)data);
        }
    }

    return;
}

#define AT_CMD_MAX_LEN 256
// TCP发送数据
int send_tcp_message(char *msg)
{
    unsigned char ret;
    char at_sktsend[AT_CMD_MAX_LEN] = {'\0'};
    char hex_str[65] = {'\0'};

    if (msg == NULL)
    {
        return -1;
    }
    ret = str2hex(msg, hex_str, 65);
    if (ret != 1)
    {
        return -2;
    }
    snprintf(at_sktsend, AT_CMD_MAX_LEN, "AT+SKTSEND=0,%d,%s\r\n", strlen(msg), hex_str);
    printf("at_sktsend:%s\r\n", at_sktsend);
    uart_write_bytes(ECHO_UART_PORT_NUM, at_sktsend, strlen(at_sktsend));
}

static void uart_example_task(void)
{
    printf("into uart hdf example!\n");
    osThreadAttr_t attr;
    attr.name = "uart_test";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = TASK_STACK_SIZE;
    attr.priority = TASK_PRIO;
    g_taskID = osThreadNew((osThreadFunc_t)uart_test, NULL, &attr);
    if (g_taskID == NULL)
    {
        printf("Failed to create Test Uart thread!\n");
    }
}

OHOS_APP_RUN(uart_example_task);

编译并烧录

在源码根目录下使用hb工具对写好的代码进行编译

选择mini级系统

同理 产品选择esp公司下的esp32

选择完毕后在源码根目录下执行hb build -f 进行编译

编译完成后会有如下界面,并且编译后的代码固件位于:out\esp32\esp32

实验现象

按下ESP32开发板上的EN键,即可观察到实验现象:

我们在公网的TCP测试服务器中可以发送测试数据,串口助手中会收到对应的ASCII码:

串口助手打印的提示消息如下:

相关推荐
星恒讯工业路由器26 分钟前
5G SA+NSA 灵活组网:如何助力行业数字化转型?——以星恒讯工业5G方案为例
网络·物联网·智能路由器·信息与通信
云水一下1 小时前
华为防火墙安全区域与NAT实战:基于eNSP的企业边界网完整部署
安全·华为·nat·下一代防火墙
小雨青年1 小时前
鸿蒙 HarmonyOS 6 | Pura X Max 鸿蒙原生适配 06:GridRow 做卡片自适应布局
华为·harmonyos
方山子哦2 小时前
软硬件uart、iic、spi、can,及蓝牙和usb的区别及应用场景
单片机·嵌入式硬件
前端不太难2 小时前
一套鸿蒙 App,如何跑在手机 / 平板 / TV?
智能手机·电脑·harmonyos
想你依然心痛2 小时前
HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“灵犀智脑“——PC端AI智能体工作流编排平台
人工智能·华为·harmonyos·智能体
AI周红伟2 小时前
All in Token,移动,电信和联通,华为,阿里,百度,字节,卖Token Plan,卖算力时代结束,卖智力时代来了:Token经济万亿赛道全景解码
大数据·人工智能·机器学习·百度·华为·copilot·openclaw
轻口味3 小时前
HarmonyOS 6.1 全栈实战录 - 10 极光星图:Map Kit 6.1 3D地球、城市灯光与Marker碰撞深度实战
3d·华为·harmonyos
czwxkn3 小时前
pcb设计-电路:IO口的灌电流与拉电流
单片机·嵌入式硬件
枫叶丹43 小时前
【HarmonyOS 6.0】Device Security Kit安全审计阻断功能深度解析
开发语言·安全·华为·harmonyos