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

【Arduino 动手做】I2C OLED 上的 DIY 模拟式立体声 VU 表 简单

头像 驴友花雕 2025.06.23 9 0

如何制作一个非常简单但视觉上有效的 0.9 英寸 OLED 显示器 VU 表 SSD 1306。

这次,我将向您展示如何在小型 0.96 英寸 OLED 显示器上制作模拟式立体 VU 表。前段时间我收到了非常适合此目的的小型黄色 OLED 显示器。

该设备是根据 arduino.cc 论坛中的“stevenart”的说明制作的,您还可以在论坛中找到原始代码(适用于 SH1106 Oled)。具体来说,在这种情况下,代码略有修改(SSD1306 Oled),并且在硬件中,部分添加了一个简单的输入电路(包络跟随器),以便 VU 表可以直接连接到音频放大器的输出。该设备的构建非常简单,并且只包含几个组件。

可以看出,VU 表的每个通道分别包含两个相同的组件。它可以只用一个 Arduino 制成,但在这种情况下,OLED 显示器必须具有不同的 I2C 地址。我的 OLED 显示器具有相同的 I2C 地址,因此我不得不制作两个相同的设备,它们的成本只比 Arduino 高几美元。但是,如果您能够获得具有不同地址的 Oled 显示器,或者有可能根据网上给出的一些说明通过焊接更改一个显示器的地址,那就更好了。以下是具有线性刻度和弧刻度的 VU 仪表的代码。对于 Reverse light (倒车灯) 修改,需要执行以下作:
在 viod 设置之后:
display.clearDisplay();

我们需要添加:

display.invertDisplay(true);

所以一个通道的组成部分是:
- Arduino 微控制器
- SSD1306 个 0.96 英寸小型 Oled 显示屏
- 两个电阻器
- 一个电容器
- 和电位器
另一个通道是相同的。让我提一下,在现场观看时,箭头的移动是流畅的。最后,将设备安装在由 PVC 材料制成的合适盒子中,并衬有自粘彩色墙纸。

 

00.jpg
01.jpg
02.jpg
03.jpg
04.jpg

项目代码:
CODE 弧标尺,单屏:

代码
/*  OLEDMeter was written to utilize any 128x64 display. I have only seen marginal attempts to
 *  animate meters and I hope this one will set a standard. Please feel free to modify and share
 *  this code for any 128x64 LCD or OLED. OLEDMeter sketch was written for use with I2C SSD1306.
 *  This code must be modified to work with other display devices.
 *  
 *  Working portion of code was taken from Adafruit Example Sound Level Sketch for the
 *  Adafruit Microphone Amplifier
 *  https://learn.adafruit.com/adafruit-microphone-amplifier-breakout/measuring-sound-levels
 *  
 *  Remaining code was written by Greg Stievenart with no claim to or any images or information 
 *  provided in this code. Freely published May 26, 2016.
 *  
 *  Software to convert background mask to 128x64 at: http://www.ablab.in/image2glcd-software/
 *  
 *  IMPORTANT: Sound source must be grounded to the Arduino or other MCU's to work. Usually the
 *  base sleeve contact on TRS or TRRS connector is the ground.
 */

#include <Wire.h>                     // requried to run I2C SSD1306
#include <SPI.h>                      // requried to run I2C SSD1306
#include <Adafruit_GFX.h>             // https://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h>          // https://github.com/wonho-maker/Adafruit_SSD1306

#define OLED_RESET 4                  // reset required for SSD1306

Adafruit_SSD1306 display(OLED_RESET);  // reset required for SSD1306

int analogInput = A0;                 // analog input for outside audio source
int hMeter = 65;                      // horizontal center for needle animation
int vMeter = 85;                      // vertical center for needle animation (outside of dislay limits)
int rMeter = 80;                      // length of needle animation or arch of needle travel

const int sampleWindow = 50;          // sample window width in mS (50 mS = 20Hz)
unsigned int sample;

