【Follow me第二季第4期】①任务一:Blink与串口打印
[复制链接]
本帖最后由 不爱胡萝卜的仓鼠 于 2024-12-24 09:18 编辑
任务一:搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!
一.环境搭建
环境搭建都写在一篇文章里了,后续任务不再介绍环境搭建了,这里一次性会把需要的开发板、库都安装好
首先需要下载arduino IDE,链接:Arduino官网下载地址。我下载的最新的2.3.4
然后需要添加RP2040开发板
我还买了一块ESP32,ESP32开发板也同理(ESP32需要在 文件 -- 首选项 -- 其他开发板管理器地址 中添加一个地址才能被搜索到:https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json)
然后为了使用RP2040上的三色LED灯、WIFI,需要安装WiFiNINA的库
使用RP2040开发板上的加速度、陀螺仪传感器,需要安装Arduino_LSM6DSOX的库
至此开发环境就OK了,如下编译和下载程序等这里就不说了,网上有很多资料可以学习
二.功能实现说明
基础的点灯,串口功能比较基础,有点没意思,我看到RP2040 connect有带BLE和WiFi,因此我额外购买了一块ESP32-S3。我想实现通过WiFi的方式实现点灯,顺便可以学习一下Arduino上如何连接WiFi、启动server、作为client连接server、TCP通讯数据收发等。
RP2040:上电后实现三色LED、LED的闪烁,并串口打印指定内容。随后连接WiFi,启动server,等待client连接,并接收控制指令,执行指令对应的代码。
ESP32:上电后连接WiFi,并以Client的角色连接server,通过TCP通讯发送控制指令给RP2040,控制2040的LED灯
三.相关资料学习
从原理图可以知道,RP2040的三色LED灯不是直连2040芯片GPIO的,是通过板载无线通讯模块间接控制的,2040与他是串口或SPI通讯,我理解是使用BLE时通过串口,并可以实现低功耗状态;使用WiFi时通过SPI。
普通的LED灯是直连2040的一个GPIO,控制普通LED灯就只要像控制普通输出模式的GPIO即可
串口就没啥好看得了,2040没有使用USB转串口芯片,USB接口直连芯片,应该就是走的USB虚拟串口的方式
原理图看完了,就来看看指导文档吧,串口和GPIO控制就不看了,网上也有很多资料,都是通用的东西
我们着重来看看RGB灯,官方文档链接:RBG。这个链接介绍了如何使用RGB灯,具体代码就自己看了,我把需要注意事项提炼一下
1.需要安装WiFiNINA这个库(我们搭建环境时就安装好了)
2.使用NINA库的BLE功能时,RGB灯是不能被使用的,因为此时SPI被关闭,这样就无法控制RGB了。官方原文如下:“Please note: While using the Bluetooth® Low Energy mode on the NINA module, the RGB cannot be used by default. While the module is in Bluetooth® Low Energy mode, SPI is deactivated, which is used to control the RGBs.”
因此我没有使用BLE控制LED灯,而是使用WiFi。不过我有个疑问,如果我要用BLE控制RGB是不是就没有办法了?我不考虑低功耗需求,能不能让他把SPI也开起来,这样我就可以控制RGB灯了?但是很可惜我没有找到官方有相关的说明
四.代码及流程图
两个开发板的流程图和代码如下。代码我就不做详细解读了,注释写的很详细了。
使用时需要注意的就是:如果不想要WiFi控制LED功能的,只要烧录2040代码即可,也满足任务的要求(关闭需要修改WIFI_CTL_LED这个宏定义为0,默认是1)。如果要的,两个板子的wifi_info.h中都需要填写WiFi账号密码,并且ESP32代码中IP地址也要修改成2040实际被路由器分配到的IP地址
4.1 2040流程图
4.2 RP2040代码
/***************************/
//RGB LED需要安装WiFiNINA库,
/***************************/
#include <WiFiNINA.h>
#include <SPI.h>
#define WIFI_CTL_LED (1)
#if WIFI_CTL_LED
#include "wifi_info.h"
const char wifi_ssid[] = SECRET_SSID;
const char wifi_password[] = SECRET_PASS;
int wifi_conn_state = WL_IDLE_STATUS;
#define SERVER_PORT (80)
WiFiServer server(SERVER_PORT);
void printWifiStatus()
{
/* 打印WiFi SSID */
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
/* 打印IP地址 */
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
/* 打印信号强度 */
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
#endif
void setup()
{
/* 初始化串口 */
Serial.begin(115200);
/* delay一下,保证串口监视器成功连接 */
delay(3000);
/* 初始化LED灯的GPIO,并开灯 */
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
/* 初始RGB LED灯的GPIO,并开灯 */
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, HIGH);
/* 打印和闪灯,完成指定任务 */
for(uint8_t j = 0; j < 4; j++)
{
Serial.println("Hello DigiKey & EEWorld!");
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(LEDR, LOW);
digitalWrite(LEDG, LOW);
digitalWrite(LEDB, LOW);
delay(1000);
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, HIGH);
delay(1000);
}
#if WIFI_CTL_LED
/* 检查wifi模块状态是否可用 */
if (WiFi.status() == WL_NO_MODULE)
{
Serial.println("Communication with WiFi module failed!");
while (1);
}
/* 检查wifi模块版本号(非必选,可去掉) */
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION)
{
Serial.println("now wifi firmware = " + fv + ", lastest version is " +
WIFI_FIRMWARE_LATEST_VERSION + ", suggest update!");
}
/* 检查SSID和PSW是否填写 */
if (strlen(wifi_ssid) <= 0)
{
Serial.println("ERROR: Plase enter WiFi SSID in \"wifi_info.h\"");
while(1);
}
if (strlen(wifi_password) <= 0)
{
Serial.println("ERROR: Plase enter WiFi password in \"wifi_info.h\"");
while(1);
}
/* 尝试使用预设的账号密码,连接路由器 */
uint8_t i = 0;
for (i = 0; i < 5; i++) //wifi连接超时时间5 * 10s
{
wifi_conn_state = WiFi.begin(wifi_ssid, wifi_password);
if (WL_CONNECTED == wifi_conn_state)
{
Serial.println("wifi connect success");
break;
}
delay(10000);
}
if (i == 5)
{
Serial.println("wifi connect failed");
while(1);
}
/* 打印wifi信息 */
printWifiStatus();
/* 开启客户端 */
server.begin();
Serial.print("server started,addr:");
Serial.print(WiFi.localIP());
Serial.print(":");
Serial.println(SERVER_PORT);
#endif
}
void loop()
{
#if WIFI_CTL_LED
WiFiClient client = server.available(); // listen for incoming clients
/* 是否有客户端连接我 */
if (client)
{
/* 打印,提示有客户端连接我 */
Serial.println("new client");
/* 从client接收到的数据的buffer */
String recv_buffer = "";
/* 持续监测客户端是否与我断连 */
while (client.connected())
{
/* 客户端是否可用 */
if (client.available())
{
/* 读取客户端发送的数据,并串口打印 */
/* read接口一次只能读一个字节,每读取一个字节后就把它拼到recv_buffer中 */
char c = client.read();
Serial.write(c);
recv_buffer += c;
/* 通过检查字符串结尾和制定的字符串是否一致,来决定是否需要执行开关灯指令 */
if (recv_buffer.endsWith("CTL_RGB_R_ON"))
{
digitalWrite(LEDR, HIGH);
}
if (recv_buffer.endsWith("CTL_RGB_R_OFF"))
{
digitalWrite(LEDR, LOW);
}
if (recv_buffer.endsWith("CTL_RGB_G_ON"))
{
digitalWrite(LEDG, HIGH);
}
if (recv_buffer.endsWith("CTL_RGB_G_OFF"))
{
digitalWrite(LEDG, LOW);
}
if (recv_buffer.endsWith("CTL_RGB_B_ON"))
{
digitalWrite(LEDB, HIGH);
}
if (recv_buffer.endsWith("CTL_RGB_B_OFF"))
{
digitalWrite(LEDB, LOW);
}
if (recv_buffer.endsWith("CTL_LED_ON"))
{
digitalWrite(LED_BUILTIN, HIGH);
}
if (recv_buffer.endsWith("CTL_LED_OFF"))
{
digitalWrite(LED_BUILTIN, LOW);
}
}
}
/* 客户端与我断连,需要关闭client连接,并打印提示信息 */
client.stop();
Serial.println("client disconnected");
/* 断连后灯回复原装 */
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, HIGH);
}
#else
Serial.println("Hello DigiKey & EEWorld!");
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, HIGH);
delay(1000);
Serial.println("Hello DigiKey & EEWorld!");
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(LEDR, LOW);
digitalWrite(LEDG, LOW);
digitalWrite(LEDB, LOW);
delay(1000);
#endif
}
4.3 ESP32流程图
4.4 ESP32代码
#include <Arduino.h>
#include <WiFi.h>
#include "wifi_info.h"
const char wifi_ssid[] = SECRET_SSID;
const char wifi_password[] = SECRET_PASS;
int wifi_conn_state = WL_IDLE_STATUS;
const IPAddress serverIP(192,168,31,215); //填写服务器的实际IP地址
uint16_t serverPort = 80; //端口默认80,服务器端也是默认80
WiFiClient client;
void printWifiStatus()
{
/* 打印WiFi SSID */
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
/* 打印IP地址 */
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
/* 打印信号强度 */
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void wifi_init()
{
/* 设置工作在STA模式 */
WiFi.mode(WIFI_STA);
/* 断开之前的连接 */
WiFi.disconnect(true, true);
}
void wifi_connect_AP()
{
/* 检查SSID和PSW是否填写 */
if (strlen(wifi_ssid) <= 0)
{
Serial.println("ERROR: Plase enter WiFi SSID in \"wifi_info.h\"");
while(1);
}
if (strlen(wifi_password) <= 0)
{
Serial.println("ERROR: Plase enter WiFi password in \"wifi_info.h\"");
while(1);
}
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(wifi_ssid);
/* 尝试使用预设的账号密码,连接路由器 */
uint8_t i = 0;
WiFi.begin(wifi_ssid, wifi_password);
/* 检测是否链接成功 */
for (i = 0; i < 20; i++)
{
delay(500);
if (WiFi.status() != WL_CONNECTED)
{
Serial.println("wifi connect success");
/* delay一会儿,等待IP等信息都拿到了再继续后续操作 */
delay(3000);
break;
}
}
if (i == 20)
{
Serial.println("wifi connect failed");
while(1);
}
/* 打印wifi信息 */
printWifiStatus();
}
void connect_server()
{
if (client.connect(serverIP, serverPort))
{
Serial.println("Connected to server");
}
else
{
Serial.println("Connection failed");
while(1);
}
}
void setup()
{
/* 初始化串口 */
Serial.begin(115200);
/* 初始化wifi模块 */
wifi_init();
/* wifi连接路由器 */
wifi_connect_AP();
/* 连接到服务器 */
connect_server();
}
void loop()
{
String cmd1 = "CTL_LED_ON";
String cmd2 = "CTL_LED_OFF";
/* 如果连接到服务器,就定时发送开关灯指令 */
if (client.connected())
{
Serial.println("ON");
client.write(cmd1.c_str());
delay(1000);
Serial.println("0FF");
client.write(cmd2.c_str());
delay(1000);
}
}
4.5 wifi_info.h
二者的WiFi密码均各自有wifi.h文件配置,需要使用者填写一个可以正常使用的WiFi账号密码。2040和ESP32的这个文件内容内容一致,代码如下:
#define SECRET_SSID ""
#define SECRET_PASS ""
四.效果展示
IMG_7662
EE大学堂视频链接:https://training.eeworld.com.cn/video/42146
五.工程及代码
|