161|1

5

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

【Follow me第二季第4期】Arduino connect nano 物联网综合应用 [复制链接]

  本帖最后由 L物恩纶 于 2024-12-31 21:33 编辑

【Follow me第二季第4期】Arduino connect nano 物联网综合应用

 

    本项目基于Arduino connect nano的项目任务,涉及音频处理、传感器数据展示及机器学习应用等领域。包括利用PDM麦克风采集音频数据,计算RMS值控制LED亮灭。通过回调函数采集数据,主循环计算RMS并平滑处理。移动平均技术能减少噪声、提升稳定性,依据平滑后的RMS值分级控制LED。 利用板载的LSM6DS3传感器采集数据,在OLED屏实时显示加速度和角速度,还以柱状图展示加速度大小。PDM麦克风采集音频数据,经格式转换、进行FFT变换和幅值计算,最后在OLED屏以柱状图实时显示频谱。基于STMicroelectronics扩展板的LSM6DSOX传感器,初始化配置后,加载振动监测程序到MLC,实时监测并将振动状态分类。

 


任务一、点灯+麦克风测试

任务1使用 PDM(Pulse Density Modulation)麦克风 采集音频数据,并通过计算音频信号的 RMS(均方根)值 来控制板载 LED 的亮灭。实时采集音频信号,计算其 RMS 值,并对 RMS 值进行平滑处理,以减少噪声对 LED 控制的影响。

 

 

 1. 音频采集:

   当 PDM 麦克风有新的音频数据时,回调函数 onPDMdata 会被触发。该函数从 PDM 麦克风读取数据到缓冲区 sampleBuffer,并更新已读取的样本数量 samplesRead。

2. 音频处理:

   在主循环中,程序检查是否有新的音频数据。如果有,调用 calculateRMS 函数计算音频信号的 RMS 值。RMS 值反映了音频信号的强度,通过计算样本的平方和的平均值,再取平方根得到。为了减少噪声的影响,调用 calculateMovingAverage 函数对 RMS 值进行平滑处理。该函数使用移动平均算法,对最近的若干个 RMS 值进行平均,返回平滑后的 RMS 值。平滑处理的核心原理是通过对数据进行平均或加权平均,减少噪声和瞬时波动的影响,从而得到更加稳定和可靠的结果。

 (1)移动平均的基本原理

移动平均是一种常用的平滑技术,它通过对最近若干个数据点进行平均,来减少噪声和瞬时波动的影响。移动平均的基本思想是:

- 维护一个固定大小的窗口(即缓冲区),用于存储最近的数据点。

- 每次有新的数据点时,将其加入窗口,并移除最旧的数据点。

- 计算窗口中所有数据点的平均值,作为当前平滑后的值。

 (2)平滑处理的效果

- 减少噪声:通过移动平均,瞬时噪声对 RMS 值的影响被显著减小,因为噪声通常表现为短时波动,而移动平均会将其与多个数据点进行平均,从而平滑掉这些波动。

- 提高稳定性:平滑后的 RMS 值更加稳定,能够更好地反映音频信号的整体强度,减少因瞬时噪声导致的 LED 误触发。

- 响应速度与平滑效果的权衡:窗口大小决定了平滑效果和响应速度的平衡。窗口越大,平滑效果越好,但响应速度会变慢;窗口越小,响应速度越快,但平滑效果会减弱。

3. LED 控制:

   根据平滑后的 RMS 值,调用 controlLEDs 函数控制 LED 的亮灭状态。RMS 值越大,表示音频信号越强,LED 的亮灭状态会根据设定的阈值进行分级控制。例如,RMS 值较小时点亮红色 LED,中等时点亮绿色 LED,较大时点亮蓝色 LED,极大时点亮所有 LED。

 

// 初始化 RMS 缓冲区
void initRMSBuffer()
{
  for (int i = 0; i < windowSize; i++)
  {
    rmsBuffer[i] = 0.0;
  }
}

// 计算移动平均
float calculateMovingAverage(float newRMS)
{
  rmsBuffer[rmsIndex] = newRMS;           // 将新 RMS 值存入缓冲区
  rmsIndex = (rmsIndex + 1) % windowSize; // 更新索引

  float sum = 0.0;
  for (int i = 0; i < windowSize; i++)
  {
    sum += rmsBuffer[i]; // 计算缓冲区中所有 RMS 值的总和
  }
  return sum / windowSize; // 返回移动平均值
}

void onPDMdata()
{
  int bytesAvailable = PDM.available();
  PDM.read(sampleBuffer, bytesAvailable);
  samplesRead = bytesAvailable / 2;
}

float calculateRMS(short *buffer, int length)
{
  long sum = 0;
  for (int i = 0; i < length; i++)
  {
    sum += (long)buffer[i] * buffer[i];
  }
  float mean = (float)sum / length;
  return sqrt(mean);
}


void loop()
{
  if (samplesRead)
  {
    float rms = calculateRMS(sampleBuffer, samplesRead);
    float smoothedRMS = calculateMovingAverage(rms); // 计算移动平均
    controlLEDs(smoothedRMS);                        // 使用平滑后的 RMS 值控制 LED
    Serial.println(smoothedRMS);
    samplesRead = 0;
  }
  static unsigned long lastTime = 0;
  if (millis() - lastTime >= 1000)
  {
    lastTime = millis();
    Serial.println("Hello DigiKey & EEWorld!");
  }
}

 

 

 


 任务二、加速度传感器数据展示

 

这个项目是一个基于 Arduino 平台的 IMU(惯性测量单元) 数据采集与可视化系统。项目使用 LSM6DS3 传感器(包含加速度计和陀螺仪)来采集设备的加速度和角速度数据,并通过 OLED 显示屏 实时显示这些数据。

将采集到的加速度和角速度数据通过 OLED 显示屏实时显示,并以柱状图的形式直观展示加速度的大小。

 

   - 柱状图绘制:通过 drawBarGraph 函数将加速度数据映射到 OLED 屏幕的高度范围,并以柱状图的形式显示。柱状图的高度与加速度的大小成正比,直观反映了设备在各个方向上的加速度变化。

 

void loop()
{
  // 获取加速度数据
  float accelX = 0.0; // 读取 X 轴加速度
  float accelY = 0.0;
  float accelZ = 0.0;
   
     if (IMU.accelerationAvailable())
  {
    IMU.readAcceleration(accelX, accelY, accelZ);
    Serial.print(accelX * CONVERT_G_TO_MS2,4);
    Serial.print('\t');  Serial.print(accelY * CONVERT_G_TO_MS2,4);
    Serial.print('\t');  Serial.println(accelZ * CONVERT_G_TO_MS2,4);
  }

  float x, y, z;

  if (IMU.gyroscopeAvailable())
  {
    IMU.readGyroscope(x, y, z);  Serial.print(x, 2);  Serial.print('\t');  Serial.print(y, 2);  
    Serial.print('\t'); Serial.println(z, 2);
  }
  // 显示加速度数据
  display.clearDisplay();

  // 在 OLED 显示实时加速度数据
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("Accel X: ");
  display.println(accelX, 2);
  display.print("Accel Y: ");
  display.println(accelY, 2);
  display.print("Accel Z: ");
  display.println(accelZ, 2);

  // 绘制柱状图
  drawBarGraph(accelX, accelY, accelZ);

  display.display();

  delay(100); // 延迟100毫秒更新
}

void drawBarGraph(float x, float y, float z)
{
  // 映射加速度值到 OLED 高度范围
  int barHeightX = map(abs(x * 50), 0, 100, 0, SCREEN_HEIGHT); // 放大倍数调整灵敏度
  int barHeightY = map(abs(y * 50), 0, 100, 0, SCREEN_HEIGHT);
  int barHeightZ = map(abs(z * 50), 0, 100, 0, SCREEN_HEIGHT);

  // 限制范围,避免超出屏幕
  barHeightX = constrain(barHeightX, 0, SCREEN_HEIGHT);
  barHeightY = constrain(barHeightY, 0, SCREEN_HEIGHT);
  barHeightZ = constrain(barHeightZ, 0, SCREEN_HEIGHT);

  // 绘制 X 轴柱状图
  display.fillRect(10, SCREEN_HEIGHT - barHeightX, 20, barHeightX, SSD1306_WHITE);
  // 绘制 Y 轴柱状图
  display.fillRect(50, SCREEN_HEIGHT - barHeightY, 20, barHeightY, SSD1306_WHITE);
  // 绘制 Z 轴柱状图
  display.fillRect(90, SCREEN_HEIGHT - barHeightZ, 20, barHeightZ, SSD1306_WHITE);
}

 

 


 任务三、声音FFT频谱分析与显示

本任务是一个基于 Arduino 平台的音频频谱分析系统,使用 PDM(Pulse Density Modulation)麦克风 采集音频数据,并通过 FFT(快速傅里叶变换) 对音频信号进行频谱分析。

 

 

(1)音频数据采集:通过 PDM 麦克风采集音频数据,并将其存储在缓冲区中。

   - PDM 数据读取:在主循环中,检查 PDM 麦克风是否有新的音频数据可用。如果有,读取音频数据到缓冲区 pdmBuffer 中。

   - 数据转换:将 PDM 数据转换为 FFT 输入格式,存储在 vReal 数组中,并将虚数部分 vImag 数组置零。

(2)FFT 频谱分析:对采集到的音频数据进行 FFT 变换,计算音频信号的频谱。

   - 加窗处理:对音频数据进行加窗处理(使用汉明窗),以减少频谱泄漏。

   - FFT 计算:对加窗后的音频数据进行 FFT 变换,计算频谱。

   - 幅值计算:将 FFT 结果转换为幅值,存储在 vReal 数组中。

3. 频谱可视化:将计算得到的频谱通过 OLED 显示屏 实时显示,以柱状图的形式展示不同频率成分的幅值。

   - OLED 显示:在 OLED 显示屏上绘制频谱图,将不同频率成分的幅值映射为柱状图的高度,并显示在屏幕上。

   - 刷新显示:每 10 毫秒更新一次 OLED 显示屏,确保频谱图的实时性。

