【Funpack2-6】基于nRF7002开发板WIFI功能的LED控制及按键监控
使用nRF7002开发板开发的LED控制及按键监控系统,通过wifi入网,连接mqtt服务器,然后监听led控制话题用来接收led控制命令以及通过button状态话题发布最新的按键状态。
标签
Funpack活动
nRF7002
wakojosin
更新2023-10-08
792

功能简介

本项目是基于nRF7002DK开发板开发设计的LED控制和按键监控系统。nRF7002DK开发板主控芯片是nRF5340单片机,此单片机是基于ARM Cortex-M33内核的双核单片机,拥有项目主要用到的单片机外设有ADC、I2C、SPI、PWM、UART和GPIO,包含的硬件有LCD屏、nst112温度传感器、LED灯和按键。

实现思路

通过Wi-Fi连接路由器实现网络通讯功能,然后通过MQTT协议实现设备端和应用端的通讯,最后通过LED和按键完成整个功能的展示。

FuNI441IGny4Fx3dgzsNRI2z3M5_

 

硬件连接

硬件上主要涉及到nRF5340与按键、LED、nRF7002之间的连接,原理图如下:

按键:

按键1连接到了P1.08,按键2连接到了P1.09,触发电平是低电平,空闲电平是高电平。

FnrVviyhiXnHc8SSKZ5rAbI1xqa3

LED:

LED1连接到了P1.06,LED2连接到了P1.07,触发电平是高电平。

FusCgHoANuroOoXn6S6EdxjKcXqR

nRF7002:通过QSPI与主控进行数据通讯。

Fij06gCmOs2cVxUak7dwTgvVU-n2

 

代码分析

软件整体的逻辑图:

FmMX3pLA9UUSTtcHrTpR3zMBDZ8Q

首先是主函数:

void main(void)
{
    int rc;
    struct net_if *iface = net_if_get_default();
    struct wifi_connect_req_params cnx_params = { 0 };
    /* Sleep 1 seconds to allow initialization of wifi driver. */
    k_sleep(K_SECONDS(1));

    /* Configurate net controller. */
    LOG_INF("Configuration found. Try to apply.\n");

    cnx_params.ssid = "PDD";
    cnx_params.ssid_length = strlen(cnx_params.ssid);
    cnx_params.security = WIFI_SECURITY_TYPE_PSK;

    cnx_params.psk = NULL;
    cnx_params.psk_length = 0;
    cnx_params.sae_password = NULL;
    cnx_params.sae_password_length = 0;

    cnx_params.psk = "12345678";
    cnx_params.psk_length = strlen(cnx_params.psk);

    cnx_params.channel = WIFI_CHANNEL_ANY;
    cnx_params.band = WIFI_FREQ_BAND_2_4_GHZ;
    cnx_params.mfp = WIFI_MFP_OPTIONAL;
    rc = net_mgmt(NET_REQUEST_WIFI_CONNECT, iface,
        &cnx_params, sizeof(struct wifi_connect_req_params));
    if (rc < 0) {
        LOG_ERR("Cannot apply saved Wi-Fi configuration, err = %d.\n", rc);
    } else {
        LOG_INF("Configuration applied.\n");
    }

    net_mgmt_init_event_callback(&wifi_prov_cb,
                        wifi_connect_handler,
                        NET_EVENT_WIFI_CONNECT_RESULT);

    net_mgmt_add_event_callback(&wifi_prov_cb);
    k_sem_take(&wifi_connected_sem, K_FOREVER);
    /* Wait for the interface to be up */
    k_sleep(K_SECONDS(6));
    LOG_INF("Connecting to MQTT Broker...");
    /* Connect to MQTT Broker */
    init_hw_and_connect_mqtt();
}

主函数主要功能是配置网络控制器来配置Wi-Fi连接,等Wi-Fi连接完成之后进行硬件相关及MQTT的初始化。

rc = net_mgmt(NET_REQUEST_WIFI_CONNECT, iface,
        &cnx_params, sizeof(struct wifi_connect_req_params));
net_mgmt的定义如下:
#define net_mgmt(_mgmt_request, _iface, _data, _len)            \
    net_mgmt_##_mgmt_request(_mgmt_request, _iface, _data, _len)
