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. 命令回显
2. 网络注册
3. 获取信号质量
4. 设置当前日期和时间
5. 设置通讯波特率
6. 指示sim卡状态
7. 创建SOCKET套接字
8. 连接远程服务器
9. 发送数据
10. 接收数据
参考代码
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_IRAMintr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endifESP_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 datauint8_t *data = (uint8_t *)malloc(BUF_SIZE);printf("start recv nbiot!\n");// Write data back to the UARTuart_write_bytes(ECHO_UART_PORT_NUM, "AT\r\n", strlen("AT\r\n"));// Read data from the UARTint 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,31217uart_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 UARTlen = 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码:
串口助手打印的提示消息如下: