回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【雕爷学编程】Arduino动手做(93)--- 0.96寸OLED液晶屏模块9 中等

头像 驴友花雕 2023.07.27 38 1

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验九十三:0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块

 

25.jpg

 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
 实验九十三: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
 项目三十一:使用 VL53L0X 进行范围测量并在 SSD1306 OLED 上显示(mm)

 实验开源代码
 

代码
/*
  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验九十七: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
  项目三十一:使用 VL53L0X 进行范围测量并在 SSD1306 OLED 上显示(mm)
  模块接线:SSD1306 OLED模块相同
  VL53L0X  Arduino
  VCC        5V
  GND        GND
  SCL        A5
  SDA        A4
*/

#include <Wire.h>
#include "Adafruit_VL53L0X.h"
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display = Adafruit_SSD1306();

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

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

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
  // init done
  display.display();
  delay(1000);


  Wire.begin();

  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while (1);
  }

  // text display big!
  display.setTextSize(4);
  display.setTextColor(WHITE);
}

void loop() {
  VL53L0X_RangingMeasurementData_t measure;

  lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!

  if (measure.RangeStatus != 4) {  // phase failures have incorrect data
    display.clearDisplay();
    display.setCursor(0, 0);
    display.print(measure.RangeMilliMeter);
    display.print("mm");
    display.display();
    Serial.println();
    delay(50);
  } else {
    display.display();
    display.clearDisplay();
    return;
  }
}

Arduino实验场景图

 

123.jpg

123556r99x69hv79fyfhuc.gif

MAX9814 麦克风放大器

MAX9814 是一款麦克风放大器,具有自动增益控制 (AGC) 和低噪声麦克风偏置功能,并且有几个选项可以通过突破进行配置。

MAX9814 模块具有三种放大器设置(40dB、50dB、60dB)。默认值为 60dB,但可以通过将增益引脚跳接到 VCC 或接地来设置为 40dB 或 50dB。

内部低噪声麦克风偏置 1.25V,2Vpp。放大器的输出在 1.25V 直流偏置时最大约为 2Vpp,因此它可以轻松用于任何高达 3.3V 输入的模数转换器。

Attack/Release 比率也可以修改,从默认的 1:4000 到 1:2000 或 1:500。

要直接连接到线路输入,您需要一个隔直电容/耦合电容来隔断直流分量。您可以使用 1uF 以上的串联阻塞电容器,这取决于您的系统,如果有疑问,请尝试从 33 uF 到 100uF。耦合电路允许交流信号从一个部分流到另一个部分,同时阻止直流分量。在音频电路中,这样做是为了防止直流分量使音频输出失真。耦合电容器的有效性取决于一系列广泛的频率相关参数,包括插入损耗、等效串联电阻和串联谐振频率。

电源:2.7V 至 5.5V

 

124 (1).jpg
124 (2).jpg

  【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
 实验九十三: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
 项目三十二:使用FFT库的迷你音乐频谱仪(声谱可视化器)
 实验接线方法: max9814接A0
 oled模块    Ardunio Uno
 GND---------GND接地线
 VCC---------5V 接电源
 SDA---------A4
 SCL ------- A5

 实验开源代码
 

代码
/*
  【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
  实验九十七: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块
  项目三十二:使用FFT库的迷你音乐频谱仪(声谱可视化器)
  实验接线方法: max9814接A0
  oled模块    Ardunio Uno
  GND---------GND接地线
  VCC---------5V 接电源
  SDA---------A4
  SCL ------- A5
*/

#include "arduinoFFT.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SAMPLES 64 // power of 2
#define SAMPLING_FREQ 8000 // 12 kHz Fmax = sampleF /2 
#define AMPLITUDE 150 // 灵敏度
#define FREQUENCY_BANDS 14
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define BARWIDTH 11
#define BARS 11
#define ANALOG_PIN A0
#define OLED_RESET     -1 // 重置引脚 #(如果共享 Arduino 重置引脚,则为 -1)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
double vImag[SAMPLES];
double vReal[SAMPLES];
unsigned long sampling_period_us;
arduinoFFT fft = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);
//调整参考以去除背景噪声
float reference = log10(80.0);
double coutoffFrequencies[FREQUENCY_BANDS];

