ИМС 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,db; 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&&db==0){vol=vol-10;db=1;delay(500);audio();cl();} if(digitalRead(8)==HIGH&&db==1){vol=vol+10;db=0;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
Следующий вариант темброблока аналогичен первому, только вместо кнопок управления «ПЛЮС» и «МИНУС» и «МЕНЮ» применен энкодер.
В данном варианте регулятора тембра и громкости, меню разделено на две части, первое меню это настройка громкости и тембра, второе меню это настройка баланса и выбор источника сигнала. При нажатии на кнопку энкодера происходит перебор основных параметров (громкость и тембр), для того чтобы попасть во второе меню необходимо нажать и удерживать кнопку энкодера, при быстром пролистывании основных параметров появится меню настройки баланса, при повторном нажатии кнопки энкодера меню выбора источника сигнала.
Если энкодер не активен в течении 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,db; 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;lcd.clear();time=millis();w1=1;if(vol>63){vol=63;}if(vol<16){vol=16;}audio();} 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(menu==3){ if (newPosition != oldPosition) { oldPosition = newPosition; balans=balans+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(balans>4){balans=4;}if(balans<-4){balans=-4;}audio();} 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);} } ///////////////////////// тембр нч ///////////////////////////// if(menu==1){ if (newPosition != oldPosition) { oldPosition = newPosition; bass=bass+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(bass>11){bass=11;}if(bass<2){bass=2;}audio();} 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(menu==2){ if (newPosition != oldPosition) { oldPosition = newPosition; treb=treb+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(treb>11){treb=11;}if(treb<2){treb=2;}audio();} 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);}} } ///////////////////////// input ///////////////////////////// if(menu==4){ if (newPosition != oldPosition) { oldPosition = newPosition; in=in+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(in>1){in=0;}if(in<0){in=1;}audio();} lcd.setCursor(0,0);lcd.print("Source selector"); lcd.setCursor(0,1);lcd.print("Input: ");lcd.print(in); } ////////////////// 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&&db==0){vol=vol-10;db=1;delay(500);audio();myEnc.write(0);menu=0;lcd.clear();} if(digitalRead(8)==HIGH&&db==1){vol=vol+10;db=0;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,db; 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;lcd.clear();time=millis();w1=1;if(vol>63){vol=63;}if(vol<16){vol=16;}audio();} 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(menu==3){ if (newPosition != oldPosition) { oldPosition = newPosition; balans=balans+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(balans>4){balans=4;}if(balans<-4){balans=-4;}audio();} 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);} } ///////////////////////// тембр нч ///////////////////////////// if(menu==1){ if (newPosition != oldPosition) { oldPosition = newPosition; bass=bass+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(bass>11){bass=11;}if(bass<2){bass=2;}audio();} 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(menu==2){ if (newPosition != oldPosition) { oldPosition = newPosition; treb=treb+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(treb>11){treb=11;}if(treb<2){treb=2;}audio();} 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);}} } ///////////////////////// input ///////////////////////////// if(menu==4){ if (newPosition != oldPosition) { oldPosition = newPosition; in=in+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w1=1;if(in>1){in=0;}if(in<0){in=1;}audio();} lcd.setCursor(0,0);lcd.print("Source selector"); lcd.setCursor(0,1);lcd.print("Input: ");lcd.print(in); } /////////////////////////////////////////////////////////// ///////////////////////// 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&&db==0){vol=vol-10;db=1;delay(500);audio();myEnc.write(0);menu=0;lcd.clear();} if(digitalRead(8)==HIGH&&db==1){vol=vol+10;db=0;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(); }
- tda8425_01.zip — основное меню: громкость, тембр, баланс, выбор входа, в дополнительном меню настройки только анализатора спектра.
TDA8425 + энкодер + пульт + STANDBY — http://forum.rcl-radio.ru/viewtopic.php?id=57
TDA8425 + энкодер + пульт + STANDBY + часы(DS3231) — http://forum.rcl-radio.ru/viewtopic.php?id=59
Дополнительные материалы:
Как при переключении входа (с 0 на 1), реализовать подключение анализатора спектра к этому же входу?
Походу ни как. Надо использовать второй аналоговый вход для второго канала и переключать его в зависимости какой INPUT работает.
ADMUX = 0b11100000; = активен А0
ADMUX = 0b11100001; = активен А1
Если добавить в обработчик переключения входа (последние 4 строки), будет работать?
///////////////////////// 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;}
if(in==1)
{ADMUX = 0b11100001;}
else
{ADMUX = 0b11100000;}
}
будет
Соединять входа так?
да
Проблемка возникла, переключает все меню в произвольном порядке, то есть ничего не трогая он листает настройки, как бороться с этим?
Если используете энкодер то проверьте наличие 3-х подтягивающих резистора по 10 К на платке энкодера.
Энкодер собирался отдельно, резисторы 3 штуки есть
Померьте напряжение на D12, должно быть 5 В, если кнопка энкодера не нажата.
На D12 ничего нет при нажатие прозванивается на землю, D10 и D11 выходит по 5 вольт
Так же при нажатие энкодера прозванивается на землю
Если стоит резистор , то при не нажатой кнопке SW должно быть 5 В
Пока экспериментировал выпаял его, сейчас запаял 5В на D12 есть
https://youtube.com/shorts/2DPQIvnRTZA
Опубликуйте код который Вы используете в теме — http://forum.rcl-radio.ru/viewforum.php?id=4
Код использую последний из этой темы
Всё заработало, попробовал ещё раз прошить её и всё заработало, спасибо Вам большое.
Здравствуйте! Не могу разобраться, что поменять в коде, чтоб в режиме input на экран выводилось не 0 или 1, слово, например AUX,BT
lcd.setCursor(0,1);lcd.print(«Input: «);lcd.print(in);
Примерно так:
lcd.setCursor(0,1);lcd.print(«Input: «);
switch(in){
case 0: lcd.print(«AUX1»);break;
case 1: lcd.print(«AUX2»);break;
}
liman28 подскажи пожалуйста по http://rcl-radio.ru/?p=82457&cpage=2#comments . там писал но ты не отвечаешь. проект вроде твой. не могу найти как тебе написать в личку