144|0

77

帖子

3

TA的资源

一粒金砂(高级)

楼主
 

【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

五.工程及代码

mission_one.rar (3.76 KB, 下载次数: 0)
点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表