ИМС 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
Дополнительные материалы:
померял сейчас напряжение на SW 5v ? но не меняется что при нажатии что при выключении .
при подаче 5 v , меню переключается
Кнопка энкодера неисправна
при подаче 5 v , меню переключается .точно , странно всё )))
попробую поставить другой энкодер
Финал : Поменял 3 энкодера , выводил отдельную кнопку . и другие танцы с бубном )) В Итоге помог резистор 10K между SW и + ? стало работать как и положено .Спасибо за помощь !
подскажите не могу загрузить ни один скетч
TDA8425 + энкодер + пульт + STANDBY а к этому можно добавить анализатор? , или к схеме с анализатором добавить пульт.
Проект давно завершен, каких то изменений или переделок не предвидеться.
Собрал вариант энкодером, отлично работает. Спасибо автору за титанический труд!
Появилась идея русифицировать дисплей 1602, чтобы громкость была громкостью и т.д. Использовал библиотеку «LCD_1602_RUS_ALL». Примеры из библиотеки работают, но когда прописываю библиотеку в скейте на TDA8425, компилятор «ругается матом». Как подружить библиотеку и скетч?
Не получится, в LCD1602 есть 8 байт для создания произвольных символов, библиотека LCD_1602_RUS_ALL использует их, но так же и скетч использует их для создания полосок уровней.
Спасибо.
how to fix this error please help me
44444:12:22: error: invalid prefix «0b» for floating constant
byte a2 [ 8 ] = { 0b00000.0b11000.0b11000.0b11000.0b11000.0b11000.0b11000.0b00000 } ;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D:\5.1 PCB\5.1__cord\44444\44444.ino: In function ‘void loop()’:
44444:49:17: error: expected primary-expression before ‘=’ token
if ( vol_d > = 0 ) { lcd. print ( «+» ) ; } else { lcd. print ( «-» ) ; }
^
44444:53:43: error: expected primary-expression before ‘=’ token
if ( vol- 32 > 0 ) { for ( z = 0 ; z = 0 ) { lcd. setCursor ( z / 2 , 1 ) ; lcd. write ( ( uint8_t ) 1 ) ; }
^
44444:59:21: error: expected ‘)’ before ‘!’ token
if ( newPosition ! = oldPosition ) {
^
44444:64:22: error: expected primary-expression before ‘=’ token
if ( balans * 2 > = 0 ) { lcd. print ( «-» ) ; } else { lcd. print ( «+» ) ; }
^
44444:67:22: error: expected primary-expression before ‘=’ token
if ( balans * 2 > = 0 ) { lcd. print ( «+» ) ; } else { lcd. print ( «-» ) ; }
^
44444:78:22: error: expected ‘)’ before ‘!’ token
if ( newPosition ! = oldPosition ) {
^
44444:84:18: error: expected primary-expression before ‘=’ token
if ( bass_d > = 0 ) { lcd. print ( «+» ) ; } else { lcd. print ( «-» ) ; }
^
44444:85:35: error: expected primary-expression before ‘=’ token
if ( bass_d > — 10 && bass_d < = 0 || bass_d 0 ) { { lcd. print («» ) ; } }
^
44444:87:40: error: expected primary-expression before ‘=’ token
if ( bass > 1 ) { for ( z = 3 ; z = 0 ) { lcd. print ( «+» ) ; } else { lcd. print ( «-» ) ; }
^
44444:100:35: error: expected primary-expression before ‘=’ token
if ( treb_d > — 10 && treb_d < = 0 || treb_d 0 ) { { lcd. print («» ) ; } }
^
44444:102:40: error: expected primary-expression before ‘=’ token
if ( treb > 1 ) { for ( z = 3 ; z < = treb + 1 ; z ++ ) { lcd. setCursor ( z, 1 ) ; lcd. write ( ( uint8_t ) 0 ) ; } }
^
44444:107:19: error: expected ')' before '!' token
if ( newPosition ! = oldPosition ) {
^
D:\5.1 PCB\5.1__cord\44444\44444.ino: In function 'void setup()':
44444:147:8: error: redefinition of 'void setup()'
}void setup() {
^~~~~
D:\5.1 PCB\5.1__cord\44444\44444.ino:21:6: note: 'void setup()' previously defined here
void setup ( ) {
^~~~~
D:\5.1 PCB\5.1__cord\44444\44444.ino: In function 'void loop()':
44444:152:6: error: redefinition of 'void loop()'
void loop() {
^~~~
D:\5.1 PCB\5.1__cord\44444\44444.ino:36:6: note: 'void loop()' previously defined here
void loop ( ) {
^~~~
exit status 1
invalid prefix "0b" for floating constant
The code was not copied correctly, select the language-Russian