void loop() {
  // 读取麦克风数据
  int amplesRead = PDM.available();
  if (amplesRead > 0) {
    PDM.read(pdmBuffer, SAMPLES);

    // 将 PDM 数据转换为 FFT 输入
    for (int i = 0; i < SAMPLES; i++) {
      vReal[i] = pdmBuffer[i] ; // 转换为浮点数
      vImag[i] = 0.0; // 虚数部分置零
    }

    // 执行 FFT
    FFT.windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD); // 汉明窗
    FFT.compute(FFT_FORWARD); // 计算 FFT
    FFT.complexToMagnitude(); // 计算幅值

    // 映射到 OLED 显示
    displayFFTOnOLED();
    // showSignal2();

    delay(10); // 控制刷新率
  }
}

// 绘制频谱图
void displayFFTOnOLED() {
  display.clearDisplay();

  // 显示频谱
  for (int i = 0; i < SAMPLES / 2; i++) { // 只显示正频部分
    // 映射幅值到 OLED 高度
    int barHeight = map(vReal[i], 0, 10000, 0, SCREEN_HEIGHT*3/4);
    // barHeight = constrain(barHeight, 0, SCREEN_HEIGHT); // 限制高度范围
    display.drawLine(i, SCREEN_HEIGHT, i, SCREEN_HEIGHT - barHeight, SSD1306_WHITE);
  }

  display.display();
}

void showSignal2() {
    int y;
     display.clearDisplay();
    for (int n = 0; n < 128; n++) {
        // y = vReal[n]*10;
        y = map(vReal[n],-2000, 2000, 5, 60);
      //  display.drawPixel(n, oldy[n], BLACK);
        display.drawPixel(n, y, WHITE);
        oldy[n] = y;
    }
    display.display();
}

 


任务四、震动强度机器学习

    本任务基于 STMicroelectronics X-NUCLEO-IKS01A3 扩展板的 LSM6DSOX 传感器的机器学习核心(MLC)应用示例。LSM6DSOX 传感器内置了一个机器学习核心(MLC),能够在不依赖外部处理器的情况下,执行简单的机器学习算法。MLC 可以用于实时监测传感器数据,并根据预定义的规则进行分类或决策。

 

 

1. 传感器初始化与配置:初始化 LSM6DSOX 传感器,并配置其加速度计和陀螺仪。

2. 机器学习核心(MLC)应用:将预定义的机器学习程序加载到 LSM6DSOX 的 MLC 中,用于振动监测。

   项目中加载了一个预定义的机器学习程序(lsm6dsox_vibration_monitoring),该程序专门用于振动监测。程序通过分析加速度计和陀螺仪的数据,判断设备的振动状态。   

- 程序验证:逐行加载程序,并检查是否加载成功。如果加载失败,程序将停止运行,并通过 LED 闪烁提示错误。

-通过 MLC 实时监测设备的振动状态,并将振动状态分类为“无振动”、“低振动”和“高振动”。

void loop() {
  if (mems_event) {
    mems_event=0;
    LSM6DSOX_MLC_Status_t status;
    AccGyr.Get_MLC_Status(&status);
    if (status.is_mlc1) {
      uint8_t mlc_out[8];
      AccGyr.Get_MLC_Output(mlc_out);
      printMLCStatus(mlc_out[0]);
    }
  }
}

void INT1Event_cb() {
  mems_event = 1;
}

void printMLCStatus(uint8_t status) {
  switch(status) {
    case 0:
      SerialPort.println("no vibration");
      display.clearDisplay();  
      display.setCursor(10,25);
      display.print("no vibration");
      display.display();
      break;
    case 1:
      SerialPort.println("low vibration");
      display.clearDisplay();  
      display.setCursor(10,25);
      display.print("low vibration");
      display.display();
      break;
    case 2:
      SerialPort.println("high vibration");
      display.clearDisplay();  
      display.setCursor(10,25);
      display.print("high vibration");
      display.display();
      break;

  }	  
}

 

 

总结:

  这次活动围绕Arduino connect nano展开,在音频处理、传感器应用及机器学习等方面各有探索,展现了多样化的功能与技术应用: 音频处理与控制:“点灯+麦克风测试”项目利用PDM麦克风采集音频,通过计算RMS值控制LED;实现音频采集、FFT频谱分析与可视化展示,提供音频频谱信息。借助LSM6DS3传感器采集加速度和角速度数据,并以直观的柱状图在OLED屏呈现;运用LSM6DSOX传感器的MLC进行振动监测与分类,体现传感器在数据采集和分析上的不同应用方式。 各项目结合Arduino等平台,综合运用多种技术实现特定功能,为相关领域的技术应用和开发提供了实践范例,展示硬件技术在不同场景下的可行性和创新性。

 


 

nano_connect_allen.zip

4.6 MB, 下载次数: 0

最新回复

有人能破解这个串口显示图显数量吗?     详情 回复 发表于 6 天前
点赞 关注(1)
 
 

回复
举报

6372

帖子

9

TA的资源

版主

沙发
 

有人能破解这个串口显示图显数量吗?  

个人签名

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

 
 
 

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

随便看看
查找数据手册?

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