- 2024-12-18
-
加入了学习《【Follow me第二季第1期】全部任务演示》,观看 全部任务演示2.0
-
加入了学习《【Follow me第二季第4期】任务汇报》,观看 【Follow me第二季第4期】任务汇报
-
上传了资料:
Arduino? Nano RP2040 Connect源码(第二季第4期)
- 2024-12-17
-
发表了主题帖:
【Follow me第二季第4期】任务汇总
本帖最后由 秋啊秋秋 于 2024-12-18 21:48 编辑
很幸运可以参加 DigiKey联合EEWorld发起的大型开发板体验活动Follow me第二季第4期,
经过任务的学习和思考,学生和我都对Arduino® Nano RP2040 Connect开发板有了以往不同的理解,这类趣味编程的板子也可以完成许多复杂的工作。所以更期待后续的活动出现更有意思的开发板活动。
项目视频演示
[localvideo]f6efa356df5ba26307b6319846318c23[/localvideo]
https://training.eeworld.com.cn/video/41996
物料展示
这是本次用到的所有物料,这次开发板集成了所有所需的传感器,也不需要额外购置,非常方便。另外只需要一条家里常用充电的MicroUSB用于连接开发板和电脑。
任务展示
任务一:搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!;
开发环境搭建:
Arduino来完成全部任务
1.下载和安装 Ardunio IDE ;
2.安装 Arduino NANO RP2040 开发板所需软件包;
3.连接开发板,选择对应型号;
开启第一步Blink三色LED并串口打印Hello DigiKey & EEWorld!:
由官方提供的原理图和引脚图可知,板载 RGB 三个 LED 为低电平点亮,并与与 WiFi 模块相连,RGB LED只需要写一个循环控制三个LED循环点亮,同时在循环里加入串口打印即可实现第一个任务;
流程图
代码
#include <WiFiNINA.h>
void setup(){
//设置串口打印后续Print
Serial.begin(9600);
//设置引脚输出模式
pinMode(LEDR,OUTPUT);
pinMode(LEDG,OUTPUT);
pinMode(LEDB,OUTPUT);
}
void loop(){
//高低电平控制开关红灯,灯光闪烁延迟300ms
digitalWrite(LEDR, LOW);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, HIGH);
delay(300);
//高低电平控制开关绿灯,灯光闪烁延迟300ms
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, LOW);
digitalWrite(LEDB, HIGH);
//高低电平控制开关蓝灯,灯光闪烁延迟300ms
delay(300);
digitalWrite(LEDR, HIGH);
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, LOW);
delay(300);
//串口打印
Serial.println("Hello DigiKey & EEWorld!");
delay(1000);
}
效果
任务二:学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据;
IMU ,即惯性测量单元(Inertial Measurement Unit),通常会提供加速度计和陀螺仪的数据。加速度计数据以重力加速度为单位,用于测量线性加速度;陀螺仪数据以角速度(通常是 )为单位,用于测量旋转速度。开发板自带的一个六轴 IMU 会提供三个轴向(x、y、z)的加速度和三个轴向的角速度数据。
根据 IMU 的通信协议和开发板的IMU库函数,编写代码来读取 IMU 数据。首先进行串口初始化并等待完成,接着尝试初始化 IMU,若成功则打印加速度计和陀螺仪的采样率,之后不断循环检查加速度计和陀螺仪数据是否可用,若可用则读取并串口输出数据,每次循环结束后延迟 800 毫秒,若 IMU 初始化失败则直接结束程序。
流程图
代码
可以使用以下代码片段来初始化和读取数据:
#include <Arduino_LSM6DSOX.h> // 引入适用于LSM6DSOX传感器的Arduino库,用于后续操作该传感器
float acc_x, acc_y, acc_z; // 用于存储加速度计在x、y、z轴方向上的测量值
float gyro_x, gyro_y, gyro_z; // 用于存储陀螺仪在x、y、z轴方向上的测量值
void setup() {
Serial.begin(9600); // 初始化串口通信,设置波特率为9600,用于后续与外部设备(如电脑)传输数据
while (!Serial); // 等待串口初始化完成,确保可以正常进行串口通信后再继续往下执行
if (!IMU.begin()) { // 初始化IMU
Serial.println("Failed to initialize IMU!"); // 通过串口输出初始化失败的提示信息
while (1); // 进入死循环,停止程序进一步执行,因为IMU初始化失败无法正常获取数据了
}
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(acc_x, acc_y, acc_z); // 读取加速度计在x、y、z轴方向上的数据,并分别存储到对应的变量中
Serial.println("Accelerometer data: ");
Serial.print(acc_x); // 输出加速度计x轴方向的数据
Serial.print('\t'); // 对齐数据
Serial.print(acc_y); // 输出加速度计y轴方向的数据
Serial.print('\t'); //
Serial.println(acc_z); // 输出加速度计z轴方向的数据,并换行,使每组数据占一行
Serial.println(); // 输出一个空行,进一步分隔不同时间采集的加速度计数据
}
if (IMU.gyroscopeAvailable()) { // 检查陀螺仪数据是否可用,即是否已经有新的有效数据可以读取了
IMU.readGyroscope(gyro_x, gyro_y, gyro_z); // 读取陀螺仪在x、y、z轴方向上的数据,并分别存储到对应的变量中
Serial.println("Gyroscope data: ");
Serial.print(gyro_x); // 输出陀螺仪x轴方向的数据
Serial.print('\t'); //
Serial.print(gyro_y); // 输出陀螺仪y轴方向的数据
Serial.print('\t'); //
Serial.println(gyro_z); // 输出陀螺仪z轴方向的数据,并换行,使每组数据占一行
Serial.println(); // 再输出一个空行,进一步分隔不同时间采集的陀螺仪数据
}
delay(800);
}
效果
任务三:学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形;
Nano RP2040 connect 配有 MP34DT06JTR 麦克风,可用于录制音频。
PDM 介绍
麦克风是将物理声音转换为数字数据的组件。
环境声音振动压缩空气,导致不同位置的空气密度分布存在差异,由此带来空气分子的波动传输,鼓膜线圈受到空气波动的影响而振动,线圈切割中心磁铁产生的磁感线,并形成感应电流,该感应电流经放大电路放大为模拟信号,传递给 MCU 模数转换器 ADC ,并转化为数字信号并通过串口输出。
麦克风通常用于移动终端、语音识别系统,甚至游戏和虚拟现实输入设备。
MP34DT06JTR 传感器是一种超小型麦克风,它使用 PDM(pulse density mdulation, 脉冲密度调制)来表示具有二进制信号的模拟信号。
先是进行串口初始化并等待完成,接着尝试初始化 PDM,若成功则配置数据接收回调,之后不断判断是否有音频样本数据可读,若可读则输出音频样本数据并清除计数,每次循环末尾添加延迟,若 PDM 初始化失败则执行相应的失败处理逻辑后再进入判断样本数据可读的环节。
流程图
代码
Arduino IDE 需安装 PDM 库
#include <PDM.h>
// 音频相关常量
const int AUDIO_CHANNELS = 1;
const int AUDIO_FREQUENCY = 24000;
// 音频样本缓冲区
short audioSampleBuffer[512];
// 读取的音频样本数
volatile int audioSamplesRead;
// 自定义的函数用于检查并处理PDM初始化失败情况
void handlePDMInitializationFailure() {
Serial.println("Failed to start PDM! Possible reasons: hardware connection issue or driver problem.");
// 这里可以添加一些简单的复位或重试逻辑,例如尝试复位PDM模块
// PDM.reset();
// if (!PDM.begin(AUDIO_CHANNELS, AUDIO_FREQUENCY)) {
// while (1);
// }
}
// 封装声道数据输出逻辑到函数,提高扩展性
void printAudioData(int numSamples, int numChannels) {
for (int i = 0; i < numSamples; i++) {
if (numChannels == 2) {
Serial.print("L:");
Serial.print(audioSampleBuffer[i]);
Serial.print(" R:");
i++;
}
Serial.println(audioSampleBuffer[i]);
}
}
// 数据接收回调函数,添加边界情况处理
void onPDMdata() {
int bytesAvailable = PDM.available();
// 检查可读字节数合法性
if (bytesAvailable < 0 || bytesAvailable > sizeof(audioSampleBuffer)) {
Serial.println("Invalid bytes available for PDM data!");
return;
}
PDM.read(audioSampleBuffer, bytesAvailable);
// 计算样本数量,考虑16-bit,2 bytes per sample
audioSamplesRead = bytesAvailable / 2;
}
void setup() {
Serial.begin(9600);
while (!Serial);
// 配置数据接收回调
PDM.onReceive(onPDMdata);
if (!PDM.begin(AUDIO_CHANNELS, AUDIO_FREQUENCY)) {
handlePDMInitializationFailure();
}
}
void loop() {
// 使用事件驱动方式,当有样本数据可读时才处理
if (audioSamplesRead > 0) {
printAudioData(audioSamplesRead, AUDIO_CHANNELS);
audioSamplesRead = 0;
}
delay(10);
}
效果
选做任务一:通过RGB LED不同颜色、亮度显示PDM麦克风收到的声音大小;
通过RGB LED不同颜色、亮度显示PDM麦克风收到的声音大小。
主要分为两部分,首先实现 RGB的颜色亮度可调,之后结合 PDM 传感器实现声控RGB。
主要思路:首先,在 PDM 数据接收回调函数 onPDMdata 中获取音频样本数据后,以样本缓冲区中数据绝对值的最大值作为声音大小的近似值进行计算。接着,运用线性映射(如 Arduino 的 map 函数)或按需采用非线性映射方式,把算出的声音大小映射到 0 - 255 范围,以此对应 RGB LED 的亮度值。同时,依据声音大小与 RGB 颜色的对应规则(如声音小对应偏冷色调,声音大对应偏暖色调),通过相应计算将声音大小转换为 RGB 三个通道各自 0 - 255 的颜色值。然后,在主循环 loop 中,当 audioSamplesRead > 0 时,先按上述步骤完成声音大小相关计算以及对 RGB LED 显示的设置,之后若有需求可继续处理音频样本数据输出,再清除已处理样本数据的计数,最后添加适当延迟来把控整体显示及数据处理的节奏。
流程图:
代码:
#include <PDM.h>
#include <WiFiNINA.h>
// 音频相关常量
const int AUDIO_CHANNELS = 1;
const int AUDIO_FREQUENCY = 24000;
// RGB LED引脚定义
// const int LEDR = 9;
// const int LEDG = 10;
// const int LEDB = 11;
// 音频样本缓冲区
short audioSampleBuffer[512];
// 读取的音频样本数
volatile int audioSamplesRead;
// 自定义的函数用于检查并处理PDM初始化失败情况
void handlePDMInitializationFailure() {
Serial.println("Failed to start PDM! Possible reasons: hardware connection issue or driver problem.");
// 这里可以添加一些简单的复位或重试逻辑,例如尝试复位PDM模块
// PDM.reset();
// if (!PDM.begin(AUDIO_CHANNELS, AUDIO_FREQUENCY)) {
// while (1);
// }
}
// 封装声道数据输出逻辑到函数,提高扩展性
void printAudioData(int numSamples, int numChannels) {
for (int i = 0; i < numSamples; i++) {
if (numChannels == 2) {
Serial.print("L:");
Serial.print(audioSampleBuffer[i]);
Serial.print(" R:");
i++;
}
Serial.println(audioSampleBuffer[i]);
}
}
// 数据接收回调函数,添加边界情况处理
void onPDMdata() {
int bytesAvailable = PDM.available();
// 检查可读字节数合法性
if (bytesAvailable < 0 || bytesAvailable > sizeof(audioSampleBuffer)) {
Serial.println("Invalid bytes available for PDM data!");
return;
}
PDM.read(audioSampleBuffer, bytesAvailable);
// 计算样本数量,考虑16-bit,2 bytes per sample
audioSamplesRead = bytesAvailable / 2;
}
void setup() {
Serial.begin(9600);
while (!Serial);
// 设置RGB LED引脚输出模式
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
// 配置数据接收回调
PDM.onReceive(onPDMdata);
if (!PDM.begin(AUDIO_CHANNELS, AUDIO_FREQUENCY)) {
handlePDMInitializationFailure();
}
}
// 用于映射声音大小到LED亮度的函数(可根据实际调整映射关系)
int mapSoundToBrightness(int soundValue) {
return map(soundValue, 0, 32767, 0, 255);
}
// 根据声音大小映射到RGB颜色值的函数(示例简单线性映射,可优化)
void mapSoundToColor(int soundSize, int &redValue, int &greenValue, int &blueValue) {
// 声音越大越偏红色,越小越偏绿色蓝色,这里简单示意,可按需求调整比例等
redValue = map(soundSize, 0, 32767, 0, 255);
greenValue = 255 - redValue;
blueValue = 0;
}
void loop() {
// 使用事件驱动方式,当有样本数据可读时才处理
if (audioSamplesRead > 0) {
// 计算声音大小(取样本缓冲区中绝对值最大值作为近似值)
int soundSize = 0;
for (int i = 0; i < audioSamplesRead; i++) {
if (abs(audioSampleBuffer[i]) > soundSize) {
soundSize = abs(audioSampleBuffer[i]);
}
}
// 根据声音大小映射到RGB LED的亮度
int brightness = mapSoundToBrightness(soundSize);
// 根据声音大小映射到RGB颜色值
int redValue, greenValue, blueValue;
mapSoundToColor(soundSize, redValue, greenValue, blueValue);
// 通过analogWrite设置RGB LED的亮度和颜色
analogWrite(LEDR, 255-redValue);
analogWrite(LEDG, 255-greenValue);
analogWrite(LEDB, 255-blueValue);
// (可选)处理音频样本数据,如输出到串口等
printAudioData(audioSamplesRead, AUDIO_CHANNELS);
// 清除读取计数
audioSamplesRead = 0;
}
delay(1000);
}
效果
项目源码
https://download.eeworld.com.cn/detail/%E7%A7%8B%E5%95%8A%E7%A7%8B%E7%A7%8B/635332
项目总结
在本次活动中,借助 Arduino Nano RP2040 Connect 开发板,顺利完成了四个任务,成功实现了对板载多种传感器模块的深度探索与测试,包括 IMU 和 PDM 模块。
基于 Arduino IDE 这一便捷的开发平台,进行代码的编辑与编译工作。而这个平台优势在于仅需安装适配的库文件,并在代码中合理调用这些函数,就能高效地完成功能开发,大幅缩减了开发周期,为跨专业背景的参与者以及编程初学者提供了极大的便利,有效降低了开发门槛。
同时Arduino Nano RP2040 Connect 开发板自身集成了丰富多样的传感器,板载资源丰富,且具有小巧精致、易于携带的特点,能够应用于多个领域。例如,通过对 IMU 模块的开发利用,我们能够实现运动状态检测以及姿态校正等功能应用;借助 PDM 模块,则可以实现声音检测和语音控制等。同时,开发板配备的无线 WiFi 和蓝牙模块,可以拥有物联网应用能力,实现万物互联,为嵌入式开发项目提供了丰富多样且极具创意的解决方案。
在此,我诚挚地感谢 DigiKey 和 EEWorld 对【Follow me 第二季第 4 期】活动的支持。衷心祝愿 Follow me 活动能够蒸蒸日上,越办越好,吸引越来越多的电子爱好者投身其中。也希望更多的朋友能够关注并积极参与 DigiKey 和 EEWorld 平台组织的各类活动,让我们在电子技术的海洋中共同学习、分享经验,一同成长进步,凭借科技的力量描绘出更加美好的未来蓝图。
- 2024-12-12
-
加入了学习《【Follow me第二季第4期】任务汇总》,观看 【Follow me第二季第4期】任务汇总
- 2024-11-28
-
加入了学习《直播回放: DigiKey FollowMe 第二季 第4期 Arduino Nano RP2040 Connect 任务讲解》,观看 Arduino Nano RP2040 Connect 任务讲解
-
加入了学习《Follow me第二季第4期 任务完成视频》,观看 【Follow me第二季第4期】最终视频