Тема: Разработка TDA7317+TDA7439+LCD1602_i2C+ENCODER+IR
http://rcl-radio.ru/wp-content/uploads/ … DA7439.gif
Так как предусмотрена управляемая яркость подсветки дисплея, то можно установить яркость подсветки в основном режиме и в режиме STANDBY (как правило с пониженной яркостью подсветки), регулировка яркости подсветки осуществляется через скетч:
#define BRIG_H 200 // Яркость 0…255 POWER ON
#define BRIG_L 50 // Яркость 0…255 POWER OFF
Подсветка — убрать перемычку с модуля I2C PCF8574 и подключить вывод модуля к цифровому выходу Arduino D6. Перед подключением замерить ток подсветки который не должен превышать 20 мА (у моего модуля ток не более 15 мА, замер производить между контактами перемычки).
Максимальный выходной ток одного выхода Arduino Nano не должен превышать 40 мА (рекомендуется не более 20 мА).
Регулировка эквалайзера - перейти в меню эквалайзера, для выбора полосы нажимать кнопку IN
#define BRIG_H 200 // Яркость 0...255 POWER ON
#define BRIG_L 50 // Яркость 0...255 POWER OFF
#define IR_1 0x2FDD02F // Кнопка вверх
#define IR_2 0x2FD32CD // Кнопка вниз
#define IR_3 0x2FD906F // Кнопка >
#define IR_4 0x2FDF20D // Кнопка <
#define IR_5 0x2FD6A95 // Кнопка IN
#define IR_6 0x2FDEA15 // Кнопка MUTE
#define IR_7 0x2FD00FF // Кнопка STANDBY (POWER)
#define CLK 9 // ENCODER
#define DT 8 // ENCODER
#define SW 10 // ENCODER
#include <Wire.h>
#include <EEPROM.h>
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <boarddefs.h> // входит в состав библиотеки IRremote
#include <IRremote.h> // http://rcl-radio.ru/wp-content/uploads/2019/06/IRremote.zip
#include <TDA7439.h> // http://rcl-radio.ru/wp-content/uploads/2019/01/TDA7439.zip
#include <TDA7317.h> // https://github.com/liman324/TDA7317.git
TDA7439 tda;
TDA7317 tda1;
Encoder myEnc(CLK, DT);
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
IRrecv irrecv(12); // указываем вывод модуля IR приемника
decode_results ir;
int menu,in,gain,vol,balans,band1,band2,band3,band4,band5,a[3],q[5],qqq[5],qi,qq,chl,chr;
int gain0,gain1,gain2,gain3,gain4,times_in,vol_old;
unsigned long times,times1,oldPosition = -999,newPosition;
byte m0=1,m1,i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
bool w,w2,gr1,gr2,power,www,in_x,mute;
void setup() {
Serial.begin(9600);Wire.begin();irrecv.enableIRIn();
MsTimer2::set(1, to_Timer);MsTimer2::start();
if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
pinMode(A0,INPUT_PULLUP); // MUTE
pinMode(A1,INPUT_PULLUP); // INPUT
pinMode(A2,INPUT_PULLUP); // POWER
pinMode(SW,INPUT); // BUTTON SW ENCODER
pinMode(6,OUTPUT); // ВЫХОД УПРАВЛЕНИЯ ПОДСВЕТКОЙ
pinMode(7,OUTPUT); // ВЫХОД УПРАВЛЕНИЯ STANDBY
analogWrite(6, BRIG_H);// больше 200 не делать
vol = EEPROM.read(0);in = EEPROM.read(1);
gain1 = EEPROM.read(2);gain2 = EEPROM.read(3);gain3 = EEPROM.read(4);gain4 = EEPROM.read(5);
balans = EEPROM.read(6)-4;
q[0] = EEPROM.read(7)-100;q[1] = EEPROM.read(8)-100;q[2] = EEPROM.read(9)-100;q[3] = EEPROM.read(10)-100;q[4] = EEPROM.read(11)-100;
lcd.init();lcd.backlight();
lcd.setCursor(5,0);lcd.print("TDA7439");
lcd.setCursor(5,1);lcd.print("TDA7317");
delay(1000);
switch(in){
case 1: gain0 = gain1;break;
case 2: gain0 = gain2;break;
case 3: gain0 = gain3;break;
case 4: gain0 = gain4;break;
}
audio();cl();
}
void loop() {
if(power==1){digitalWrite(7,LOW);}else{digitalWrite(7,HIGH);}
if ( irrecv.decode( &ir )) {Serial.print("0x");Serial.println( ir.value,HEX);irrecv.resume();times=millis();w=1;w2=1;}// IR приемник - чтение, в мониторе порта отображаются коды кнопок
if(ir.value==0){gr1=0;gr2=0;}// запрет нажатий не активных кнопок пульта
if(m0==1){m0=0;
byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};
byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);}
if(m1==1){m1=0;
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(power==0){
/// MENU //////////////////////////////
if(digitalRead(SW)==LOW){menu++;if(menu>2){menu=0;};switch(menu){case 0: m0=1;break;case 1: m1=1;break;case 2: m0=1;break;}delay(200);lcd.clear();w=1;w2=1;times=millis();w2=1;}
if(ir.value==IR_1){menu++;gr1=0;gr2=0;cl1();times=millis();w=1;w2=1;if(menu>2){menu=0;};switch(menu){case 0: m0=1;break;case 1: m1=1;break;case 2: m0=1;break;}delay(200);lcd.clear();w=1;w2=1;times=millis();w2=1;}
if(ir.value==IR_2){menu--;gr1=0;gr2=0;cl1();times=millis();w=1;w2=1;if(menu<0){menu=2;};switch(menu){case 0: m0=1;break;case 1: m1=1;break;case 2: m0=1;break;}delay(200);lcd.clear();w=1;w2=1;times=millis();w2=1;}
/// INPUT ////////////////////////////
if((digitalRead(A1)==LOW||ir.value==IR_5)&&menu!=1){in++;gr1=0;gr2=0;if(in>4){in=1;}menu=100;w=1;w2=1;in_x=1;times=millis();cl();delay(200);}
/// MUTE //////////////////////////////
if((digitalRead(A0)==LOW||ir.value==IR_6)&&mute==0){mute=1;gr1=0;gr2=0;menu=100;cl();lcd.setCursor(6,0);lcd.print("MUTE");vol_old=vol;vol=0;audio();}
if((digitalRead(A0)==LOW||ir.value==IR_6)&&mute==1){mute=0;gr1=0;gr2=0;menu=0;m0=1;cl();w2=1;vol=vol_old;audio();}
}
/// POWER /////////////////////////////
if((ir.value==IR_7||digitalRead(A2)==LOW)&&power==0){power=1;cl();lcd.setCursor(3,0);lcd.print("POWER OFF");menu=100;m0=1;
vol_old=vol;vol=0;audio();delay(3000);analogWrite(6,BRIG_L);}// power off
if((ir.value==IR_7||digitalRead(A2)==LOW)&&power==1){power=0;analogWrite(6, BRIG_H);cl();lcd.setCursor(3,0);lcd.print("POWER ON ");
vol=vol_old;audio();w2=1;w=1;menu=0;m0=1;myEnc.write(0);delay(2000);cl();}// power on
/// VOLUME ///////////////////////////////////////////////////
if(menu==0){
if(ir.value==IR_3){vol++;gr1=1;gr2=0;cl1();times=millis();w=1;w2=1;vol_conf();audio();}// кнопка >
if(ir.value==0xFFFFFFFF and gr1==1){vol++;gr2=0;cl1();times=millis();w=1;w2=1;vol_conf();audio();}// кнопка >>>>>>
if(ir.value==IR_4){vol--;gr1=0;gr2=1;cl1();times=millis();w=1;w2=1;vol_conf();audio();}// кнопка <
if(ir.value==0xFFFFFFFF and gr2==1){vol--;gr1=0;cl1();times=millis();w=1;w2=1;vol_conf();audio();}// кнопка <<<<<<
if (newPosition != oldPosition){oldPosition = newPosition;
vol=vol+newPosition;myEnc.write(0);newPosition=0;w=1;times=millis();w2=1;vol_conf();audio();}
lcd.setCursor(0,0);lcd.print("VOLUME ");
lcd.setCursor(0,1);lcd.print("INPUT ");lcd.print(in);
if(w2==1){w2=0;
a[0]=(vol)/10;a[1]=(vol)%10;
for(int i=0;i<2;i++){
switch(i){
case 0: e1=9,e2=10,e3=11;break;
case 1: e1=12,e2=13,e3=14;break;
}
switch(a[i]){
case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
}
lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
}}
}
// Equalizer /////////////////////////////////////
if(menu==1){
if(digitalRead(A1)==LOW||ir.value==IR_5){qi++;gr1=0;gr2=0;ir.value=0;if(qi>4){qi=0;}w=1;w2=1;delay(300);}
switch(qi){
case 0: qq=q[0];break;
case 1: qq=q[1];break;
case 2: qq=q[2];break;
case 3: qq=q[3];break;
case 4: qq=q[4];break;
}
if(ir.value==IR_3){qq++;gr1=1;gr2=0;cl1();times=millis();www=1;w=1;w2=1;eq_conf();}// кнопка >
if(ir.value==0xFFFFFFFF and gr1==1){qq++;gr2=0;cl1();times=millis();www=1;w=1;w2=1;eq_conf();}// кнопка >>>>>>
if(ir.value==IR_4){qq--;gr1=0;gr2=1;cl1();times=millis();www=1;w=1;w2=1;eq_conf();}// кнопка <
if(ir.value==0xFFFFFFFF and gr2==1){qq--;gr1=0;cl1();times=millis();www=1;w=1;w2=1;eq_conf();}// кнопка <<<<<<
if (newPosition != oldPosition){oldPosition = newPosition;
qq=qq+newPosition;myEnc.write(0);newPosition=0;w=1;times=millis();w2=1;eq_conf();www=1;}
if(www==1){www=0;q[qi]=qq;audio();}
for (int pos = 0; pos < 5; pos++) {lcd.setCursor(pos, 0);
qqq[pos] = map(q[pos],-7,7,0,15);
if (qqq[pos] > 7){lcd.write((uint8_t)qqq[pos] - 8);lcd.setCursor(pos, 1);lcd.write((uint8_t)7);}
else {lcd.print(" ");lcd.setCursor(pos, 1);lcd.write((uint8_t)qqq[pos]);}}
lcd.setCursor(7,0);lcd.print("F ");
switch(qi){
case 0: lcd.print("60 Hz");break;
case 1: lcd.print("260 Hz");break;
case 2: lcd.print("1 kHz");break;
case 3: lcd.print("3 kHz");break;
case 4: lcd.print("10 kHz");break;
}
lcd.setCursor(7,1);lcd.print("G ");lcd.print(q[qi]*2);lcd.print(" dB ");
}
//////// BALANCE ///////////////////////////////////////////////////////////////
if(menu==2){
if(ir.value==IR_3){balans++;gr1=1;gr2=0;cl1();times=millis();www=1;w=1;w2=1;ball_fun();}// кнопка >
if(ir.value==0xFFFFFFFF and gr1==1){balans++;gr2=0;cl1();times=millis();www=1;w=1;w2=1;ball_fun();}// кнопка >>>>>>
if(ir.value==IR_4){balans--;gr1=0;gr2=1;cl1();times=millis();www=1;w=1;w2=1;ball_fun();}// кнопка <
if(ir.value==0xFFFFFFFF and gr2==1){balans--;gr1=0;cl1();times=millis();www=1;w=1;w2=1;ball_fun();}// кнопка <<<<<<
if (newPosition != oldPosition){oldPosition = newPosition;
balans=balans-newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;ball_fun();www=1;
}
if(www==1){www=0;audio();}
lcd.setCursor(4,0);lcd.print(F(" <> "));lcd.setCursor(4,1);lcd.print(F("CHL CHR"));
chl=(4+balans)-4;chr=(4-balans)-4;
if(chl<0){lcd.setCursor(12,0);chl=abs(chl);lcd.write((uint8_t)3);}else{lcd.setCursor(12,0);lcd.print(" ");}
if(chr<0){lcd.setCursor(0,0);chr=abs(chr);lcd.write((uint8_t)3);}else{lcd.setCursor(0,0);lcd.print(" ");}
if(w2==1){w2=0;a[0]=chl;a[1]=chr;
for(int i1=0;i1<2;i1++){
switch(i1){
case 0: e1=1,e2=2,e3=3;break;
case 1: e1=13,e2=14,e3=15;break;
}
switch(a[i1]){
case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
}
lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
}}}
////////////////////////// GAIN IN /////////////////////////////////////////////////////////////////////////////////////
if(in_x==1){ menu=100;
switch(in){
case 1: gain0 = gain1;break;
case 2: gain0 = gain2;break;
case 3: gain0 = gain3;break;
case 4: gain0 = gain4;break;
}
if(ir.value==IR_3){gain0++;gr1=1;gr2=0;cl1();times=millis();www=1;w=1;gain_func();}// кнопка >
if(ir.value==0xFFFFFFFF and gr1==1){gain0++;gr2=0;cl1();times=millis();www=1;w=1;gain_func();}// кнопка >>>>>>
if(ir.value==IR_4){gain0--;gr1=0;gr2=1;cl1();times=millis();www=1;w=1;gain_func();}// кнопка <
if(ir.value==0xFFFFFFFF and gr2==1){gain0--;gr1=0;cl1();times=millis();www=1;w=1;gain_func();}// кнопка <<<<<<
if (newPosition != oldPosition) {oldPosition = newPosition;
gain0=gain0+newPosition;myEnc.write(0);newPosition=0;times=millis();www=1;w=1;gain_func();}
switch(in){
case 1: gain1 = gain0;break;
case 2: gain2 = gain0;break;
case 3: gain3 = gain0;break;
case 4: gain4 = gain0;break;
}
if(www==1){www=0;audio();}
lcd.setCursor(3,0);lcd.print("INPUT ");lcd.print(in);lcd.setCursor(3,1);lcd.print("GAIN ");lcd.print(gain0);lcd.print(" dB ");
}
//// EEPROM ///////////////////////////////////////
if(in_x==1){times_in=3000;}else{times_in=10000;}
if(millis()-times>times_in && w==1 && power==0 && mute==0){w=0;in_x=0;EEPROM.update(0,vol);EEPROM.update(1,in);
EEPROM.update(2,gain1);EEPROM.update(3,gain2);EEPROM.update(4,gain3);EEPROM.update(5,gain4);
EEPROM.update(6,balans+4);
EEPROM.update(7,q[0]+100);EEPROM.update(8,q[1]+100);EEPROM.update(9,q[2]+100);EEPROM.update(10,q[3]+100);EEPROM.update(11,q[4]+100);
menu=0;cl();m0=1;w2=1;
}
} // END LOOP
void gain_func(){if(gain0<0){gain0=0;}if(gain0>15){gain0=15;}}
void ball_fun(){if(balans>4){balans=4;}if(balans<-4){balans=-4;}}
void eq_conf(){if(qq>7){qq=7;}if(qq<-7){qq=-7;}}
void vol_conf(){if(vol>48){vol=48;} if(vol<0){vol=0;}}
void cl(){ir.value=0;delay(300);lcd.clear();}
void cl1(){ir.value=0;delay(200);}
void audio(){
tda.setInput(in); // 1 to 4 // номер канала
tda.inputGain(gain); // 0 to 15 // усиление
tda.setVolume(vol); // 0 to 48 ( 0 is mute) // громкость
tda.setSnd(0, 1); //-7 to +7 , 1 - Bass | 2 - Mids | 3 - Trebble
tda.setSnd(0, 2);
tda.setSnd(0, 3);
tda.spkAtt(4-balans, 4+balans); // баланс R L от 0 to 79 (db)
/////////// номер полосы, дБ (-7...+7) //////////
tda1.setBand(0,q[4]); // 10000 Hz
tda1.setBand(1,q[3]); // 260 Hz
tda1.setBand(2,q[2]); // 1000 Hz
tda1.setBand(3,q[1]); // 3000 Hz
tda1.setBand(4,q[0]); // 60 Hz
}
void to_Timer(){newPosition = myEnc.read()/4;}