256|5

113

帖子

4

TA的资源

一粒金砂(高级)

楼主
 

【Follow me第二季第4期】Arduino Nano RP2040学习总结+FFT音频灯 [复制链接]

  本帖最后由 eew_cT3H5d 于 2024-12-31 22:54 编辑

活动链接:https://www.eeworld.com.cn/huodong/digikey_follow_me_2024_04/

先放最后项目:FFT音频灯,然后在讲述【Follow me第二季第4期】Arduino Nano RP2040学习总结

扩展任务:FFT音频灯项目

项目效果演示:

FFT音频LED灯

效果展示:

程序代码:

20241222213943138.zip (1.74 KB, 下载次数: 2)

程序流程图:

 

傅里叶FFT变换原理

 

硬件组成连接框图:

   

参考来源:

链接已隐藏,如需查看请登录或者注册

 

下面进行讲解【Follow me第二季第4期】学习过程

准备工作:

1)开发板介绍

 

2)安装开发板支持包

 

3)安装开发板WIFI支持包

 

4)板载负载驱动引脚

5)开发板数字I/O引脚

 

6)开发板相关通讯引脚

 

 

必做任务一:搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!

程序代码:备注digitalWrite(!digitalRead())不能直接使用

#include <WiFiNINA.h>

void setup() {

  Serial.begin(115200);

  pinMode(LEDR,OUTPUT);
  pinMode(LEDG,OUTPUT);
  pinMode(LEDB, OUTPUT);
 }

void loop() {


    digitalWrite(LEDR, LOW);//0
    digitalWrite(LEDG, LOW);//0
    digitalWrite(LEDB, LOW);//0
    Serial.println("Hello DigiKey & EEWorld!");
    delay(200);
    digitalWrite(LEDR, HIGH);//1
    digitalWrite(LEDG, HIGH);//1
    digitalWrite(LEDB, HIGH);//1
    Serial.println("Hello DigiKey & EEWorld!");
    delay(200);
}

点亮三色LED效果(红、绿、蓝构成白色):

串口接收数据:

 

程序流程图:

 

扩展:点亮ws2812数字全彩LED

下载库:

 

打开案例库:

 

选择GPIO5作为驱动引脚

 

程序代码:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define LED_PIN    5

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 64

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}

void loop() {
  // Fill along the length of the strip in various colors...
  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, half brightness
  theaterChase(strip.Color(127,   0,   0), 50); // Red, half brightness
  theaterChase(strip.Color(  0,   0, 127), 50); // Blue, half brightness
  rainbow(10);             // Flowing rainbow cycle along the whole strip
  theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}

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
  }
}

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) {

  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {

    strip.rainbow(firstPixelHue);

    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)
      for(int c=b; c<strip.numPixels(); c += 3) {
        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
    }
  }
}

程序流程图:

 

驱动ws2812模块效果:

 

必做任务二:学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据;

下载库LSM6DSOX

 

程序代码:

#include <Arduino_LSM6DSOX.h>

void setup() {
Serial.begin(115200); // 初始化串口
while (!Serial); // 等待串口连接

if (!IMU.begin()) {
Serial.println("无法初始化 LSM6DSOX IMU 传感器!");
while (1);
}
Serial.println("LSM6DSOX IMU 传感器已初始化");
}

void loop() {
float ax, ay, az; // 加速度
float gx, gy, gz; // 角速度

// 读取加速度值
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(ax, ay, az);
Serial.print("加速度 (m/s^2): X=");
Serial.print(ax);
Serial.print(" Y=");
Serial.print(ay);
Serial.print(" Z=");
Serial.println(az);
}

// 读取角速度值
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(gx, gy, gz);
Serial.print("陀螺仪 (rad/s): X=");
Serial.print(gx);
Serial.print(" Y=");
Serial.print(gy);
Serial.print(" Z=");
Serial.println(gz);
}

delay(100); // 延迟 500 毫秒
}

程序流程图:

 

编译下载程序:

 

 

必做任务三:学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形。

打开案例库:

 

编译程序:

 

程序流程图:

 

程序代码:

#include <PDM.h>

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

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

// 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(9600);
  while (!Serial);

  // Configure the data receive callback
  PDM.onReceive(onPDMdata);

  // Optionally set the gain
  // Defaults to 20 on the BLE Sense and 24 on the Portenta Vision Shield
  // PDM.setGain(30);

  // Initialize PDM with:
  // - one channel (mono mode)
  // - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense
  // - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shield
  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;
  }
}

/**
 * Callback function to process the data from the PDM microphone.
 * NOTE: This callback is executed as part of an ISR.
 * Therefore using `Serial` to print messages inside this function isn't supported.
 * */
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;
}

串口打印数据:

 

 

选做任务一(非必做):通过RGB LED不同颜色、亮度显示PDM麦克风收到的声音大小;

参考内容:https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-microphone-basics/

演示效果:不同敲击显示不同颜色

程序代码:
#include <WiFiNINA.h>
#include <PDM.h>

bool LED_SWITCH = false;

