Анализатор спектра на SH1106 OLED 1.3″ (Arduino)

SH1106 OLED 1.3″ — OLED-дисплей с контроллером SH1106. Этот дисплей имеет разрешение 128×64 пикселей и может отображать монохромную графику и текст. Он может использоваться для различных проектов, где нужно отобразить информацию компактным и энергосберегающим способом. Дисплей легко подключается к микроконтроллерам и одноплатным компьютерам, таким как Arduino или Raspberry Pi, используя интерфейс SPI или I2C.

На OLED дисплее можно сделать простой анализатор спектра аудио сигнала.

Анализатор спектра выполнен на базе микроконтроллера LGT8F328P. Используется плата разработчика LGT8F328P-LQFP32 MiniEVB.

Плата LGT8F328P-LQFP32 MiniEVB 

LGT8F328P-LQFP32 MiniEVB — это миниатюрная платформа разработки с микроконтроллером LGT8F328P в корпусе LQFP32. Этот микроконтроллер совместим с ATmega328P, имеет тактовую частоту до 32 МГц и 32 Кб флэш-памяти. MiniEVB оснащена USB-интерфейсом, который позволяет программировать и отлаживать микроконтроллер, а также подключить его к компьютеру. Кроме того, на плате есть разъемы для питания, монтажа дополнительных периферийных устройств и раздельного доступа к пинам микроконтроллера. Эта платформа разработки может быть использована для создания различных электронных проектов, начиная от простых LED-мигалок до сложных устройств на базе микроконтроллера.

Как добавить поддержку LGT8F328P (плата) в Arduino IDE и прошить микроконтроллер написано в LGT8F328P-LQFP32 MiniEVB в Arduino IDE.

#define AUTO_GAIN 1       // автонастройка по громкости (экспериментальная функция)
#define VOL_THR 25        // порог тишины (ниже него отображения на матрице не будет)
#define LOW_PASS 20       // нижний порог чувствительности шумов (нет скачков при отсутствии звука)
#define DEF_GAIN 80       // максимальный порог по умолчанию (при GAIN_CONTROL игнорируется)
#define FHT_N 256         // ширина спектра х2
#define LOG_OUT 1

// вручную забитый массив тонов, сначала плавно, потом круче
byte posOffset[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};//1500 Hz
//byte posOffset[16] = {1, 2, 3, 4, 6, 8, 10, 13, 16, 20, 25, 30, 35, 40, 45, 50};//4000 Hz

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#include <Wire.h>
#include <U8glib.h>  // http://rcl-radio.ru/wp-content/uploads/2023/04/U8glib.zip
#include <FHT.h>     // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=297&download=1

U8GLIB_SH1106_128X64 myOLED(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);  // Dev 0, Fast I2C / TWI
 
  byte gain = DEF_GAIN;   
  unsigned long gainTimer,times;
  byte maxValue, maxValue_f;
  float k = 0.1;
  byte ur[16],urr[16];
  
void setup() {
  delay(100); 
  sbi(ADCSRA, ADPS2);
  cbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);
  Serial.begin(9600);
  Wire.begin();Wire.setClock(800000L);
  myOLED.begin();
 // myOLED.setRot180();
  myOLED.setFont(u8g_font_profont11r);
  analogReadResolution(10);// АЦП 10 БИТ
  analogReference(INTERNAL1V024);
  pinMode(A0,INPUT); // INPUT AUDIO
}
 
void loop() {
 analyzeAudio();
/////// PRINT OLED /////////////////////////////////
 myOLED.firstPage();  
  do {
 for (int pos = 0; pos < 128; pos+=8) {
 int posLevel = map(fht_log_out[posOffset[pos/8]], LOW_PASS, gain, 0, 60);
   posLevel = constrain(posLevel, 0, 60);
   if(millis()-times<2000){posLevel=60;}     
     urr[pos] = posLevel;
     if(urr[pos]<ur[pos]){ur[pos]=ur[pos]-1;}
      else{ur[pos] = posLevel;}
      delayMicroseconds(200); 
 for (int v_pos=0; v_pos<ur[pos]+4;v_pos+=4){myOLED.drawBox(pos, 61-v_pos, 6, 2);}}
  } while( myOLED.nextPage() );
//////////////////////////////////
 if (AUTO_GAIN) {
    maxValue_f = maxValue * k + maxValue_f * (1 - k);
    if (millis() - gainTimer > 1500) {      // каждые 1500 мс
      // если максимальное значение больше порога, взять его как максимум для отображения
      if (maxValue_f > VOL_THR) gain = maxValue_f;
      // если нет, то взять порог побольше, чтобы шумы вообще не проходили
      else gain = 100;
      gainTimer = millis();
    }
  }
}// end loop
 
void analyzeAudio() {
  for (int i = 0 ; i < FHT_N ; i++) {
    int sample = analogRead(A0);
    fht_input[i] = sample; // put real data into bins
  }
  fht_window();  // window the data for better frequency response
  fht_reorder(); // reorder the data before doing the fht
  fht_run();     // process the data in the fht
  fht_mag_log(); // take the output of the fht
}

Добавить комментарий

Войти с помощью: