| Ваш IP: 54.163.20.123 | Online(40) - гости: 13, боты: 27 | Загрузка сервера: 0.44 ::::::::::::

Темброблок на TDA8425 (Arduino)

ИМС TDA8425 представляет собой двухканальный (стереофонический) регулятор громкости и тембра с микропроцессорным управлением.

Технические характеристики:

  • Производитель: Philips
  • Напряжение питания минимальное 7 В
  • Напряжение питания максимальное 13,2 В
  • Частотный диапазон 35…20000 Гц
  • Коэффициент гармоник 0,05%
  • Выходное напряжение максимальное 1 В
  • Регулировка громкости 48 уровней от -88 дБ до +6 дБ с шагом 2 дБ
  • Регулировка тембра НЧ  от -12 дБ до +15 дБ с шагом 3 дБ
  • Регулировка тембра ВЧ  от -12 дБ до +12 дБ с шагом 3 дБ
  • Регулировка баланса 8 дБ с шагом 2 дБ

 

Плата Arduino Nano аудиопроцессор TDA8425 обмениваются данными на шине I2C по линиям SDA (data — данные) и SCL (clock — синхронизация).

Темброблок имеет пять кнопок управления:

  • МЕНЮ — перебор параметров (громкость, баланс, тембр НЧ, тембр ВЧ, выбор канала)
  • ПЛЮС — прибавление громкости, тембра и др.
  • МИНУС  — уменьшение громкости, тембра и др.
  • MUTE — включение/выключение режима MUTE
  • — 20 дБ — при нажатии на кнопку громкость уменьшается на 20 дБ

Если кнопки регулировок «ПЛЮС» и «МИНУС» и кнопка «МЕНЮ» не были активны в течении 10 секунд, то происходит запись всех настроек в энергонезависимую память (функция EEPROM.update не перезаписывает ячейку памяти если значение переменной не менялось), так же происходит переход из режима регулировок тембра, баланса, выбора входа в режим регулировки громкости.

Если в режиме MUTE нет необходимости, то выход D9 необходимо подключить к GND.

  #include <Wire.h>
  #include <TDA8425.h>
  #include <LiquidCrystal.h>
  #include <EEPROM.h>//#include <EEPROMex.h>
  TDA8425 tda;
  LiquidCrystal lcd(7, 6, 2, 3, 4, 5);// RS,E,D4,D5,D6,D7
  byte a1[8]={0b00000,0b11011,0b11011,0b11011,0b11011,0b11011,0b11011,0b00000};
  byte a2[8]={0b00000,0b11000,0b11000,0b11000,0b11000,0b11000,0b11000,0b00000};
  int menu,vol_d,z,w,w1,bass_d,treb,treb_d,balans;
  byte vol,bass,in,mute=0;
  unsigned long time;
 
void setup(){
  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(12,INPUT);// меню
  pinMode(11,INPUT);// плюс
  pinMode(10,INPUT);// минус
  pinMode(9,INPUT);// mute
  pinMode(8,INPUT);// -20дБ
  lcd.createChar(0,a1); lcd.createChar(1,a2); 
  vol = EEPROM.read(0);// vol eeprom
  bass = EEPROM.read(1);// bass eeprom
  treb = EEPROM.read(2);// treb eeprom
  in = EEPROM.read(3);// in eeprom
  balans = EEPROM.read(4)-4;// balans eeprom
   audio();
  lcd.setCursor(4,0);lcd.print("TDA8425");delay(500);
 }
 
void loop(){
   if(digitalRead(12)==HIGH){menu++;mute=0;audio();cl();time=millis();w1=1;if(menu>4){menu=0;}}// меню
 
 // индикация громкости + управление кнопками //////////////
   if(menu==0){
   if(digitalRead(11)==HIGH){vol++;w=1;if(vol>63){vol=63;}}// 63 максимальная громкость = +6 дБ 
   if(digitalRead(10)==HIGH){vol--;w=1;if(vol<=16){vol=16;}}// 16 минимум громкости = -88 дБ
  lcd.setCursor(0,0);lcd.print("Volume    ");
  vol_d=vol*2-120;
   if(vol_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(vol_d>-10){{lcd.print(" ");}}
  lcd.print(abs(vol_d));lcd.print(" dB   ");
 // ползунок громкости начинает работать с -56 дБ
   if(vol-32>0){for(z=0;z<=vol-33;z++){lcd.setCursor(z/2,1);lcd.write((uint8_t)0);}}
   if((vol-32)%2==0&&vol-32>=0){lcd.setCursor(z/2,1);lcd.write((uint8_t)1);}
   if(w==1){audio();cl();time=millis();w1=1;w=0;}
 }
 ///////////////////////////////////////////////////////////
 
 // индикация баланс + управление кнопками +\- 8 дБ ///////
   if(menu==1){
   if(digitalRead(11)==HIGH){balans++;w=1;if(balans>4){balans=4;}}
   if(digitalRead(10)==HIGH){balans--;w=1;if(balans<-4){balans=-4;}}
  lcd.setCursor(0,0);
   if(balans*2>=0){lcd.print("-");}else{lcd.print("+");}
  lcd.print(abs(balans*2));lcd.print(" dB ");
  lcd.print(" <>  ");
   if(balans*2>=0){lcd.print("+");}else{lcd.print("-");}
  lcd.print(abs(balans*2));lcd.print(" dB ");
  lcd.setCursor(0,1);lcd.print("R");
  lcd.setCursor(15,1);lcd.print("L");
   if(balans<0){lcd.setCursor(balans+7,1);lcd.write((uint8_t)0);}
   if(balans>0){lcd.setCursor(balans+8,1);lcd.write((uint8_t)0);}
   if(balans==0){lcd.setCursor(7,1);lcd.write((uint8_t)0);lcd.setCursor(8,1);lcd.write((uint8_t)0);}
   if(w==1){audio();cl();time=millis();w1=1;w=0;}
 }
 /////////////////////////////////////////////////////////////
 
 // индикация тембр НЧ + управление кнопками //////////////
   if(menu==2){
   if(digitalRead(11)==HIGH){bass++;w=1;if(bass>11){bass=11;}}// 11 максимум тембр = +15 дБ 
   if(digitalRead(10)==HIGH){bass--;w=1;if(bass<2||bass==255){bass=2;}}// 2 минимум тембр = -12 дБ
  lcd.setCursor(0,0);lcd.print("Bass      ");
  bass_d=bass*3-18;
   if(bass_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(bass_d>-10&&bass_d<=0||bass_d<10&&bass_d>0){{lcd.print(" ");}}
  lcd.print(abs(bass_d));lcd.print(" dB   ");
   if(bass>1){for(z=3;z<=bass+1;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
   if(w==1){audio();cl();time=millis();w1=1;w=0;}
 }
 ///////////////////////////////////////////////////////////
 
 // индикация тембр ВЧ + управление кнопками //////////////
   if(menu==3){
   if(digitalRead(11)==HIGH){treb++;w=1;if(treb>10){treb=10;}}// 10 максимум тембр = +12 дБ 
   if(digitalRead(10)==HIGH){treb--;w=1;if(treb<2||treb==255){treb=2;}}// 2 минимум тембр = -12 дБ
  lcd.setCursor(0,0);lcd.print("Treble    ");
  treb_d=treb*3-18;
   if(treb_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(treb_d>-10&&treb_d<=0||treb_d<10&&treb_d>0){{lcd.print(" ");}}
  lcd.print(abs(treb_d));lcd.print(" dB   ");
   if(treb>1){for(z=3;z<=treb+1;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
   if(w==1){audio();cl();time=millis();w1=1;w=0;}
 }
 ///////////////////////////////////////////////////////////
 
 /////////// input /////////////////////////////////////////
   if(menu==4){
   if(digitalRead(11)==HIGH){in++;w=1;if(in>1&&in<255){in=0;}}
   if(digitalRead(10)==HIGH){in--;w=1;if(in>2){in=1;}}
  lcd.setCursor(0,0);lcd.print("Source selector");
  lcd.setCursor(0,1);lcd.print("Input: ");lcd.print(in);
   if(w==1){audio();cl();time=millis();w1=1;w=0;}
 }
////////////////////////////////////////////////////////////
 
////////////////// mute //////////////////////////////////
   if(digitalRead(9)==HIGH){mute++;if(mute>1){mute=0;}
   if(mute==1){menu=-1;}else{menu=0;}
  audio();cl();
  lcd.setCursor(6,0);lcd.print("MUTE");
 }
///////////////////////////////////////////////////////////
 
///////////////////  -20 dB ///////////////////////////////
   if(digitalRead(8)==HIGH){vol=vol-10;delay(500);audio();cl();}
//////////////////////////////////////////////////////////
 
// запись всех настроек в EEPROM если кнопки + и - не нажимались в течении 10 сек
// если настройки тембра, баланса и номер входа не менялись в течении 10 сек, переход в рег. Громкости
   if(millis()-time>10000 && w1==1){
     EEPROM.update(0,vol);
     EEPROM.update(4,balans+4);
     EEPROM.update(1,bass);
     EEPROM.update(2,treb);
     EEPROM.update(3,in);
  menu=0;w1=0;cl();
 }
}
 
void cl(){
  delay(200);
  lcd.clear();
 }
 
void audio(){
  tda.setVolumeL(vol+balans);
  tda.setVolumeR(vol-balans);
  tda.setBass(bass);
  tda.setTreble(treb);
  tda.setMute(mute);
  tda.setSource(in);
 }

Библиотеки

TDA8425.ZIP 

MsTimer2.ZIP

Encoder.zip


Следующий вариант темброблока аналогичен первому, только вместо кнопок управления «ПЛЮС» и «МИНУС» и  «МЕНЮ» применен энкодер.

В данном варианте регулятора тембра и громкости, меню разделено на две части, первое меню это настройка громкости и тембра, второе меню это настройка баланса и выбор источника сигнала. При нажатии на кнопку энкодера происходит перебор основных параметров (громкость и тембр), для того чтобы попасть во второе меню необходимо нажать и удерживать кнопку энкодера, при быстром пролистывании основных параметров появится меню настройки баланса, при повторном нажатии кнопки энкодера меню выбора источника сигнала.

Если энкодер не активен в течении 10 секунд происходит переход на регулировку громкости и запись всех настроек в энергонезависимую память.

  #include <Wire.h>
  #include <TDA8425.h>
  #include <Encoder.h>
  #include <LiquidCrystal.h>
  #include <EEPROM.h>//
 // #include <EEPROMex.h>
  #include <MsTimer2.h>
   Encoder myEnc(11, 10);//CLK, DT
   TDA8425 tda;
   LiquidCrystal lcd(7, 6, 2, 3, 4, 5);// RS,E,D4,D5,D6,D7
   byte a1[8]={0b00000,0b11011,0b11011,0b11011,0b11011,0b11011,0b11011,0b00000};
   byte a2[8]={0b00000,0b11000,0b11000,0b11000,0b11000,0b11000,0b11000,0b00000};
   int z,vol,vol_d,balans,bass,bass_d,treb,treb_d,in,mute,sss;
   byte menu,w1;
   long oldPosition  = -999,newPosition;
   unsigned long time;
 
   void to_Timer(){ //функция таймера
 newPosition = myEnc.read()/4;}
 
void setup() {
  Serial.begin(9600);
   lcd.begin(16, 2);
   pinMode(12,INPUT);// меню кнопка энкодера SW
   lcd.createChar(0,a1); lcd.createChar(1,a2); 
   vol = EEPROM.read(0);// vol eeprom
   bass = EEPROM.read(1);// bass eeprom
   treb = EEPROM.read(2);// treb eeprom
   in = EEPROM.read(3);// in eeprom
   balans = EEPROM.read(4)-4;// balans eeprom
   audio();
   lcd.setCursor(4,0);lcd.print("TDA8425");delay(500);
   MsTimer2::set(1, to_Timer);MsTimer2::start();
}
 
void loop() {
   if(digitalRead(12)==LOW&&menu<3){sss++;menu++;myEnc.write(0);oldPosition  = -999;delay(300);time=millis();w1=1;if(menu>2){menu=0;}if(sss>2){menu=3;delay(300);}}// меню
   if(digitalRead(12)==HIGH){sss=0;}
   if(menu==3&&digitalRead(12)==LOW&&sss==0){menu=4;oldPosition  = -999;delay(300);time=millis();w1=1;lcd.clear();}
   if(menu==4&&digitalRead(12)==LOW){menu=0;delay(300);lcd.clear();}
   ///////////////////////// громкость /////////////////////////////
   if(menu==0){
   if (newPosition != oldPosition) {
    oldPosition = newPosition;
    vol=vol+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(vol>63){vol=63;}if(vol<16){vol=16;}}
 
  lcd.setCursor(0,0);lcd.print("Volume    ");
  vol_d=vol*2-120;
   if(vol_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(vol_d>-10){{lcd.print(" ");}}
  lcd.print(abs(vol_d));lcd.print(" dB   ");
 // ползунок громкости начинает работать с -56 дБ
   if(vol-32>0){for(z=0;z<=vol-33;z++){lcd.setCursor(z/2,1);lcd.write((uint8_t)0);}}
   if((vol-32)%2==0&&vol-32>=0){lcd.setCursor(z/2,1);lcd.write((uint8_t)1);}
  audio();
  }
   ///////////////////////// баланс /////////////////////////////
  if(menu==3){
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    balans=balans+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(balans>4){balans=4;}if(balans<-4){balans=-4;}}
 
  lcd.setCursor(0,0);
   if(balans*2>=0){lcd.print("-");}else{lcd.print("+");}
  lcd.print(abs(balans*2));lcd.print(" dB ");
  lcd.print(" <>  ");
   if(balans*2>=0){lcd.print("+");}else{lcd.print("-");}
  lcd.print(abs(balans*2));lcd.print(" dB ");
  lcd.setCursor(0,1);lcd.print("L");
  lcd.setCursor(15,1);lcd.print("R");
   if(balans<0){lcd.setCursor(balans+7,1);lcd.write((uint8_t)0);}
   if(balans>0){lcd.setCursor(balans+8,1);lcd.write((uint8_t)0);}
   if(balans==0){lcd.setCursor(7,1);lcd.write((uint8_t)0);lcd.setCursor(8,1);lcd.write((uint8_t)0);}
  audio();
}
  ///////////////////////// тембр нч /////////////////////////////
  if(menu==1){
   if (newPosition != oldPosition) {
    oldPosition = newPosition;
    bass=bass+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(bass>11){bass=11;}if(bass<2){bass=2;}}
 
  lcd.setCursor(0,0);lcd.print("Bass      ");
  bass_d=bass*3-18;
   if(bass_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(bass_d>-10&&bass_d<=0||bass_d<10&&bass_d>0){{lcd.print(" ");}}
  lcd.print(abs(bass_d));lcd.print(" dB   ");
   if(bass>1){for(z=3;z<=bass+1;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
  audio();
 }
   ///////////////////////// тембр вч /////////////////////////////
  if(menu==2){
   if (newPosition != oldPosition) {
    oldPosition = newPosition;
    treb=treb+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(treb>11){treb=11;}if(treb<2){treb=2;}}
 
   if(treb>10){treb=10;}if(treb<2||treb==255){treb=2;}
  lcd.setCursor(0,0);lcd.print("Treble    ");
  treb_d=treb*3-18;
   if(treb_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(treb_d>-10&&treb_d<=0||treb_d<10&&treb_d>0){{lcd.print(" ");}}
  lcd.print(abs(treb_d));lcd.print(" dB   ");
   if(treb>1){for(z=3;z<=treb+1;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
  audio();
 }
  ///////////////////////// input /////////////////////////////
  if(menu==4){
if (newPosition != oldPosition) {
    oldPosition = newPosition;
    in=in+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(in>1){in=0;}if(in<0){in=1;}}
 
  lcd.setCursor(0,0);lcd.print("Source selector");
  lcd.setCursor(0,1);lcd.print("Input: ");lcd.print(in);
  audio();
 }
////////////////// mute //////////////////////////////////
   if(digitalRead(9)==HIGH){mute++;if(mute>1){mute=0;}
   if(mute==1){menu=-1;}else{oldPosition  = -999;menu=0;}
  audio(); delay(300);lcd.clear();
  lcd.setCursor(6,0);lcd.print("MUTE");
 }
///////////////////////////////////////////////////////////
 
///////////////////  -20 dB ///////////////////////////////
   if(digitalRead(8)==HIGH){vol=vol-10;delay(500);audio();myEnc.write(0);menu=0;lcd.clear();}
//////////////////////////////////////////////////////////
 
 
   if(millis()-time>10000 && w1==1){// сохранение всех настроек в eeprom через 60 сек неактивности
     myEnc.write(0);
     EEPROM.update(0,vol);
     EEPROM.update(4,balans+4);
     EEPROM.update(1,bass);
     EEPROM.update(2,treb);
     EEPROM.update(3,in);
     w1=0;menu=0;lcd.clear(); }
 
 }// loop
 
void audio(){
  tda.setVolumeL(vol+balans);
  tda.setVolumeR(vol-balans);
  tda.setBass(bass);
  tda.setTreble(treb);
  tda.setMute(mute);
  tda.setSource(in);
 }

Видео


Следующий скетч позволяет добавить анализатор спектра, при этом линейный входной сигнал необходимо  подать на вход А0. При неактивности кнопок управления и энкодера через 10 секунд происходит запись всех измененных параметров в энергонезависимую память и активация анализатора спектра, если нажать кнопку энкодера или покрутить его ручку анализатор спектра прекращает работать, и осуществляется переход в основное меню (громкость).

Дополнительно во второе меню (нажать и удерживать кнопку энкодера) добавлены настройки анализатора спектра:

  • AUTO_GAIN — автонастройка по громкости (0…1)
  • VOL_THR — порог тишины, ниже него отображения на экране не будет, это значение всегда должно быть быть меньше DEF_GAIN (10…100) (25-30 оптимально), параметр активен когда AUTO_GAIN = 1
  • LOW_PASS — нижний порог чувствительности шумов, нет скачков при отсутствии звука, это значение должно быть меньше DEF_GAIN (10..100) (35-40 оптимально)
  • DEF_GAIN — максимальный порог по умолчанию, это значение всегда должно быть выше VOL_THR и LOW_PASS (30…200)(80-120 оптимально), параметр активен когда AUTO_GAIN = 0
  • GRAPH_ATT — аттенюатор чувствительности (0,5…1,5), параметр активен когда AUTO_GAIN = 1
  • GRAPHICS — изменение вида графических полос (0…4)
  • Conv. speed — скорость преобразования для аналогового входа (чем больше значение тем более узкий частотный диапазон):
    • 0 — CLK/4
    • 1 — CLK/8 (оптимально)
    • 2  — CLK/16
    • 3  — CLK/32
    • 4  — CLK/64
    • 5  — CLK/128

Для перехода по параметрам настроек анализатора спектра необходимо нажимать кнопку MUTE.

Скетч не тестировался, возможно требутся правка кода.

Дополнительная билиотека FHT.ZIP

  #define FHT_N 256          // ширина спектра х2
  #define LOG_OUT 1
  #include <FHT.h>          
  #include <LiquidCrystal.h>
  #include <Wire.h>
  #include <TDA8425.h>
  #include <Encoder.h>
  #include <EEPROM.h>
 // #include <EEPROMex.h>
  #include <MsTimer2.h>
   LiquidCrystal lcd(7, 6, 2, 3, 4, 5);// RS,E,D4,D5,D6,D7
   Encoder myEnc(11, 10);//CLK, DT
   TDA8425 tda;
  // вручную забитый массив тонов, сначала плавно, потом круче
   byte posOffset[16] = {2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
   int AUTO_GAIN;    // автонастройка по громкости (экспериментальная функция)
   int VOL_THR;       // порог тишины (ниже него отображения на экране не будет)
   int LOW_PASS;        // нижний порог чувствительности шумов (нет скачков при отсутствии звука)
   int DEF_GAIN;     // максимальный порог по умолчанию (при GAIN_CONTROL игнорируется)
   unsigned long gainTimer,time;
   byte maxValue, maxValue_f,www,www1,spek,menu,w1,w2,y;
   float k = 0.1,k_usil;
   int z,vol,vol_d,balans,bass,bass_d,treb,treb_d,in,mute,sss,i,sp,graf,k_us,gain,i2,sped;
   long oldPosition  = -999,newPosition;
 
    void to_Timer(){ //функция таймера
    newPosition = myEnc.read()/4;}
 
void setup() { Serial.begin(9600);
  lcd.begin(16, 2);// LCD 16X2
  ADMUX  = 0b11100000; 
  //ADCSRA = 0b11110011;
   if(EEPROM.read(0)>100){ // используется толко один раз при первом запуске, если ячейка памяти для громкости вне диапазона регулирования
     EEPROM.update(0,40);  // установка всех настроек по умолчанию
     EEPROM.update(4,0);
     EEPROM.update(1,0);
     EEPROM.update(2,0);
     EEPROM.update(3,0);
     EEPROM.update(5,1);
     EEPROM.update(6,30);
     EEPROM.update(7,35);
     EEPROM.update(8,80);
     EEPROM.update(9,0);
     EEPROM.update(10,10);
     EEPROM.update(11,0);
   }
   pinMode(12,INPUT);// меню кнопка энкодера SW
   vol = EEPROM.read(0);// vol eeprom
   bass = EEPROM.read(1);// bass eeprom
   treb = EEPROM.read(2);// treb eeprom
   in = EEPROM.read(3);// in eeprom
   balans = EEPROM.read(4)-4;// balans eeprom
   AUTO_GAIN = EEPROM.read(5);
   VOL_THR = EEPROM.read(6);
   LOW_PASS = EEPROM.read(7);
   DEF_GAIN = EEPROM.read(8);
   graf = EEPROM.read(9);
   k_us = EEPROM.read(10);
   sped = EEPROM.read(11);
   audio();
   lcd.setCursor(4,0);lcd.print("TDA8425");delay(500);
   MsTimer2::set(1, to_Timer);MsTimer2::start();
}
 
void loop() {
  if(spek==1){
 
  if(www==1){
             if(graf==0){
             byte v1[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11011};
             byte v2[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11011, 0b11011};
             byte v3[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11011, 0b11011, 0b11011};
             byte v4[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b11011, 0b11011, 0b11011, 0b11011};
             byte v5[8] = {0b00000, 0b00000, 0b00000, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011};
             byte v6[8] = {0b00000, 0b00000, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011};
             byte v7[8] = {0b00000, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011};
             byte v8[8] = {0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011};
             lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);
             lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);
         }
             if(graf==1){
             byte v1[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01110};
             byte v2[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01110, 0b01110};
             byte v3[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01110, 0b01110, 0b01110};
             byte v4[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b01110, 0b01110, 0b01110, 0b01110};
             byte v5[8] = {0b00000, 0b00000, 0b00000, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110};
             byte v6[8] = {0b00000, 0b00000, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110};
             byte v7[8] = {0b00000, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110};
             byte v8[8] = {0b01110, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110};
             lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);
             lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);}
 
             if(graf==2){
             byte v1[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01010};
             byte v2[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01010, 0b01010};
             byte v3[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b01010, 0b01010, 0b01010};
             byte v4[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b01010, 0b01010, 0b01010, 0b01010};
             byte v5[8] = {0b00000, 0b00000, 0b00000, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010};
             byte v6[8] = {0b00000, 0b00000, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010};
             byte v7[8] = {0b00000, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010};
             byte v8[8] = {0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010, 0b01010};
             lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);
             lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);}
 
             if(graf==3){
             byte v1[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b10101};
             byte v2[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b10101, 0b10101};
             byte v3[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b10101, 0b10101, 0b10101};
             byte v4[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b10101, 0b10101, 0b10101, 0b10101};
             byte v5[8] = {0b00000, 0b00000, 0b00000, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101};
             byte v6[8] = {0b00000, 0b00000, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101};
             byte v7[8] = {0b00000, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101};
             byte v8[8] = {0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101};
             lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);
             lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);}
 
             if(graf==4){
             byte v1[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111};
             byte v2[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111};
             byte v3[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};
             byte v4[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111};
             byte v5[8] = {0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
             byte v6[8] = {0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
             byte v7[8] = {0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
             byte v8[8] = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
             lcd.createChar(0, v1);lcd.createChar(1, v2);lcd.createChar(2, v3);lcd.createChar(3, v4);
             lcd.createChar(4, v5);lcd.createChar(5, v6);lcd.createChar(6, v7);lcd.createChar(7, v8);}
  www=0;
  }
  analyzeAudio();   // функция FHT, забивает массив fht_log_out[] величинами по спектру
 
  for (int pos = 0; pos < 16; pos++) {   // для окошек дисплея с 0 по 15
    // найти максимум из пачки тонов
    if (fht_log_out[posOffset[pos]] > maxValue) maxValue = fht_log_out[posOffset[pos]];
 
    lcd.setCursor(pos, 0);
 
    // преобразовать значение величины спектра в диапазон 0..15 с учётом настроек
    int posLevel = map(fht_log_out[posOffset[pos]], LOW_PASS, gain, 0, 15);
    posLevel = constrain(posLevel, 0, 15);
  while(y<3){y++;
    if (posLevel > 7) {         // если значение больше 7 (значит нижний квадратик будет полный)
      lcd.write((uint8_t)posLevel - 8);    // верхний квадратик залить тем что осталось
      lcd.setCursor(pos, 1);          // перейти на нижний квадратик
      lcd.write((uint8_t)7);        // залить его полностью
  } 
    else {                             // если значение меньше 8
      lcd.print(" ");                 // верхний квадратик пустой
      lcd.setCursor(pos, 1);          // нижний квадратик
      lcd.write((uint8_t)posLevel);        // залить полосками
    }} y=0;
}
 
 
   k_usil=k_us;k_usil=k_usil*0.1;
  if (AUTO_GAIN==1) {
    maxValue_f = maxValue*k_usil * k + maxValue_f * (1 - k);
   if (millis() - gainTimer > 1500) {      // каждые 1500 мс
      // если максимальное значение больше порога, взять его как максимум для отображения
      if (maxValue_f > VOL_THR) gain = maxValue_f;
      // если нет, то взять порог побольше, чтобы шумы вообще не проходили
      else gain = 100;
      gainTimer = millis();
    }}else{gain=DEF_GAIN;
  }// spektr
  } 
 
   if(digitalRead(12)==LOW&&menu<3){sss++;if(spek==1){menu==0;}else{menu++;}www1=0;spek=0;myEnc.write(0);oldPosition  = -999;delay(300);time=millis();w1=1;if(menu>2){menu=0;}if(sss>2){menu=3;delay(300);}}// меню
   if(digitalRead(12)==HIGH){sss=0;}
   if(menu==3&&digitalRead(12)==LOW&&sss==0){menu=4;oldPosition  = -999;delay(300);time=millis();w1=1;lcd.clear();}
   if(menu==4&&digitalRead(12)==LOW&&sss==0){menu=5;oldPosition  = -999;delay(300);time=millis();w1=1;lcd.clear();}
   if(menu==5&&digitalRead(12)==LOW){menu=0;time=millis();w1=1;delay(300);lcd.clear();}
   if (newPosition != oldPosition&&spek==1) {oldPosition = newPosition;menu=0,www1=0;spek=0;w1=1;time=millis();lcd.clear();}
 
    if(spek==0){
      if(www1==0){byte a1[8]={0b00000,0b11011,0b11011,0b11011,0b11011,0b11011,0b11011,0b00000};
                  byte a2[8]={0b00000,0b11000,0b11000,0b11000,0b11000,0b11000,0b11000,0b00000};
                  lcd.createChar(0,a1); lcd.createChar(1,a2); www1=1; }
 
   ///////////////////////// громкость /////////////////////////////
   if(menu==0){
   if (newPosition != oldPosition) {
    oldPosition = newPosition;
    vol=vol+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(vol>63){vol=63;}if(vol<16){vol=16;}}
 
  lcd.setCursor(0,0);lcd.print("Volume    ");
  vol_d=vol*2-120;
   if(vol_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(vol_d>-10){{lcd.print(" ");}}
  lcd.print(abs(vol_d));lcd.print(" dB   ");
 // ползунок громкости начинает работать с -56 дБ
   if(vol-32>0){for(z=0;z<=vol-33;z++){lcd.setCursor(z/2,1);lcd.write((uint8_t)0);}}
   if((vol-32)%2==0&&vol-32>=0){lcd.setCursor(z/2,1);lcd.write((uint8_t)1);}
  audio();
  }
   ///////////////////////// баланс /////////////////////////////
  if(menu==3){
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    balans=balans+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(balans>4){balans=4;}if(balans<-4){balans=-4;}}
 
  lcd.setCursor(0,0);
   if(balans*2>=0){lcd.print("-");}else{lcd.print("+");}
  lcd.print(abs(balans*2));lcd.print(" dB ");
  lcd.print(" <>  ");
   if(balans*2>=0){lcd.print("+");}else{lcd.print("-");}
  lcd.print(abs(balans*2));lcd.print(" dB ");
  lcd.setCursor(0,1);lcd.print("L");
  lcd.setCursor(15,1);lcd.print("R");
   if(balans<0){lcd.setCursor(balans+7,1);lcd.write((uint8_t)0);}
   if(balans>0){lcd.setCursor(balans+8,1);lcd.write((uint8_t)0);}
   if(balans==0){lcd.setCursor(7,1);lcd.write((uint8_t)0);lcd.setCursor(8,1);lcd.write((uint8_t)0);}
  audio();
}
  ///////////////////////// тембр нч /////////////////////////////
  if(menu==1){
   if (newPosition != oldPosition) {
    oldPosition = newPosition;
    bass=bass+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(bass>11){bass=11;}if(bass<2){bass=2;}}
 
  lcd.setCursor(0,0);lcd.print("Bass      ");
  bass_d=bass*3-18;
   if(bass_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(bass_d>-10&&bass_d<=0||bass_d<10&&bass_d>0){{lcd.print(" ");}}
  lcd.print(abs(bass_d));lcd.print(" dB   ");
   if(bass>1){for(z=3;z<=bass+1;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
  audio();
 }
   ///////////////////////// тембр вч /////////////////////////////
  if(menu==2){
   if (newPosition != oldPosition) {
    oldPosition = newPosition;
    treb=treb+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(treb>11){treb=11;}if(treb<2){treb=2;}}
 
   if(treb>10){treb=10;}if(treb<2||treb==255){treb=2;}
  lcd.setCursor(0,0);lcd.print("Treble    ");
  treb_d=treb*3-18;
   if(treb_d>=0){lcd.print("+");}else{lcd.print("-");}
   if(treb_d>-10&&treb_d<=0||treb_d<10&&treb_d>0){{lcd.print(" ");}}
  lcd.print(abs(treb_d));lcd.print(" dB   ");
   if(treb>1){for(z=3;z<=treb+1;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
  audio();
 }
  ///////////////////////// input /////////////////////////////
  if(menu==4){
if (newPosition != oldPosition) {
    oldPosition = newPosition;
    in=in+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(in>1){in=0;}if(in<0){in=1;}}
 
  lcd.setCursor(0,0);lcd.print("Source selector");
  lcd.setCursor(0,1);lcd.print("Input: ");lcd.print(in);
  audio();
 }
///////////////////////////////////////////////////////////
 
  ///////////////////////// spectrum analyzer /////////////////////////////
  if(menu==5){  
    if(digitalRead(9)==HIGH){sp++;myEnc.write(0);oldPosition  = -999;delay(300);time=millis();if(sp>6){sp=0;}}
     lcd.setCursor(0,0);lcd.print("Spectrum analyzer");
if (newPosition != oldPosition) {
    oldPosition = newPosition;
    switch(sp){ w1=0;
    case 0: AUTO_GAIN=AUTO_GAIN+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(AUTO_GAIN>1){AUTO_GAIN=0;}if(AUTO_GAIN<0){AUTO_GAIN=1;};
    lcd.setCursor(0,1);lcd.print("AUTO_GAIN ");lcd.print(AUTO_GAIN);break;
    case 1: VOL_THR=VOL_THR+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(VOL_THR>100){VOL_THR=100;}if(VOL_THR<10){VOL_THR=10;};
    lcd.setCursor(0,1);lcd.print("VOL_THR ");lcd.print(VOL_THR);break;
    case 2: LOW_PASS=LOW_PASS+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(LOW_PASS>100){LOW_PASS=100;}if(LOW_PASS<10){LOW_PASS=10;};
    lcd.setCursor(0,1);lcd.print("LOW_PASS ");lcd.print(LOW_PASS);break;
    case 3: DEF_GAIN=DEF_GAIN+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(DEF_GAIN>200){DEF_GAIN=200;}if(DEF_GAIN<30){DEF_GAIN=30;};
    lcd.setCursor(0,1);lcd.print("DEF_GAIN ");lcd.print(DEF_GAIN);break;
    case 4: k_us=k_us+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(k_us>15){k_us=15;}if(k_us<5){k_us=5;}; k_usil=k_us;k_usil=k_usil*0.1;
    lcd.setCursor(0,1);lcd.print("GRAPH_ATT ");lcd.print(k_usil,1);break;
    case 5: graf=graf+newPosition;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(graf>4){graf=4;}if(graf<0){graf=0;};
    lcd.setCursor(0,1);lcd.print("GRAPHICS ");lcd.print(graf);break;
    case 6: sped=sped+newPosition;w2=0;myEnc.write(0);newPosition=0;audio();lcd.clear();time=millis();w1=1;if(sped>5){sped=5;}if(sped<0){sped=0;};
    lcd.setCursor(0,1);lcd.print("Conv. speed ");lcd.print(sped);break;
 
  }}}
 /////////////////////////////////////////////////////////////////////////
    }// spek = 0
  if(w2==0){
    switch(sped){
      case 0: ADCSRA = 0b11110010;break;
      case 1: ADCSRA = 0b11110011;break;
      case 2: ADCSRA = 0b11110100;break;
      case 3: ADCSRA = 0b11110101;break;
      case 4: ADCSRA = 0b11110110;break;
      case 5: ADCSRA = 0b11110111;break;
    }w2=1;}
 
////////////////// mute //////////////////////////////////
   if(digitalRead(9)==HIGH&&menu!=5){mute++;if(mute>1){mute=0;}
   if(mute==1){menu=-1;w1=0;spek=0;www1=0;}else{oldPosition  = -999;menu=0;}
  audio();delay(300);lcd.clear();
  lcd.setCursor(6,0);lcd.print("MUTE");
 }
///////////////////////////////////////////////////////////
 
///////////////////  -20 dB ///////////////////////////////
   if(digitalRead(8)==HIGH){vol=vol-10;delay(500);audio();myEnc.write(0);menu=0;lcd.clear();}
//////////////////////////////////////////////////////////
 
 
   if(millis()-time>10000 && w1==1){// сохранение всех настроек в eeprom через 60 сек неактивности
     //myEnc.write(0);
     EEPROM.update(0,vol);
     EEPROM.update(4,balans+4);
     EEPROM.update(1,bass);
     EEPROM.update(2,treb);
     EEPROM.update(3,in);
     EEPROM.update(5,AUTO_GAIN);
     EEPROM.update(6,VOL_THR);
     EEPROM.update(7,LOW_PASS);
     EEPROM.update(8,DEF_GAIN);
     EEPROM.update(9,graf);
     EEPROM.update(10,k_us);
     EEPROM.update(11,sped);
     w1=0;menu=0;lcd.clear();spek=1;www=1; sp=0;}
 
 }// loop
 
void audio(){
  tda.setVolumeL(vol+balans);
  tda.setVolumeR(vol-balans);
  tda.setBass(bass);
  tda.setTreble(treb);
  tda.setMute(mute);
  tda.setSource(in);  }
 
void analyzeAudio() {  
   cli(); 
 while( i < FHT_N ) {  i++; 
    do{ADCSRA |= (1 << ADSC);} 
    while((ADCSRA & (1 << ADIF)) == 0);
    fht_input[i] = (ADCL|ADCH << 8); 
    }i=0;
    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
   sei();
}

Комментарии

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

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

Случайные статьи

  • Простой испытатель кварцев

    Простой испытатель кварцев

    Схема испытателя кварцев состоит из генератора на VT1, детектора на диодах VD1 VD2 и усилителя постоянного тока на VT2. К устройству кварцевый резонатор подсоединяется при помощи зажимов. Если кварцевый резонатор исправен, то на R2 появляется ВЧ напряжение, которое затем поступает на диоды для детектирования. Выделенная постоянная составляющая открывает транзистор VT2, …Подробнее...
  • Простой АМ приемник на 2-х транзисторах

    Простой АМ приемник на 2-х транзисторах

    На рисунке показана схема простого АМ приемника состоящего всего из двух транзисторов. Транзистор VT1 работает как ВЧ-усилитель с обратной связью и как демодулятор одновременно. Чувствительность приемника зависит от величины обратной связи и может быть отрегулирована при помощи потенциометра VР1. VT2 используется как усилитель НЧ. Катушки антенный намотаны на ферритовом стержне …Подробнее...
  • Мостовой усилитель на базе TDA7374B

    Мостовой усилитель на базе TDA7374B

    Усилитель на базе TDA7374B относится к классу АВ и используется в автомобильных аудиосистемах. Микросхема имеет защиту от перенапряжения, переполюсовки, тепловую, защиту от статического электричества, защиту от КЗ выходов на шину питания и корпус. Так же имеется встроенная система STAND-BY и MUTE. Усилитель на базе TDA7374B имеет следующие характеристики: Номинальное напряжение …Подробнее...
  • Индикатор уровня

    Индикатор уровня

    Очень простая схема индикации уровня на 10-и светодиодах представлена на рис.. микросхема которая используется в данной схеме обладает коэф. усиления — 1. С помощью переключателя S1, мы можем выбрать индикации. Уровень водного сигнала от 60 мВ до 1,25 В. Элементная база R1-2=10Kohm D11-12=1N 4148 S1= mini switch R3-4=1Kohm C1=10uF 25V …Подробнее...
  • Усилитель мощности для СВ-радиостанции (27МГц)

    Данный усилитель мощности предназначен для эксплуатации носимой радиостанции в стационарном режиме. При этом сигнал с ее выхода поступает на вход усилителя через коаксиальный кабель. Мощность носимой радиостанции при входном сопротивлении 50 Ом усилителя мощности составляет 1-2Вт. Данный усилитель мощности развивает мощность до 30-40Вт. выход рассчитан на 75-омную антенну. Схема усилителя …Подробнее...