ИМС 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
Дополнительные материалы:
купил у китайцев такую штуку блок питания с енкодерами, после второго включения сдохла мега8,напрочь, искал долго нашел прошивку под кнопки и похожую схему,(больше ничего не нашел) автор писал, что содрал с этого устройства, работает криво(почти не работает).Забросил, уже долго валяеца. Можна написать для этого БП на мегу8. Что для этого нужно. А я постараюсь срисовать схему и выложить у вас.
Но это не срочно, на недалекое будущее.
Схему посмотреть можно конечно, что из этого выйдет не знаю, в ARDUINO IDE можно написать скетч под МЕГУ (уже делал) и скомпилировать hex. Главное понять как работает плата БП.
Добрый вечер. Я еще учусь, будьте снисходительны.
Запустил ардуино с TDA8425. Идет некоторрое время самостоятельный перебор меню, затем все виснет. Подскажите пож. возможную причину. Заранее благодарен.
а можна шоб все коментарии на LCD были по русски
под какой пульт сделали код ?
желательно RC5
телевизионный у меня их 2 ведра
http://forum.rcl-radio.ru/viewtopic.php?id=59
Такой вопрос — при *-20 dB* вычитается от текущего. Если несколько раз подряд нажимать, то уходит хрен знает куда, потом резко на максимальную громкость.
Нужен ведь триггер, что бы при следующем нажатии был возврат на прежнию позицию.
это в обоих скетчах.
что поменять что бы был тригер -20дб?
Исправил, не тестировал, но должно работать как надо. При повторном нажатии на кнопку -20дБ уровень громкости возвращается в исходное состояние.
Теперь как надо, спасибо за оперативность
Добрый вечер. Я еще учусь, будьте снисходительны.
Запустил ардуино с TDA8425. Идет некоторрое время самостоятельный перебор меню, затем все виснет. Подскажите пож. возможную причину. Заранее благодарен.
Проверьте энкодер, на платке энкодера должно быть установлено 3 резистора по 10 К
Стоит реально 2 резистора и одно место пустое c обозначениеv R1
Огромное спасибо. Все заработало.
Здравствуйте! Собрал всё работает отлично . Но есть проблема с энкодером . При вращении , он перелистывает меню. Подскажите пожалуйста что может быть ?
Проверьте кнопку энкодера, при вращении она нажимается. Осмотрите платку энкодера на предмет замыкания.
Проверил, при вращении тестер, не показывает замыкания контактов .
фото платки
А если нажать на кнопку энкодера , то на экране быстро перелистываются вес режимы, секунды три , и останавливается
Выводы энкодера CLK, DT и SW имеют подтяжку к +5В через резисторы 10К?
Уточните какой скетч?
Да,3 резистора 10 K , скетч второй , там где вместо кнопок применен энкодер
А если нажать на кнопку энкодера , то на экране быстро перелистываются вес режимы, секунды три , и останавливается
—
происходит зависание контроллера?
нет , работает дальше без проблем . уже проверил всё только можно ))) первая моя работа с ардуино .