67|0

2

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【Follow me第二季第4期】任务提交 [复制链接]

  本帖最后由 坛/我=佬 于 2025-1-13 14:18 编辑

一、视频介绍


 

二、任务实现详情

必做任务搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!
物料清单:Arduino Nano RP2040 Connect
设计思路:
Arduino Nano RP2040 Connect板载一颗共阳RGB LED,但是没有直接连接到RP2040的IO上,而是连接到Nina W102 Wi-Fi/Bluetooth模组的IO上。
由原理图可知,当Nina W102的IO输出高电平时,LED熄灭;输出低电平时,LED点亮。对应代码为digitalWrite(LEDR, LOW)熄灭LED,digitalWrite(LEDR, HIGH)点亮LED。
所以本质上是RP2040通过SPI控制W102模组的IO,使其输出高低电平,进一步控制RGB LED亮灭。但是Arduino通过WiFiNINA library简化了这个步骤,使用pinMode、digitalWrite等函数就可以控制,具体的实现流程被封装到WiFiNINA库里面。因此,要控制板载的RGB LED,首先需要安装WiFiNINA库并调用。
RP2040片上具有USB1.1控制器和PHY,支持Host和Device模式。Arduino官方基于此硬件设计了bootloader,使该USB接口具有下载代码和串口调试的功能。
软件流程图
 
代码实现
#include <SPI.h>
#include <WiFiNINA.h>

void setup() {
  Serial.begin(115200);      // initialize serial communication
  delay(500);
  while(!Serial);            //等待串口初始化完毕
  // {
  //   Serial.println("Serial init failed!");
  //   while(1);
  // }

  Serial.println("Programme Starting!");
  Serial.println("Hello DigiKey & EEWorld!");  //打印信息

  pinMode(LEDR, OUTPUT);        //初始化RGB引脚
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);
  
  digitalWrite(LEDR, LOW);      //设置RGB引脚默认状态为低,对应熄灭状态
  digitalWrite(LEDG, LOW);
  digitalWrite(LEDB, LOW);
}

void loop() {
  digitalWrite(LEDR, HIGH);     //显示红色
  digitalWrite(LEDG, LOW);
  digitalWrite(LEDB, LOW);
  delay(500);
  digitalWrite(LEDR, LOW);      //显示绿色
  digitalWrite(LEDG, HIGH);
  digitalWrite(LEDB, LOW);
  delay(500);
  digitalWrite(LEDR, LOW);      //显示蓝色
  digitalWrite(LEDG, LOW);
  digitalWrite(LEDB, HIGH);
  delay(500);
}

功能展示

必做任务二:学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据
物料清单:Arduino Nano RP2040 Connect
设计思路:
Arduino Nano RP2040 Connect板载一颗六轴IMU(LSM6DSOXTR),内置3轴加速度计和3轴陀螺仪,通过3轴加速度计可以获得物体的运动方向,通过3轴陀螺仪可以获得物体的旋转角度。LSM6DSOXTR的具体参数如下
LSM6DSOXTR通过IIC与LSM6DSOXTR进行通信,并且由于RP2040配置为IIC模式时,IO口为开漏输出,需要通过硬件对SCL和SDA两根信号线进行上拉操作。
要通过IIC对LSM6DSOXTR进行操作,首先需要安装对应的Arduino_LSM6DSOX library,里面包含Arduino官方封装过的API函数,可以快速上手获取IMU的加速度和陀螺仪原始数据。
软件流程图
 
代码实现
#include <Arduino_LSM6DSOX.h>

float Ax, Ay, Az;
float Gx, Gy, Gz;

void setup() {
  Serial.begin(115200);

  while(!Serial);             //防止程序run直到串口打开

  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");
    while (1);
  }

  Serial.print("Accelerometer sample rate = ");
  Serial.print(IMU.accelerationSampleRate());
  Serial.println("Hz");
  Serial.println();

  Serial.print("Gyroscope sample rate = ");  
  Serial.print(IMU.gyroscopeSampleRate());
  Serial.println("Hz");
  Serial.println();

}

void loop() {

  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(Ax, Ay, Az);

    Serial.println("Accelerometer data: ");
    Serial.print(Ax);
    Serial.print('\t');
    Serial.print(Ay);
    Serial.print('\t');
    Serial.println(Az);
    Serial.println();
  }

  if (IMU.gyroscopeAvailable()) {
    IMU.readGyroscope(Gx, Gy, Gz);
    
    Serial.println("Gyroscope data: ");
    Serial.print(Gx);
    Serial.print('\t');
    Serial.print(Gy);
    Serial.print('\t');
    Serial.println(Gz);
    Serial.println();
  }

delay(500);

}

功能展示

 
必做任务三:学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形
物料清单:Arduino Nano RP2040 Connect
设计思路:
Arduino Nano RP2040 Connect板载一颗全向MEMS麦克风(MP34DT06JTR),可以用来感知外界环境的声音变化,并将其记录并量化为数值。MP34DT06JTR的具体参数如下
MP34DT06JTR通过PDM接口与RP2040连接。操作MEMS麦克风也需要额外的PDM library,但是与任务一和任务二不同的是,在安装Arduino Nano RP2040 Connect板的时候,内部就已经带了PDM library,不需要额外搜索安装,直接用就可以。
软件流程图
 
代码实现
#include <PDM.h>

// default number of output channels
static const char channels = 1;

// default PCM output frequency
static const int frequency = 20000;

// Buffer to read samples into, each sample is 16-bits
short sampleBuffer[512];

// Number of audio samples read
volatile int samplesRead;

void setup() {
  Serial.begin(115200);
  while (!Serial);
  // Configure the data receive callback
  PDM.onReceive(onPDMdata);

  if (!PDM.begin(channels, frequency)) {
    Serial.println("Failed to start PDM!");
    while (1);
  }
}

void loop() {
  // Wait for samples to be read
  if (samplesRead) {

    // Print samples to the serial monitor or plotter
    for (int i = 0; i < samplesRead; i++) {
      if (channels == 2) {
        Serial.print("L:");
        Serial.print(sampleBuffer[i]);
        Serial.print(" R:");
        i++;
      }
      Serial.println(sampleBuffer[i]);

    }

    // Clear the read count
    samplesRead = 0;
  }
}

void onPDMdata() {
  // Query the number of available bytes
  int bytesAvailable = PDM.available();

  // Read into the sample buffer
  PDM.read(sampleBuffer, bytesAvailable);

  // 16-bit, 2 bytes per sample
  samplesRead = bytesAvailable / 2;
}

功能展示

 
扩展任务:雷达感应氛围灯
物料清单:Arduino Nano RP2040 Connect、6x10 RGB MATRIX、24GHz mmWave
来自seeed的XIAO RGB灯板,上面一共有6x10个RGB灯珠
来自seeed的24GHz mmWave雷达传感器,可以用来检测附近是否有人存在
设计思路:
当人离开电脑长时间不使用时,电脑会进入休眠状态节省电量。同理,当人离开桌面时,氛围灯关闭;重新回来时,氛围灯开启。一方面可以带来绚丽多彩的氛围特效,另一方面还可以节省电量。
24GHz mmWave通过串口与RP2040通信,RP2040接收到串口数据后,对数据进行解析,从而获取到传感器识别到的当前状态。在使用前需要安装mmwave_for_xiao library。模块参数如下
6x10 RGB MATRIX通过级联方式可以控制60个RGB,同时还可以通过板与板之间级联,方便扩展,采用WS2812灯珠。使用前需要安装Adafruit_NeoPixel library可以方便控制指定颜色和指定灯珠。特性如下
软件流程图
 
代码实现
#include <mmwave_for_xiao.h>
#include <Adafruit_NeoPixel.h>

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN        25 // On Trinket or Gemma, suggest changing this to 1

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 60 // Popular NeoPixel ring size

// Creates a global Serial object for printing debugging information
#define ShowSerial Serial

// Initialising the radar configuration
// Seeed_HSP24 xiao_config(COMSerial, ShowSerial);
Seeed_HSP24 xiao_config(Serial1);

Seeed_HSP24::RadarStatus radarStatus;