// VU meter background mask image:
static const unsigned char PROGMEM VUMeter[] = { 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x04, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0x98, 0x08, 0x06, 0x03, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x09, 0x00, 0x80, 0x21, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x06, 0x03, 0x00, 0x20, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x71, 0x80, 0xA4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0A, 0x40, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3C, 0x00, 0x00,
  0x00, 0x00, 0x3A, 0x40, 0x00, 0x00, 0x02, 0x01, 0x00, 0x40, 0x80, 0x07, 0x00, 0x20, 0x00, 0x00,
  0x00, 0x00, 0x42, 0x40, 0x00, 0x08, 0x02, 0x01, 0x08, 0x40, 0x80, 0x00, 0x00, 0x38, 0x00, 0x00,
  0x00, 0x00, 0x79, 0x80, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x11, 0x04, 0x00, 0x38, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x02, 0x01, 0x08, 0x81, 0x21, 0x04, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x00, 0x84, 0x02, 0x04, 0x0F, 0xFF, 0xFF, 0xC3, 0xE2, 0x04, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x00, 0xC2, 0x01, 0x07, 0xF0, 0x00, 0x00, 0x3B, 0xFE, 0x08, 0x40, 0x40, 0x08, 0x00,
  0x00, 0xFE, 0x00, 0x62, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE8, 0x40, 0x80, 0x7F, 0x00,
  0x00, 0x00, 0x00, 0x21, 0x1E, 0x00, 0x04, 0x00, 0x80, 0x00, 0x7F, 0xFE, 0x80, 0x80, 0x08, 0x00,
  0x00, 0x00, 0x03, 0x31, 0xE0, 0x00, 0x04, 0x00, 0x80, 0x04, 0x01, 0xFF, 0xC1, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x07, 0x1E, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1F, 0xFA, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x07, 0xF0, 0x00, 0x40, 0x3B, 0x07, 0x60, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x34, 0x81, 0x90, 0xCC, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x03, 0x30, 0x0C, 0x82, 0x90, 0x53, 0x20, 0x00, 0x07, 0xF8, 0x00, 0x00,
  0x00, 0x00, 0x70, 0x40, 0x00, 0xC8, 0x3B, 0x02, 0x60, 0x53, 0x20, 0x00, 0x00, 0xFE, 0x00, 0x00,
  0x00, 0x01, 0x80, 0x20, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x4C, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00,
  0x00, 0x06, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00,
  0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00,
  0x00, 0x30, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00,
  0x00, 0x00, 0x40, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
  0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x02, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x06, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x8C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x70, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup(){

  pinMode(analogInput, INPUT);                             // analog input for outside audio source
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);                // needed for SSD1306 display
  display.clearDisplay();                                  // clears display from any library info displayed
  
  
}

void loop(){

/***********************************************************************
 Start of code taken from Adafruit Example Sound Level Sketch for the 
 Adafruit Microphone Amplifier
************************************************************************/
  
  unsigned long startMillis = millis();                    // start of sample window
  unsigned int PeaktoPeak = 0;                             // peak-to-peak level
  unsigned int SignalMax = 0;
  unsigned int SignalMin = 1024;

  while ( millis() - startMillis < sampleWindow ){

    sample = analogRead(analogInput);
    if (sample < 1024) {

      if (sample > SignalMax){

        SignalMax = sample;                                // saves just the max levels
      }

      else if (sample < SignalMin){

        SignalMin = sample;                                // saves just the min levels
      }
    }
  }

  PeaktoPeak = SignalMax - SignalMin;                      // max - min = peak-peak amplitude
  float MeterValue = PeaktoPeak * 330 / 1024;              // convert volts to arrow information

/****************************************************
 End of code taken from Adafruit Sound Level Sketch
*****************************************************/
  
  MeterValue = MeterValue - 34;                            // shifts needle to zero position
  display.clearDisplay();                                  // refresh display for next step
  display.drawBitmap(0, 0, VUMeter, 128, 64, WHITE);       // draws background
  int a1 = (hMeter + (sin(MeterValue / 57.296) * rMeter)); // meter needle horizontal coordinate
  int a2 = (vMeter - (cos(MeterValue / 57.296) * rMeter)); // meter needle vertical coordinate
  display.drawLine(a1, a2, hMeter, vMeter, WHITE);         // draws needle
  display.display();
}

CODE 线性刻度,立体声双屏:

代码
/*  OLEDMeter was written to utilize any 128x64 display. I have only seen marginal attempts to
 *  animate meters and I hope this one will set a standard. Please feel free to modify and share
 *  this code for any 128x64 LCD or OLED. OLEDMeter sketch was written for use with I2C SSD1306.
 *  This code must be modified to work with other display devices.
 *  
 *  Working portion of code was taken from Adafruit Example Sound Level Sketch for the
 *  Adafruit Microphone Amplifier
 *  https://learn.adafruit.com/adafruit-microphone-amplifier-breakout/measuring-sound-levels
 *  
 *  Remaining code was written by Greg Stievenart with no claim to or any images or information 
 *  provided in this code. Freely published May 26, 2016.
 *  
 *  Software to convert background mask to 128x64 at: http://www.ablab.in/image2glcd-software/
 *  
 *  IMPORTANT: Sound source must be grounded to the Arduino or other MCU's to work. Usually the
 *  base sleeve contact on TRS or TRRS connector is the ground.
 */