展开之后如下:
net_mgmt_NET_REQUEST_WIFI_CONNECT(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params, sizeof(struct wifi_connect_req_params));
通过FUNC_ALIAS来关联net_mgmt_NET_REQUEST_WIFI_CONNECT和wifi_connect,也就是说当调用上面的net_mgmt函数时也就是调用了wifi_connect函数,并将对应的参数传入进去。

网络配置通过wifi_connect_req_params数据对象进行初始化的,里面包含的ssid、密码、加密方式,频段等信息。

下面是硬件及MQTT的初始化过程

static void init_hw_and_connect_mqtt(void)
{
	int err;
	uint32_t connect_attempt = 0;

	if (dk_leds_init() != 0) {
		LOG_ERR("Failed to initialize the LED library");
	}

	if (dk_buttons_init(button_handler) != 0) {
		LOG_ERR("Failed to initialize the buttons library");
	}

	err = client_init(&client);
	if (err) {
		LOG_ERR("Failed to initialize MQTT client: %d", err);
		return;
	}

do_connect:
	if (connect_attempt++ > 0) {
		LOG_INF("Reconnecting in %d seconds...",
			CONFIG_MQTT_RECONNECT_DELAY_S);
		k_sleep(K_SECONDS(CONFIG_MQTT_RECONNECT_DELAY_S));
	}
	err = mqtt_connect(&client);
	if (err) {
		LOG_ERR("Error in mqtt_connect: %d", err);
		goto do_connect;
	}

	err = fds_init(&client,&fds);
	if (err) {
		LOG_ERR("Error in fds_init: %d", err);
		return;
	}

	while (1) {
		err = poll(&fds, 1, mqtt_keepalive_time_left(&client));
		if (err < 0) {
			LOG_ERR("Error in poll(): %d", errno);
			break;
		}

		err = mqtt_live(&client);
		if ((err != 0) && (err != -EAGAIN)) {
			LOG_ERR("Error in mqtt_live: %d", err);
			break;
		}

		if ((fds.revents & POLLIN) == POLLIN) {
			err = mqtt_input(&client);
			if (err != 0) {
				LOG_ERR("Error in mqtt_input: %d", err);
				break;
			}
		}

		if ((fds.revents & POLLERR) == POLLERR) {
			LOG_ERR("POLLERR");
			break;
		}

		if ((fds.revents & POLLNVAL) == POLLNVAL) {
			LOG_ERR("POLLNVAL");
			break;
		}
	}

	LOG_INF("Disconnecting MQTT client");

	err = mqtt_disconnect(&client);
	if (err) {
		LOG_ERR("Could not disconnect MQTT client: %d", err);
	}
	goto do_connect;
}

mqtt初始化函数里面最关键的两个任务就是mqtt_live和mqtt_input,mqtt_live用来维持mqtt的心跳,需要周期性的调用,mqtt_input用来处理接收到的mqtt数据包。

通过client_init来初始化mqtt客户端结构体对象,通过mqtt_connect来连接mqtt服务器。

通过poll机制来监听mqtt的数据包。

功能展示

连接网络和MQTT是自动的,通过日志来展示连接过程,日志里展示了Wi-Fi连接的结果,动态获取到的IP地址,MQTT服务器连接的结果及订阅的话题:

FlipfIgz7VjuLg1UAt1bTciCfJzF

应用连接相应的话题:

FjJIDAKYbTaAU07b1Gp8sylFAUww

LED控制:

通过发送LED相关的命令来触发LED的亮灭。

Ft2S81EzDlKlIyfER4Mos3ruOaU7FjXsC3ivdZ0zsdJ8HVsuA8JN2xmX

按键监控,当按下按键的时候,会上报对应的消息,按键1对应的BTN_1_PRES,按键2对应BTN_2_PRES:

FmcLDpL9aBKhbuoZy3MullaT8OGw

心得体会

通过本次活动,了解了nRF5340单片机和nRF7002网络协处理器的相关功能、性能参数,了解了开发环境的搭建,了解ncs相关API的使用,主要涉及网络、sdk、mqtt相关的API。期待下一期的活动。

附件下载
mqtt_led_btn_nrf7002DK.zip
代码
团队介绍
个人
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号