void setup() {
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    for (;;); // Don't proceed, loop forever
  }

  // Setup display
  display.clearDisplay();
  display.display();
  display.setRotation(0);
  display.invertDisplay(false);

  sampling_period_us = (1.0 / SAMPLING_FREQ ) * pow(10.0, 6);

  // 计算截止频率,以对数标度为基数 POt
  double basePot = pow(SAMPLING_FREQ / 2.0, 1.0 / FREQUENCY_BANDS);
  coutoffFrequencies[0] = basePot;
  for (int i = 1 ; i < FREQUENCY_BANDS; i++ ) {
    coutoffFrequencies[i] = basePot * coutoffFrequencies[i - 1];
  }

  // 绘制虚线以分离频段
  for (int i = 0; i < BARS - 1 ; i++) {
    for (int j = 0; j < SCREEN_HEIGHT ; j += 4) {
      display.writePixel((i + 1)*BARWIDTH + 2 , j, SSD1306_WHITE );
    }
  }
  display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
}

int oldHeight[20];
int oldMax[20];
double maxInFreq;

void loop() {
  // 采样
  for (int i = 0; i < SAMPLES; i++) {
    unsigned long newTime = micros();
    int value = analogRead(ANALOG_PIN);
    vReal[i] = value;
    vImag[i] = 0;
    while (micros() < (newTime + sampling_period_us)) {
      yield();
    }
  }

  // 计算 FFT
  fft.DCRemoval();
  fft.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  fft.Compute(FFT_FORWARD);
  fft.ComplexToMagnitude();

  double median[20];
  double max[20];
  int index = 0;
  double hzPerSample = (1.0 * SAMPLING_FREQ) / SAMPLES; //
  double hz = 0;
  double maxinband = 0;
  double sum = 0;
  int count = 0;
  for (int i = 2; i < (SAMPLES / 2) ; i++) {
    count++;
    sum += vReal[i];
    if (vReal[i] >  max[index] ) {
      max[index] = vReal[i];
    }
    if (hz > coutoffFrequencies[index]) {
      median[index] = sum / count;
      sum = 0.0;
      count = 0;
      index++;
      max[index] = 0;
      median[index]  = 0;
    }
    hz += hzPerSample;
  }
  // 计算每个频段的中值和最大值
  if ( sum > 0.0) {
    median[index] =  sum / count;
    if (median[index] > maxinband) {
      maxinband = median[index];
    }
  }
  int bar = 0;

  for (int i = FREQUENCY_BANDS - 1; i >= 3; i--) {
    int newHeight = 0;
    int newMax = 0;
    // 计算实际分贝
    if (median[i] > 0 && max[i] > 0 ) {
      newHeight = 20.0 * (log10(median[i] ) - reference);
      newMax = 20.0 * (log10(max[i] ) - reference);
    }

    // 调整最小和最大级别
    if (newHeight < 0 ||  newMax < 0) {
      newHeight = 1;
      newMax = 1;
    }
    if (newHeight >= SCREEN_HEIGHT - 2) {
      newHeight = SCREEN_HEIGHT - 3;
    }
    if (newMax >= SCREEN_HEIGHT - 2) {
      newMax = SCREEN_HEIGHT - 3;
    }

    int barX = bar * BARWIDTH + 5;
    // 删除旧水平中位数
    if (oldHeight[i] > newHeight) {
      display.fillRect(barX, newHeight + 1, 7, oldHeight[i], SSD1306_BLACK);
    }
    // 删除旧的最大级别
    if ( oldMax[i] > newHeight) {
      for (int j = oldMax[i]; j > newHeight; j -= 2) {
        display.drawFastHLine(barX , j, 7, SSD1306_BLACK);
      }
    }
    // 绘制新的最大级别
    for (int j = newMax; j > newHeight; j -= 2) {
      display.drawFastHLine(barX , j, 7,  SSD1306_WHITE);
    }
    // 绘制新的级别中位数
    display.fillRect(barX , 1, 7, newHeight, SSD1306_WHITE);
    oldMax[i] = newMax;
    oldHeight[i] = newHeight;
    bar++;
  }
  display.drawFastHLine(0 , SCREEN_HEIGHT - 1, SCREEN_WIDTH, SSD1306_WHITE);
  display.display();
}

  【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
 实验九十七: 0.96寸I2C IIC通信128*64显示器 OLED液晶屏模块


 项目三十二:使用FFT库的迷你音乐频谱仪(声谱可视化器)(完整测试视频2分41秒)

https://v.youku.com/v_show/id_XNTgwNzU4MDIzNg==.html?spm=a2hcb.playlsit.page.1

 

评论

user-avatar
  • hacker_

    hacker_2023.07.27

    666

    0
    icon 他的勋章
      展开更多