#include <Wire.h>                     // requried to run I2C SSD1306
//#include <SPI.h>                      // requried to run I2C SSD1306
#include <Adafruit_GFX.h>             // https://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h>         // https://github.com/adafruit/Adafruit_SSD1306

#define OLED_RESET 4                  // reset required for SSD1306

Adafruit_SSD1306 display1(OLED_RESET);  // reset required for SSD1306
Adafruit_SSD1306 display2(OLED_RESET);  // reset required for SSD1306


int left = A0;                 // analog input for outside audio source
int right = A1;                 // analog input for outside audio source

int hMeter = 65;                      // horizontal center for needle animation
int vMeter = 85;                      // vertical center for needle animation (outside of dislay limits)
int rMeter = 80;                      // length of needle animation or arch of needle travel
float MeterValueLeft;
float MeterValueRight;
const int sampleWindow = 5;          // sample window width in mS (50 mS = 20Hz)
unsigned int sampleLeft;
unsigned int sampleRight;
unsigned int PeakRight = 400;                             // start needle fall max to min on start
unsigned int PeakLeft = 400;                             // start needle fall max to min on start
unsigned int fallTimeRight;          // needle fallspeed
unsigned int fallTimeLeft;          // needle fallspeed

// VU meter background mask image:
static const unsigned char PROGMEM VUMeter[] = { 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x1D, 0xC0, 0x00, 0x2E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x40, 0x1C, 0x00, 0x1C, 0x10, 
0x00, 0x05, 0x40, 0x00, 0x2A, 0x00, 0x00, 0x02, 0x00, 0x00, 0xA0, 0x40, 0x04, 0x00, 0x04, 0x10, 
0x1F, 0x1D, 0x40, 0x00, 0x2A, 0x00, 0x00, 0x0E, 0x00, 0x00, 0xA0, 0x40, 0x1C, 0x00, 0x1C, 0x7C, 
0x00, 0x11, 0x40, 0x00, 0x2A, 0x00, 0x00, 0x02, 0x00, 0x00, 0xA0, 0x40, 0x10, 0x00, 0x04, 0x10, 
0x00, 0x1D, 0xC0, 0x00, 0x2E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x40, 0x1C, 0x00, 0x1C, 0x10, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x40, 0x08, 0x00, 0x08, 0x00, 

0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x40, 0x08, 0x00, 0x08, 0x00, 
0x00, 0x02, 0x00, 0x00, 0x08, 0x08, 0x08, 0x04, 0x10, 0x40, 0x5F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x01, 0x00, 0x00, 0x20, 0x00, 0x40, 0x01, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x03, 0x80, 0x01, 0xDC, 0x02, 0x38, 0x0E, 0xE0, 0xEE, 0x05, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x02, 0x80, 0x00, 0x54, 0x02, 0xA8, 0x08, 0xA0, 0xAA, 0x05, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x02, 0x80, 0x01, 0xD4, 0x02, 0xA8, 0x0E, 0xA0, 0xEA, 0x05, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x02, 0x80, 0x01, 0x14, 0x03, 0xA8, 0x0A, 0xA0, 0xAA, 0x05, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x03, 0x80, 0x01, 0xDC, 0x00, 0xB8, 0x0E, 0xE0, 0xEE, 0x05, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x14, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x17, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
};

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

  pinMode(left, INPUT);                             // analog input for outside audio source
    pinMode(right, INPUT);                             // analog input for outside audio source

  display1.begin(SSD1306_SWITCHCAPVCC, 0x3C);                // needed for SSD1306 display1    3C
  display1.clearDisplay();  // clears display from any library info displayed
  
  display2.begin(SSD1306_SWITCHCAPVCC, 0x3D);                // needed for SSD1306 display     3D
  display2.clearDisplay();                                  // clears display from any library info displayed
 
}