// When setting up the NeoPixel library, we tell it how many pixels,
// and which pin to use to send signals. Note that for older NeoPixel
// strips you might need to change the third parameter -- see the
// strandtest example for more information on possible values.
Adafruit_NeoPixel strip(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels

void setup() {
  ShowSerial.begin(115200);
  Serial1.begin(115200);
  while(!ShowSerial);
  delay(500);

  strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.setBrightness(64);
  ShowSerial.println("Programme Starting!");

  xiao_config.disableEngineeringModel();        //关闭工程上报模式,此时为基本上报模式
  // xiao_config.enableEngineeringModel();         //开启工程上报模式
}

void loop() {
  int retryCount = 0;
  const int MAX_RETRIES = 10;  // Maximum number of retries to prevent infinite loops

  //Get radar status
  do {
    radarStatus = xiao_config.getStatus();
    retryCount++;
  } while (radarStatus.targetStatus == Seeed_HSP24::TargetStatus::ErrorFrame && retryCount < MAX_RETRIES);

  //Parses radar status and prints results from debug serial port
  if (radarStatus.targetStatus != Seeed_HSP24::TargetStatus::ErrorFrame) {
    ShowSerial.print("Status: " + String(targetStatusToString(radarStatus.targetStatus)) + " ---- ");
    ShowSerial.println("Distance: " + String(radarStatus.distance) + "  Mode: " + String(radarStatus.radarMode));

    if (radarStatus.radarMode == 1) {             //如果工程上报模式开启,为1
      ShowSerial.print("Move:");
      for (int i = 0; i < 9; i++) {
        ShowSerial.print(" " + String(radarStatus.radarMovePower.moveGate[i]) + ",");
      }
      ShowSerial.println("");
      ShowSerial.print("Static:");
      for (int i = 0; i < 9; i++) {
        ShowSerial.print(" " + String(radarStatus.radarStaticPower.staticGate[i]) + ",");
      }
      ShowSerial.println("");
      ShowSerial.println("Photosensitive: " + String(radarStatus.photosensitive));
    }

  }

  delay(100);
}

// Parsing the acquired radar status
const char* targetStatusToString(Seeed_HSP24::TargetStatus status) {
  switch (status) {
    case Seeed_HSP24::TargetStatus::NoTarget:
    {
      // if(radarStatus.noTargrtduration > 1000)
      // {

      // }

      return "NoTarget";
    }
      
    case Seeed_HSP24::TargetStatus::MovingTarget:
    {
      colorWipe(strip.Color(255,   0,   0), 50);    // Red
      colorWipe(strip.Color(  0, 255,   0), 50);    // Green
      colorWipe(strip.Color(  0,   0, 255), 50);    // Blue
      // theaterChase(strip.Color(127, 127, 127), 50); // White
      // theaterChase(strip.Color(127,   0,   0), 50); // Red
      // theaterChase(strip.Color(  0,   0, 127), 50); // Blue
      return "MovingTarget";
    }
      
    case Seeed_HSP24::TargetStatus::StaticTarget:
    {
      rainbow(10);
      return "StaticTarget";
    }
      
    case Seeed_HSP24::TargetStatus::BothTargets:
    {
      theaterChaseRainbow(200);
      return "BothTargets";
    }
      
    default:
      return "Unknown";
  }
}

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) {  // Repeat 10 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show(); // Update strip with new contents
      delay(wait);  // Pause for a moment
    }
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 3 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 3*65536. Adding 256 to firstPixelHue each time
  // means we'll make 3*65536/256 = 768 passes through this outer loop:
  for(long firstPixelHue = 0; firstPixelHue < 3*65536; firstPixelHue += 256) {
    for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the single-argument hue variant. The result
      // is passed through strip.gamma32() to provide 'truer' colors
      // before assigning to each pixel:
      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
    }
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {  // Repeat 30 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        // hue of pixel 'c' is offset by an amount to make one full
        // revolution of the color wheel (range 65536) along the length
        // of the strip (strip.numPixels() steps):
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}


功能展示

 
心得体会:
这是我第一次参加得捷follow me的活动,整体上来说收获很多,而且提供的板子非常适合大家快速上手,希望明年还会有类似活动,积极参加!

 

三、可编译下载的代码

完成任务源码下载地址https://download.eeworld.com.cn/detail/%E5%9D%9B/%E6%88%91=%E4%BD%AC/635603

点赞 关注
 
 

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

随便看看
查找数据手册?

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
快速回复 返回顶部 返回列表