Анализатор спектра на светодиодной шкале SHB10R (Arduino IDE)

Светодиодная шкала SHB10R — это, по сути, 10 независимых светодиодов в одном корпусе, выложенных в форме шкалы. У индикатора 20 ножек: анод и катод для каждого светодиодах.

SHB10R.pdf

На основе ATtmega8535 используя светодиодную шкалу SHB10R можно сделать простой 12-и полосный анализатор спектра по 10 диодов (по 1 модуля SHB10R) на одну полосу. В итоге используется 12 светодиодных модулей (120 светодиодов).

ATmega8535 — это микроконтроллер производства компании Atmel, который относится к семейству AVR. Вот основные характеристики ATmega8535:

— Архитектура: AVR
— Количество выводов: 44
— Рабочая частота: 0 — 16 МГц
— Количество программной памяти: 8 Кбайт флэш-памяти
— Количество оперативной памяти: 512 байт
— Количество EEPROM: 512 байт
— Количество аналоговых входов: 8
— Количество цифровых входов/выходов: 32
— Интерфейсы: USART, SPI, I2C, 8-битный таймер/счетчик, 16-битный таймер/счетчик, внешнее прерывание

ATmega8535 — это достаточно старый микроконтроллер, который уже не производится компанией Atmel. Однако он все еще может использоваться в некоторых проектах, особенно если требуется небольшое количество памяти и не очень высокая частота работы.

Как ранее отмечалось анализатор спектра звукового сигнала содержит 12 полос, но может быть расширен и до 16 с небольшой правкой скетча.

Так как светодиодная шкала SHB10R  это 10 независимых светодиодов в одном корпусе, то для данного проекта все катоды шкалы необходимо соединить вместе. Общим катодом каждой шкалы будет управлять транзистор BC337. Все одноименные аноды всех шкал необходимо соединить вместе, так как для управления шкалами используется динамическая индикация.

Схема анализатора спектра

Так как прошиваться микроконтроллер будет через Arduino IDE, то на схеме все выводы слева это выводы микросхемы. А выводы справа на схеме это выводы принятые в платформе Arduino (см.ниже обозначение выводов).

Как прошить микроконтроллер ATtmega8535 в Arduino IDE написано в ATmega8535 + Arduino IDE.

#define AUTO_GAIN 1       // автонастройка по громкости (экспериментальная функция)
#define VOL_THR 15        // порог тишины (ниже него отображения на матрице не будет)
#define LOW_PASS 10       // нижний порог чувствительности шумов (нет скачков при отсутствии звука)
#define DEF_GAIN 50       // максимальный порог по умолчанию (при GAIN_CONTROL игнорируется)
#define FHT_N 128         // ширина спектра х2
#define LOG_OUT 1
#define BRIG    5         // ЯРКОСТЬ ИНДИК. 1-10 1=MAX
#define STEP    2000      // ПЛАВНОСТЬ ХОДА ИНД. 1-5000

byte posOffset[12] = {2, 3, 5, 7, 10, 13, 17, 21, 25, 30, 37, 45};
//byte anod[]={16,17,18,19,20,21,22,23,31,30};
byte anod[]={30,31,23,22,21,20,19,18,17,16};
byte katod[]={15,14,13,12,11,10,9,8,7,6,5,4};
int timer_i,kt;

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

#include <FHT.h>     // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=297&download=1

byte gain = DEF_GAIN;   
unsigned long gainTimer,times;
byte maxValue, maxValue_f;
float k = 0.1;
byte ur[12],urr[12];

void setup(){
  delay(100); 
  sbi(ADCSRA, ADPS2);
  cbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);
  cli();
  TCCR2=0;
  OCR2 = 20;
  TCCR2 |= (1 << WGM21);
  TCCR2 |= (1 << CS22) | (1 << CS21)| (1 << CS20);
  TIMSK |= (1 << OCIE2);
  sei();
 for(int i=0;i<10;i++){pinMode(anod[i],OUTPUT);}
 for(int i=0;i<12;i++){pinMode(katod[i],OUTPUT);}
  analogReference(INTERNAL);
  pinMode(A0,INPUT); // INPUT AUDIO
  }

void loop(){  
   analyzeAudio(); 
 
for (int pos = 0; pos < 12; pos++) {
 int posLevel = map(fht_log_out[posOffset[pos]], LOW_PASS, gain*0.5, 0, 9);
   posLevel = constrain(posLevel, 0, 9);
     urr[pos] = posLevel;
     if(urr[pos]<ur[pos]){ur[pos]=ur[pos]-1;}
      else{ur[pos] = posLevel;}
      delayMicroseconds(STEP); 
}     
 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();
    }
  } 

  } 