// 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(9600);
  pinMode(LEDB, OUTPUT);
  while (!Serial);
  // Configure the data receive callback
  PDM.onReceive(onPDMdata);

  // Optionally set the gain
  // Defaults to 20 on the BLE Sense and -10 on the Portenta Vision Shields
  // PDM.setGain(30);

  // Initialize PDM with:
  // - one channel (mono mode)
  // - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense
  // - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shields
  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]);

      if (sampleBuffer[i] > 10000 || sampleBuffer[i] <= -10000) {
        LED_SWITCH = !LED_SWITCH;
        if (LED_SWITCH) {
          Serial.println();
          digitalWrite(LEDR, HIGH);
          Serial.println("ON!");
          Serial.println();
          delay(100);
        }
        else {
          Serial.println();
          digitalWrite(LEDR, LOW);
          Serial.println("OFF!");
          Serial.println();
          delay(100);
        }
      }


      if (sampleBuffer[i] > 8000 || sampleBuffer[i] <= -8000) {
        LED_SWITCH = !LED_SWITCH;
        if (LED_SWITCH) {
          Serial.println();
          digitalWrite(LEDG, HIGH);
          Serial.println("ON!");
          Serial.println();
          delay(100);
        }
        else {
          Serial.println();
          digitalWrite(LEDG, LOW);
          Serial.println("OFF!");
          Serial.println();
          delay(100);
        }
      }

      if (sampleBuffer[i] > 5000 || sampleBuffer[i] <= -5000) {
        LED_SWITCH = !LED_SWITCH;
        if (LED_SWITCH) {
          Serial.println();
          digitalWrite(LEDB, HIGH);
          Serial.println("ON!");
          Serial.println();
          delay(100);
        }
        else {
          Serial.println();
          digitalWrite(LEDB, LOW);
          Serial.println("OFF!");
          Serial.println();
          delay(100);
        }
      }
      
    }

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

/**
   Callback function to process the data from the PDM microphone.
   NOTE: This callback is executed as part of an ISR.
   Therefore using `Serial` to print messages inside this function isn't supported.
 * */
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;
}

程序流程图:

 

 

 

一 、3-5分钟短视频

视频链接:https://training.eeworld.com.cn/course/68912/learn?preview=1#lesson/42241

Follow me第二季第4期

 

二、任务实现详情

本帖内容

项目总结:通过这次Follow me第二季第4期活动,熟悉Arduino编程环境搭建及开发板的使用,通过移植FFT音频LED加深对Arduino Nano RP2040了解。

 

三、可编译下载的代码

地址:https://download.eeworld.com.cn/detail/eew_cT3H5d/635478

 

 

最新回复

arduino对ws2812灯带的支持还是挺全面的     详情 回复 发表于 4 天前
点赞 关注(1)
 
 

回复
举报

6372

帖子

10

TA的资源

版主

沙发
 

效果非常不错    

点评

买的2020封装的ws2812矩阵效果还是挺好的  详情 回复 发表于 5 天前
个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

回复

227

帖子

3

TA的资源

一粒金砂(高级)

板凳
 

FFT音频灯效果很不错,有时间也玩一下

点评

对快速傅里叶分解也比较有利理解含义  详情 回复 发表于 5 天前
 
 
 

回复

113

帖子

4

TA的资源

一粒金砂(高级)

4
 

买的2020封装的ws2812矩阵效果还是挺好的

点评

arduino对ws2812灯带的支持还是挺全面的    详情 回复 发表于 4 天前
 
 
 

回复

113

帖子

4

TA的资源

一粒金砂(高级)

5
 
Maker_kun 发表于 2025-1-1 10:59 FFT音频灯效果很不错,有时间也玩一下

对快速傅里叶分解也比较有利理解含义

 
 
 

回复

6372

帖子

10

TA的资源

版主

6
 
eew_cT3H5d 发表于 2025-1-1 21:10 买的2020封装的ws2812矩阵效果还是挺好的

arduino对ws2812灯带的支持还是挺全面的  

个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
数字电视!不爱你爱谁?

我们知道,专利法有一个区域性,如果别人没有到我们国家来申请专利,那怕我们的产品使用了他人的技术,这也不算侵权。虽然,中国 ...

库存免费送!

送走了妩媚的春天,迎来了热情奔放的夏天!夏天的阳光,是炎热的,它像一个热情奔放的女郎,向人们张开了双臂,娇人的阳光像火一样地 ...

转:我为什么离开ARM加入MIPS? 

本文作者系,原ARM技术行销经理,费浙平。 几星期前刚递交辞职信的时候,很多朋友都表示了理解,他们都知道,经过近8年的努力 ...

读取LPC ARM芯片唯一序列号的方法

对于ARM芯片基本都有唯一序列号,这产权保护,产品加密,产品序列号设置带来了极大的方便。但是不同厂家,甚至同一厂家不同系列 ...

TI C2000 LaunchPad原理图解读!

C2000_Launchpad实验板主要由MCU最小系统和DSP仿真器两部分电路组成,如图1所示,绿色线条以下部分是MCU最小系统, 绿色线条以上 ...

【懒人自理鱼缸控制系统】KEIL 环境RTE方式下控制GPIO管脚

【懒人自理鱼缸控制系统】KEIL 环境RTE方式下APP控制管脚 一、开发环境说明 1、IDE:安装好SDK的KEIL及PACK 2、项目工程 ...

micropython最新更新中优化了neopixel驱动

最近的更新中,减少了neopixel的代码大小,优化fill()速度。 drivers/neopixel: Reduce code size of driver. drivers/n ...

PLC 和 运动控制器 的高速IO设计

有没有坛友在 PLC 和 运动控制器 上设计高速IO来采集AB相差分脉冲 (采集手摇轮脉冲发生器的脉冲信号,判断手摇轮的方向和速度) ...

10月17日 |泰克 “芯”朋友见面大会-长沙站

850539 会议简介: 本次研讨会,我们将从测试角度看半导体的整条产业链,从材料器件的测试分析、功率半导体器件评估 ...

时序图上上下都有横线是什么意思呢?(SPI菊链)

859571 芯片数据手册上,SPI通信时序图上面两边都有这样的横线是什么意思呢?(上面的是不使用菊链的时序图) (使用AD57 ...

关闭
站长推荐上一条 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
快速回复 返回顶部 返回列表