本帖最后由 慕容雪花 于 2024-12-17 12:42 编辑
往期分享:
【Follow me第二季第4期】- 任务准备:底板制作与开发环境搭建 https://bbs.eeworld.com.cn/thread-1302013-1-1.html
视频链接: https://training.eeworld.com.cn/video/41983
代码:
VideoProjectN
任务一:
任务目标:搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!
开发板上除了有右上角的单色BUILTIN小灯,还有一组RGB,不过是连接到NINA模块引脚上。
在Arduino开发环境下,首先要想使用NINA WiFi模组,需要安装如下库:
之后需要包含如下的头文件:
#include <WiFiNINA.h>
任务程序流程图:
任务核心代码:
void setup(void) {
Serial.begin(9600);
Serial.print(F("Hello! ST77xx TFT Test"));
//Init LED rgb PINS.
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
digitalWrite(LEDR, HIGH); //RED
digitalWrite(LEDG, HIGH); //GREEN
digitalWrite(LEDB, HIGH); //BLUE
tft.init(135, 240); // Init ST7789 240x135
Serial.println(F("Initialized"));
uint16_t time = millis();
tft.fillScreen(ST77XX_BLACK);
time = millis() - time;
Serial.println(time, DEC);
delay(500);
tft.fillScreen(ST77XX_BLACK);
}
void loop() {
Serial.println("Hello DigiKey & EEWorld!");
testdrawtext("EEWORLD", ST77XX_RED);
Serial.println("red led up");
digitalWrite(LEDR, HIGH); //RED
digitalWrite(LEDG, LOW); //GREEN
digitalWrite(LEDB, LOW); //BLUE
delay(500);
testdrawtext("EEWORLD", ST77XX_GREEN);
Serial.println("green led up");
digitalWrite(LEDR, LOW); //RED
digitalWrite(LEDG, HIGH);
digitalWrite(LEDB, LOW); //BLUE
delay(500);
testdrawtext("EEWORLD", ST77XX_BLUE);
Serial.println("blue led up");
digitalWrite(LEDR, LOW); //RED
digitalWrite(LEDG, LOW); //GREEN
digitalWrite(LEDB, HIGH);
delay(500);
}
任务实现效果:三色LED依次闪烁,屏幕有相应颜色提示,串口有数据输出。
任务二、学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据
开发板上安装了一颗6轴惯性测量单元传感器,其位置如下:
LSM6DSOXTR 是一款 6 轴 IMU(惯性测量单元)系统级封装,具有 3 轴数字加速度计和 3 轴数字陀螺仪,在高性能模式下以 0.55 mA 的速度提高性能,并支持始终开启的低功耗功能,为消费者提供最佳运动体验。
LSM6DSOXTR支持主要的操作系统要求,提供 9 KB 的真实、虚拟和批处理传感器,用于动态数据批处理。意法半导体的 MEMS 传感器模块系列利用了已经用于生产微机械加速度计和陀螺仪的稳健而成熟的制造工艺。各种传感元件采用专门的微加工工艺制造,而 IC 接口则使用 CMOS 技术开发,允许设计专用电路,该电路经过调整以更好地匹配传感元件的特性。
LSM6DSOXTR的满量程加速度范围为 ±2/±4/±8/±16 g,角速率范围为 ±125/±250/±500/±1000/±2000 dps。
3轴加速度计是用来测量加速度的机电装置,可以是静态的重力加速度或者运动物体的时刻变化的加速度等。利用加速度传感器能够计算出板子倾斜的方向或者角度。
3轴数字陀螺仪:
陀螺仪传感器是一种能够测量和保持物体的方向和角速度的装置。陀螺仪比加速度计更先进,因为它们可以测量物体的倾斜和横向方向,而加速度计只能测量物体的直线运动。
陀螺仪图示。
陀螺仪传感器也被称为“角速率传感器”或“角速度传感器”。角速度是单位时间内物体旋转角度的变化量,单位是每秒的度数。
在Arduino开发环境中,需要使用到“Arduino_LSM6DS3”来驱动该传感器。程序流程图:
获取6轴数据的代码如下:
#include <Arduino_LSM6DSOX.h>
float Ax, Ay, Az;
float Gx, Gy, Gz;
void setup() {
Serial.begin(9600);
while(!Serial);
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);
}
烧录验证:
串口有三轴加速度与角速度传感器数据。
数据的波形也可以方便的通过串口绘图工具展示:
为了增加任务二的可玩性,尝试了使用Eigen库在TFT屏幕上绘制了变化的立方体,立方体的旋转角度是根据MadgwickAHRS算法计算出来的实时变化的数据。
pitch是围绕Y轴旋转,也叫做俯仰角。当X轴的正半轴位于过坐标原点的水平面之上(抬头)时,俯仰角为正,否则为负,如下图所示:
yaw是围绕Z轴旋转,也叫偏航角。即机头右偏航为正,反之为负。如下图所示:
roll是围绕X轴旋转,也叫翻滚角。机体向右滚为正,反之为负。如下图所示:
在上位机方面,采用了VOFA+这个工具里面有个立体方块,可以配置开发板的旋转来一起high起来。
更新后软件流程图如下所示:
其中,立方体是通过矩阵的方式描述,下面是8个顶点与12条边。
pt << -1, -1, 1, 1, //A 0
1, -1, 1, 1, //B 1
1, 1, 1, 1, //c 2
-1, 1, 1, 1, //d 3
-1, -1, -1, 1, //e 4
1, -1, -1, 1, //f 5
1, 1, -1, 1, //g 6
-1, 1, -1, 1; //h 7
tp << 0, 1, //A-B
1, 2, //b-c
2, 3, //c-d
3, 0, //d-a
0, 4, //a-e
1, 5, //b-f
2, 6, //c-g
3, 7, //d-h
4, 5, //e-f
5, 6, //f-g
6, 7, //g-h
7, 4; //h-e
在TFT屏幕上绘制立方体:
void drawTube(const MatrixXd& m, uint16_t color) {
int nr = tp.rows(); //行数
for (int i = 0; i < nr; i++) {
auto start = m.row(tp(i, 0));
auto end = m.row(tp(i, 1));
tft.drawLine(start(0), start(1), end(0), end(1), color);
}
}
根据6轴数据计算开发板旋转角度的时候,本次上位机是VOFA+,要注意其专有点协议格式。
// Prints rotation angles (roll, pitch, and yaw) calculated using the
// Madgwick algorithm.
// Note: Yaw is relative, not absolute, based on initial starting position.
// Calculating a true yaw (heading) angle requires an additional data source,
// such as a magnometer.
void printRotationAngles() {
char buffer[5]; // string buffer for use with dtostrf() function
if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()
&& IMU.readAcceleration(ax, ay, az) && IMU.readGyroscope(gx, gy, gz)) {
filter.updateIMU(gx, gy, gz, ax, ay, az); // update roll, pitch, and yaw values
// Print rotation angles
float data[3];
data[0] = filter.getRoll();
data[1] = filter.getPitch();
data[2] = filter.getYaw();
Serial.write((char *)data, sizeof(float) * 3);
// 发送帧尾
char tail[4] = {0x00, 0x00, 0x80, 0x7f};
Serial.write(tail, 4);
}
}
如果上位机选择的是VOFA+,注意使用JustFloat协议要遵循一定的格式。
然后再左侧“控件”栏中选择立方体,然后拖拽到右侧窗口,然后分别指定每个通道的数据来源。
任务三、学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形
开发板上有一个ST公司的PDM麦克风:
PDM是一种调制形式,用于表示数字域中的模拟信号。它是1位数字采样的高频数据流。在PDM信号中,脉冲的相对密度对应于模拟信号的幅度。大量的1s对应于高(正)幅度值,而大量的0s对应于低(负)幅度值,交替的1s和0s对应于幅度值0。
电路原理图如下:
相关参数如下:
- Signal-to-noise ratio: 64dB
- Sensitivity: -26dBFS ±3dB
- Temperature range: -40 to 85°C
程序流程图:
核心代码:
#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);
Serial.print(" R:");
i++;
}
Serial.println(sampleBuffer);
if (sampleBuffer > 10000 || sampleBuffer <= -10000) {
LED_SWITCH = !LED_SWITCH;
if (LED_SWITCH) {
Serial.println();
digitalWrite(LEDB, HIGH);
Serial.println("ON!");
Serial.println();
delay(1000);
}
else {
Serial.println();
digitalWrite(LEDB, LOW);
Serial.println("OFF!");
Serial.println();
delay(1000);
}
}
}
// 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;
}
安静状态下,打一个响指,可以通过串口工具捕捉到如下波形:
对着开发板说几句话,可以捕捉到如下波形:
总结:
非常感谢本次活动!让我体验了6轴传感器,体验了PDM与arduino nano rp2040。后续会继续体验多核与rtos的用法,改善项目效果。
|