void loop(){

  unsigned long startMillis = millis();                    // start of sample window
  unsigned int PeaktoPeakLeft = 0;                             // peak-to-peak level
  unsigned int SignalMaxLeft = 0;
  unsigned int SignalMinLeft = 1024;
  unsigned int PeaktoPeakRight = 0;                             // peak-to-peak level
  unsigned int SignalMaxRight = 0;
  unsigned int SignalMinRight = 1024;
  while ( millis() - startMillis < sampleWindow ){

    sampleLeft = analogRead(left);
    sampleRight = analogRead(right);

    if (sampleLeft < 1024) {

      if (sampleLeft > SignalMaxLeft){

        SignalMaxLeft = sampleLeft;                                // saves just the max levels
      }

      else if (sampleLeft < SignalMinLeft){

        SignalMinLeft = sampleLeft;                                // saves just the min levels
      }
    }
    if (sampleRight < 1024) {

      if (sampleRight > SignalMaxRight){

        SignalMaxRight = sampleRight;                                // saves just the max levels
      }

      else if (sampleRight < SignalMinRight){

        SignalMinRight = sampleRight;                                // saves just the min levels
      }
    }
   
  }

  PeaktoPeakLeft = SignalMaxLeft - SignalMinLeft;                      // max - min = peak-peak amplitude
  PeaktoPeakRight = SignalMaxRight - SignalMinRight;                   // max - min = peak-peak amplitude

   if (PeaktoPeakLeft > PeakLeft){

        PeakLeft = PeaktoPeakLeft;// saves just the min levels
      }else if(PeaktoPeakLeft < PeakLeft){
        fallTimeLeft = ((PeakLeft - PeaktoPeakLeft) / 2);
        PeakLeft = PeakLeft-fallTimeLeft;
      }
   if (PeaktoPeakRight > PeakRight){

        PeakRight = PeaktoPeakRight;// saves just the min levels
      }else if(PeaktoPeakRight < PeakRight){
        fallTimeRight = ((PeakRight - PeaktoPeakRight) / 2);
        PeakRight = PeakRight-fallTimeRight;
      }

    

  MeterValueLeft = PeakLeft ;              // convert volts to arrow information sensitivity 
  MeterValueRight = PeakRight ;              // convert volts to arrow information sensitivity 

 drawleft();
 drawright();
}

void drawleft(){
  




  MeterValueLeft = MeterValueLeft - 34;                            // shifts needle to zero position
  display1.clearDisplay();                                  // refresh display for next step
  display1.drawBitmap(0, 0, VUMeter, 128, 64, WHITE);       // draws background white
  int a1 = (hMeter + (sin(MeterValueLeft / 57.296) * rMeter)); // meter needle horizontal coordinate
  int a2 = (vMeter - (cos(MeterValueLeft / 57.296) * rMeter)); // meter needle vertical coordinate
  
display1.drawLine(a1-2, a2, hMeter-1, vMeter, BLACK);         // draws needle
display1.drawLine(a1-1, a2, hMeter-1, vMeter, WHITE);         // draws needle  
display1.drawLine(a1, a2, hMeter, vMeter, WHITE);         // draws needle
display1.drawLine(a1+1, a2, hMeter+1, vMeter, WHITE);         // draws needle  
display1.drawLine(a1+2, a2, hMeter+1, vMeter, BLACK);         // draws needle
  display1.display();
}
void drawright(){
  




  MeterValueRight = MeterValueRight - 44;                            // shifts needle to zero position
  display2.clearDisplay();                                  // refresh display for next step
  display2.drawBitmap(0, 0, VUMeter, 128, 64, WHITE);       // draws background white
  int a1 = (hMeter + (sin(MeterValueRight / 57.296) * rMeter)); // meter needle horizontal coordinate
  int a2 = (vMeter - (cos(MeterValueRight / 57.296) * rMeter)); // meter needle vertical coordinate
  display1.drawLine(a1-2, a2, hMeter-1, vMeter, BLACK);         // draws needle
display1.drawLine(a1-1, a2, hMeter-1, vMeter, WHITE);         // draws needle  
display1.drawLine(a1, a2, hMeter, vMeter, WHITE);         // draws needle
display1.drawLine(a1+1, a2, hMeter+1, vMeter, WHITE);         // draws needle  
display1.drawLine(a1+2, a2, hMeter+1, vMeter, BLACK);         // draws needle
  display2.display();
}

【Arduino 动手做】I2C OLED 上的 DIY 模拟式立体声 VU 表
项目链接:https://www.hackster.io/mircemk/diy-analog-style-stereo-vu-meter-on-i2c-oled-00aca7
项目作者:北马其顿 米尔塞姆克(Mirko Pavleski)

项目视频 :https://www.youtube.com/watch?v=Wsuehxhob-c
项目代码:
CODE 弧标尺,单屏:
https://www.hackster.io/code_files/532492/download
CODE 线性刻度,立体声双屏:
https://www.hackster.io/code_files/532493/download

 

00170---.gif
00170---=.gif

评论

user-avatar
icon 他的勋章
    展开更多