본문 바로가기
아두이노

DIY 아두이노 OLED 스펙트럼 분석기

by 모빌리티키즈 2024. 10. 17.
728x90
반응형

프로젝트 소개

오늘은 아두이노를 이용해 OLED 스펙트럼 분석기를 만들어보겠습니다.  분석기는 0-3.3V 아날로그 입력으로 작동하며 매우 부드럽고 선명한 오디오 주파수를 시각화합니다. DVD 음악 플레이어, 아이팟, MP3 플레이어  다양한 오디오 장치에서 사용할  있는  분석기는 모든 종류의 음악을 시각적으로 표현할  있습니다.  프로젝트는 브레드보드에서 간단하게 만들  있습니다.

필요 부품

  • 아두이노 나노 또는 아두이노 우노
  • 128x64 I2C OLED 디스플레이
  • 점퍼 와이어
  • 브레드보드

SSD1306 OLED 디스플레이

 디스플레이는 I2C 2선식 인터페이스를 사용하여 아두이노와 연결됩니다. 크기는 0.96인치로, 128x64 픽셀 해상도를 가지고 있습니다. OLED는 유기 발광 다이오드를 의미하며, 백라이트 핀이 필요하지 않습니다.

연결 방법

     OLED 핀                                                                                         아두이노 핀

 

Vin 5V (전원)
GND GND (접지)
SCL A5 (I2C 핀)
SDA A4 (I2C 핀)

아두이노 모델에 따른 I2C  배치:

  • Arduino Uno/Nano: SDA (A4), SCL (A5)
  • Arduino Leonardo/Mega: SDA (20), SCL (21)

사용 라이브러리

  • Adafruit SSD1306 라이브러리
  • Adafruit GFX 라이브러리

 라이브러리들은 Github에서 다운로드할  있으며, Arduino IDE의 라이브러리 매니저를 통해 설치할  있습니다.

연결 방법

브레드보드를 이용해 간단하게 OLED와 아두이노를 연결합니다.

소스 코드

아래는 SSD1306 OLED 디스플레이를 사용한 전체 코드입니다.

cpp
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  // 초기화
  if(!display.begin(SSD1306_I2C_ADDRESS, OLED_RESET)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  display.display();
  delay(2000); // 디스플레이 부팅 딜레이

  // 디스플레이 클리어
  display.clearDisplay();

  // 텍스트 설정
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.print(F("Hello, world!"));
  display.display(); 
}

void loop() {
  // 스펙트럼 분석 코드 추가 예정
}

 코드에서는 기본적인 OLED 초기화  텍스트 출력을 포함하고 있습니다. 여기서 추가적으로 오디오 주파수 시각화 코드를 작성하면 됩니다.

 

 

 
 

오늘 저는 아두이노를 만들고 있습니다. OLED 스펙트럼 분석기는 0-3.3v 아날로그 입력으로 작동합니다. 이것은 매우 부드럽고 선명한 오디오 주파수의 시각화. 이것은 매우 중요합니다. DVD 음악 플레이어, 아이팟, MP3 플레이어 및 오디오 스펙트럼 분석기 만들기 다른 음악 플레이어는 보기가 좋을 뿐만 아니라 모든 종류의 음악을 나타냅니다. 당신은 그것을 맞추기 위해 상자를 만들고 자동차나 원하는 곳 어디에나 부착할 수 있지만 나는 브레드보드에서 간단하게 만드세요.

참고: 이 프로젝트는 다음을 위한 것입니다. 간단한 오디오 장치, 실제 스펙트럼 분석기 장치는 전자 레인지에 사용됩니다. 신호, 레이더 신호, 접시 안테나 신호, 케이블 주파수 신호 등 하다 Arduino가 영구적으로 타거나 충돌할 것이라고 제안하는 이러한 것을 사용하려고 하지 마십시오.

이 블로그에서는 Arduino Spectrum에 대해 배웁니다 다음과 같은 분석기:

>>SSD1306 OLED 디스플레이

>>필요한 부품

>>우리가 사용해야 하는 라이브러리

>>매우 쉬운 브레드보드 연결

>>전체 코드

SSD1306 OLED 디스플레이 :

Arduino를 위한 이 매우 일반적이고 간단한 OLED 디스플레이 I2C 2선식이라고 하는 arduino에서 연결할 핀의 수가 매우 적습니다. I2C는 인터페이스(I2C=IIC=Inter-Integrated Circuit)이고 OLED는 약자입니다. 유기 발광 다이오드용. 이 OLED 디스플레이의 크기는 0.96인치입니다. 너무 작게 만들고 총 픽셀은 128X64 픽셀 해상도입니다. 사진을 비트맵으로 변환하고 이 디스플레이에 표시할 프로그램을 프로그래밍합니다. 16X2 LCD에서 디스플레이 백라이트 핀이 필요하지만 OLED에서는 이 핀이 필요하지 않습니다.

OLED를 Arduino에 연결하는 것은 매우 간단합니다. 다음 배선을 따르십시오 :
OLED 핀 : 아두이노 핀
Vin | 5V는 전원 핀
GND입니다 | GND //이것은 GND 핀
SCL입니다 | A5 이것은 I2C 핀
SDA입니다 | A4 이것은 I2C 핀입니다.
Arduino 핀의 종류 사용하는 경우 :
Arduino Uno : SDA (A4), SCL (A5)
아두이노 나노: SDA (A4), SCL (A5)
아두이노 레오나르도: SDA (20), SCL (21)
아두이노 메가: SDA (20), SCL (21)
 

필요한 부속:

아두이노 나노 또는
아두이노 우노
128x68 I2C OLED 디스플레이
점퍼 와이어
브레드보드

이 프로젝트에 사용된 라이브러리:

이 프로젝트의 초보자라면 다음을 수행해야 합니다. Github에서 사용할 수 있는 Adafruit SSD1306 Master zip Library SSD1306 다운로드 또한 다음에서도 사용할 수 있는 Adafruit GFX 라이브러리 master.zip 하나 더 필요합니다. 깃허브. Arduino IDE 소프트웨어를 열고 스케치 탭으로 이동 한 다음 여기에서 포함을 클릭하십시오. 라이브러리를 클릭하고 Add Zip Library(Zip 라이브러리 추가)를 클릭하면 다운로드한 라이브러리를 추가할 수 있습니다. 또한 Manage Library Option에서 다운로드하여 설치할 수 있습니다. 이 상자의 라이브러리.



이제 이 프로젝트를 위해 FIX_FFT.h를 다운로드해야 합니다. fix_fft.h 및 nano_engine.h 라이브러리의 마스터 zip 여기 나노 엔진 (이것은 SSD1306의 내장 헤더 파일입니다).

브레드보드 연결:

이것은 Arduino Nano에 대한 매우 간단한 연결이며 올레드. 여기서는 연결된 음악의 볼륨을 조정하기 위해 10k 변수를 사용하고 있습니다 A0 핀 및 오디오 입력 플러그로 오디오 장치와 연결합니다.
 
 

오디오 입력:

항상 볼륨을 확인하십시오tage 및 전류 수준 Arduino 보드의 아날로그 입력은 음악 또는 사운드 입력, 일부 앰프 및 사운드 장치는 출력으로 너무 높은 전류이므로 연결하지 마십시오. 이 이 장치는 3.8 - 4V 및 40mA - 300mA 최대 전압 및 전류만 필요합니다. 미니 휴대용 앰프, 아이팟, 휴대용 스피커, MP3 플레이어 등에서
 

전체 코드:

여기에서 Arduino IDE에 코드를 복사하여 붙여넣을 수 있습니다
이것은 ColoneWatch Github의 저작권 코드입니다.
// Copyright [2019] [colonelwatch]

#include <fix_fft.h>                  // 8-bit FFT library modified for Arduino
#include <ssd1306.h>                  // library for OLED
#include <nano_engine.h>              // library for nanoengine (which draws sector-by-sector on OLED because the ATtiny85 can't hold a full buffer)

// To get this program to operate, the SDA and SCL pins must be reassigned to 0 and 2 respectively in the library header file
// The file is located in libraries\ssd1306\src\intf\i2c\ssd1306_i2c_conf.h
// Make sure to undo this if the library will be used again in the future

// These are user-adjustable
//#define LOG_OUTPUT              // Uncomment to enable logarithmic output (exchanges absolute resoluton for more readable output; may require different below params)
#define SAMPLING_FREQUENCY 15000  // Sampling frequency (Actual max measured frequency captured is half)
#define TIME_FACTOR 3             // Smoothing factor (lower is more dynamic, higher is smoother) ranging from 1 to 10+
#define SCALE_FACTOR 12           // Direct scaling factor (raise for higher bars, lower for shorter bars)

#ifdef LOG_OUTPUT
const float log_scale = 64./log(64./SCALE_FACTOR + 1.);                              // Attempts to create an equivalent to SCALE_FACTOR for log function
#endif
const float coeff = 1./TIME_FACTOR;                                                  // Time smoothing coefficients (used to factor in previous data)
const float anti_coeff = (TIME_FACTOR-1.)/TIME_FACTOR;
const unsigned int sampling_period_us = round(1000000 * (2.0 / SAMPLING_FREQUENCY)); // Sampling period (doubled to account for overclock)