ISR(TIMER2_COMP_vect){
  switch(timer_i){
    case 0: cl();kat();an();break;
    case 1: cl();kat();an();break;
    case 2: cl();kat();an();break;
    case 3: cl();kat();an();break;
    case 4: cl();kat();an();break;
    case 5: cl();kat();an();break;
    case 6: cl();kat();an();break;
    case 7: cl();kat();an();break;
    case 8: cl();kat();an();break;
    case 9: cl();kat();an();break;
    case 10: cl();kat();an();break;
    case 11: cl();kat();an();break;
    }
    timer_i++;
 
    if(timer_i>11){timer_i=0;}}  

void an(){
  switch(ur[timer_i]){
    case 0:ch(anod[0],1);ch(anod[1],0);ch(anod[2],0);ch(anod[3],0);ch(anod[4],0);ch(anod[5],0);ch(anod[6],0);ch(anod[7],0);ch(anod[8],0);ch(anod[9],0);break;
    case 1:ch(anod[0],1);ch(anod[1],1);ch(anod[2],0);ch(anod[3],0);ch(anod[4],0);ch(anod[5],0);ch(anod[6],0);ch(anod[7],0);ch(anod[8],0);ch(anod[9],0);break;
    case 2:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],0);ch(anod[4],0);ch(anod[5],0);ch(anod[6],0);ch(anod[7],0);ch(anod[8],0);ch(anod[9],0);break;
    case 3:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],1);ch(anod[4],0);ch(anod[5],0);ch(anod[6],0);ch(anod[7],0);ch(anod[8],0);ch(anod[9],0);break;
    case 4:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],1);ch(anod[4],1);ch(anod[5],0);ch(anod[6],0);ch(anod[7],0);ch(anod[8],0);ch(anod[9],0);break;
    case 5:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],1);ch(anod[4],1);ch(anod[5],1);ch(anod[6],0);ch(anod[7],0);ch(anod[8],0);ch(anod[9],0);break;
    case 6:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],1);ch(anod[4],1);ch(anod[5],1);ch(anod[6],1);ch(anod[7],0);ch(anod[8],0);ch(anod[9],0);break;
    case 7:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],1);ch(anod[4],1);ch(anod[5],1);ch(anod[6],1);ch(anod[7],1);ch(anod[8],0);ch(anod[9],0);break;
    case 8:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],1);ch(anod[4],1);ch(anod[5],1);ch(anod[6],1);ch(anod[7],1);ch(anod[8],1);ch(anod[9],0);break;
    case 9:ch(anod[0],1);ch(anod[1],1);ch(anod[2],1);ch(anod[3],1);ch(anod[4],1);ch(anod[5],1);ch(anod[6],1);ch(anod[7],1);ch(anod[8],1);ch(anod[9],1);break;
    }
  }
void kat(){
  switch(timer_i){                                                             
    case 0:ch(15,1);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break;  
    case 1:ch(15,0);ch(14,1);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break;
    case 2:ch(15,0);ch(14,0);ch(13,1);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break; 
    case 3:ch(15,0);ch(14,0);ch(13,0);ch(12,1);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break; 
    case 4:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,1);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break;
    case 5:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,1);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break;
    case 6:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,1);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break;
    case 7:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,1);ch(7,0);ch(6,0);ch(5,0);ch(4,0);break;
    case 8:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,1);ch(6,0);ch(5,0);ch(4,0);break;
    case 9:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,1);ch(5,0);ch(4,0);break;
   case 10:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,1);ch(4,0);break;
   case 11:ch(15,0);ch(14,0);ch(13,0);ch(12,0);ch(11,0);ch(10,0);ch(9,0);ch(8,0);ch(7,0);ch(6,0);ch(5,0);ch(4,1);break;
  }}

void cl(){for(int i=0;i<10;i++){ch(anod[i],0);}for(int i=0;i<12;i++){ch(katod[i],0);}delayMicroseconds(100*BRIG);}  
void ch(int pin, int logic){digitalWrite(pin,logic);}  
void analyzeAudio() {
  for (int iu = 0 ; iu < FHT_N ; iu++) {
    int sample = analogRead(A0)*2;
    fht_input[iu] = 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
}

Comments

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

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