int8_t data[64], buff[32];                                     // used to store FFT input/output and past data
unsigned long microseconds;                                    // used for timekeeping
int summ, avg;                                                 // used for DC bias elimination

NanoEngine<TILE_32x32_MONO> engine;                            // declares nanoengine

void setup()
{
  OSCCAL = 240; // Overclocks the MCU to around 30 MHz, set lower if this causes instability, raise if you can/want
  
  ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2));       // clear ADC prescaler bits
  ADCSRA |= bit (ADPS2);                                      // sets ADC clock in excess of 10kHz
  ADCSRA |= bit (ADPS0);

  ssd1306_128x64_i2c_init();                                  // initializes OLED
  ssd1306_clearScreen();                                      // clears OLED
  
  engine.begin();                                             // inititalizes nanoengine
};

void loop()
{
  summ = 0;
  for (int i = 0; i < 64; i++) {
    microseconds = micros();
    
    data[i] = ((analogRead(A0)) >> 2) - 128;                        // Fitting analogRead data (range:0 - 1023) to int8_t array (range:-128 - 127)
    summ += data[i];
    while (micros() < (microseconds + sampling_period_us)) {        // Timing out uC ADC to fulfill sampling frequency requirement
    }
  }

  // Eliminating remaining DC component (produces usable data in FFT bin #0, which is usually swamped by DC bias)
  avg = summ/64;
  for (int i = 0; i < 64; i++){
    data[i] -= avg;
  }
    
  fix_fftr(data, 6, 0);                             // Performing real FFT
  
  // Time smoothing by user-determined factor and user-determined scaling
  for(int count = 0; count < 32; count++){
  if(data[count] < 0) data[count] = 0;                                          // Eliminating negative output of fix_fftr
  #ifdef LOG_OUTPUT
  else data[count] = log_scale*log((float)(data[count]+1));                     // Logarithmic function equivalent to SCALING_FACTOR*log2(x+1)
  #else
  else data[count] *= SCALE_FACTOR;                                             // Linear scaling up according to SCALE_FACTOR
  #endif
  data[count] = (float)buff[count] * anti_coeff + (float)data[count] * coeff;   // Smoothing by factoring in past data
  buff[count] = data[count];                                                    // Storing current output as next frame's past data
  if(data[count] > 63) data[count] = 63;                                        // Capping output at screen height
  }
  
  // Output to SSD1306 using nanoengine canvas from library
  engine.refresh();                                               // Mark entire screen to be refreshed
  engine.canvas.clear();                                          // Clear canvas as previous data
  for(int i = 0; i < 8; i++){
    engine.canvas.drawVLine(i*4,31-(data[i]+1),31);          // Draw to canvas data for lower-leftest sector (FFT bins 0 - 7, lower half)
  }
  engine.canvas.blt(0,32);                                        // Outputs canvas to OLED with an offset (x pixels, y pixels)
  engine.canvas.clear();
  for(int i = 0; i < 8; i++){
    if(data[i] > 31) engine.canvas.drawVLine(i*4,31-(data[i]-31),31);     // Draw to canvas data for upper-leftest sector (FFT bins 0 - 7, upper half)
  }
  engine.canvas.blt(0,0);
  engine.canvas.clear();
  for(int i = 8; i < 16; i++){
    engine.canvas.drawVLine((i-8)*4,31-(data[i]+1),31);      // FFT bins 8 - 15, lower half
  }
  engine.canvas.blt(32,32);  
  engine.canvas.clear();
  for(int i = 8; i < 16; i++){
    if(data[i] > 31) engine.canvas.drawVLine((i-8)*4,31-(data[i]-31),31);   // FFT bins 9 - 15, upper half
  }
  engine.canvas.blt(32,0);
  engine.canvas.clear();
  for(int i = 16; i < 24; i++){
    engine.canvas.drawVLine((i-16)*4,31-(data[i]+1),31);     // FFT bins 16 - 23, lower half
  }
  engine.canvas.blt(64,32);
  engine.canvas.clear();
  for(int i = 16; i < 24; i++){
    if(data[i] > 31) engine.canvas.drawVLine((i-16)*4,31-(data[i]-31),31);  // FFT bins 16 - 23, upper half 
  }
  engine.canvas.blt(64,0);
  engine.canvas.clear();
  for(int i = 24; i < 32; i++){
    engine.canvas.drawVLine((i-24)*4,31-(data[i]+1),31);     // FFT bins 24 - 31, lower half
  }
  engine.canvas.blt(96,32);
  engine.canvas.clear();
  for(int i = 24; i < 32; i++){
    if(data[i] > 31) engine.canvas.drawVLine((i-24)*4,31-(data[i]-31),31);  // FFT bins 24 - 31, upper half
  }
  engine.canvas.blt(96,0);
}
728x90
반응형