TDA7439 + OLED1.3 + ENCODER + IR (LGT8F328 | Arduino Nano)

ИК-модуль VS1838B

ИМС TDA7439 – регулятор громкости и трехполосный регулятор тембра, разработан для использования в HI-FI аппаратуре и качественных автомобильных аудиосистемах, обладает низким уровнем шумов и искажений.

Основные технические характеристики ИМС TDA7439:

  • Громкость 48 уровней от -48 до 0 дБ
  • Регулировка тембра НЧ, СЧ, ВЧ  ±14 дБ (±7 уровней)
  • Коммутация входов — 4 стерео канала

    Энкодер ky-040

  • Усиление от 0 до 30 дБ независимое для каждого канала
  • Регулировка баланса ±8 дБ (ограниченно программно)
  • Напряжение питания от 6 до 10,2 В (типовое значение 9 В)
  • КНИ на частоте 1 кГц не более 0,01%

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

В качестве органов управления регулятором громкости и тембра три используются кнопки, энкодер KY-040 и ИК-модуля VS1838B. Информация о настройках выводится на OLED дисплей с разрешением 128 на 64 точки, диагональ дисплея 1,3 дюйма, чип драйвера — SH1106  I2C. В проекте используется плата контроллера LGT8F328, но можно использовать Atduino Nano.

Меню управления регулятором громкости и тембра

Громкость

Тембр ВЧ

Тембр СЧ

Тембр НЧ

Баланс

Выбор входа и усиления

MUTE

STANDBY

Подачи питания регулятор громкости и тембра переходит в режим STANDBY, вывод D13 используется для управления режимом STANDBY УМЗЧ. В регулятор громкости и тембра так же предусмотрены цифровые выходы режима работы селектора входов, к ним при необходимости можно подключить светодиоды диоды (через резистор 200 Ом) для индикации активности входа, использовать как управляющий сигнал для подачи питания на источник звукового сигнала.

#define ENC_DT       8
#define ENC_CLK      9
#define ENC_SW       10
#define IR           12

#define MENU      0x33B820DF // button encoder
#define UP        0x33B810EF // >>>
#define DW        0x33B8E01F // <<<
#define INPUT_IR  0x33B88877 // IN
#define POWER_IR  0x33B800FF // POWER
#define MUTE_IR   0x33B811FF // MUTE

#define IN            2 
#define POWER         6
#define POWER_OUT_PIN 13
#define MUTE          3


#define IN1_OUT   A0
#define IN2_OUT   A1
#define IN3_OUT   A2
#define IN4_OUT   A3

#include <Wire.h> 
#include <U8glib.h>            // https://github.com/olikraus/u8glib/
#include <MsTimer2.h>          // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
#include <TDA7439.h>           // http://rcl-radio.ru/wp-content/uploads/2019/01/TDA7439.zip
#include <Encoder.h>           // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip 
#include <EEPROM.h>
#include <boarddefs.h>         // входит в состав библиотеки IRremote
#include <IRremote.h>          // http://rcl-radio.ru/wp-content/uploads/2019/06/IRremote.zip
 
TDA7439 tda;
Encoder myEnc(ENC_DT, ENC_CLK);
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);
IRrecv irrecv(IR); 
decode_results ir; 

long oldPosition  = -999,newPosition, times;
int vol_reg,balans,treb_reg,bass_reg,mid_reg,in_reg,gain0,gain1,gain2,gain3,gain4,menu,vol_old;
bool gr1,gr2,w=1,w1,www,power,power_off=1,mute;

void setup() {
  Wire.begin();Serial.begin(9600);
  irrecv.enableIRIn();
  pinMode(ENC_SW,INPUT);
  pinMode(IN,INPUT_PULLUP);
  pinMode(MUTE,INPUT_PULLUP);
  pinMode(POWER,INPUT_PULLUP); 
  pinMode(POWER_OUT_PIN,OUTPUT);
  pinMode(IN1_OUT,OUTPUT);
  pinMode(IN2_OUT,OUTPUT);
  pinMode(IN3_OUT,OUTPUT);
  pinMode(IN4_OUT,OUTPUT);
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении  
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  vol_reg = EEPROM.read(0);treb_reg = EEPROM.read(1)-7;mid_reg = EEPROM.read(2)-7;bass_reg = EEPROM.read(3)-7;
  in_reg = EEPROM.read(4);gain1 = EEPROM.read(5);gain2 = EEPROM.read(6);gain3 = EEPROM.read(7);gain4 = EEPROM.read(8);balans = EEPROM.read(9)-8;
  switch(in_reg){
    case 1: gain0=gain1;break;
    case 2: gain0=gain2;break;
    case 3: gain0=gain3;break;
    case 4: gain0=gain4;break;
    }
  audio();  
}

void loop() {
  if(power==0){
   if(in_reg==1){digitalWrite(IN1_OUT,HIGH);}else{digitalWrite(IN1_OUT,LOW);}
   if(in_reg==2){digitalWrite(IN2_OUT,HIGH);}else{digitalWrite(IN2_OUT,LOW);}
   if(in_reg==3){digitalWrite(IN3_OUT,HIGH);}else{digitalWrite(IN3_OUT,LOW);}
   if(in_reg==4){digitalWrite(IN4_OUT,HIGH);}else{digitalWrite(IN4_OUT,LOW);}
  }
   else{digitalWrite(IN1_OUT,LOW);digitalWrite(IN2_OUT,LOW);digitalWrite(IN3_OUT,LOW);digitalWrite(IN4_OUT,LOW);}
   
  // IR ////////////////////////////////////////
 if ( irrecv.decode( &ir )) {Serial.print("0x");Serial.println( ir.value,HEX);irrecv.resume();}// IR приемник - чтение, в мониторе порта отображаются коды кнопок
 if(ir.value==0){gr1=0;gr2=0;}// запрет нажатий не активных кнопок пульта  

// BUTTON ///////////////////////////////////////////////////
 if((digitalRead(POWER)==LOW||ir.value==POWER_IR||power_off==1)&&power==0&&mute==0){power_off=0;power=1;menu=100;cl();vol_old=vol_reg;vol_reg=0;audio();
  u8g.firstPage();do {u8g.setFont(u8g_font_profont12r);u8g.drawStr(40,30,"POWER OFF");} while( u8g.nextPage() );
  delay(1500); u8g.firstPage();do {} while( u8g.nextPage() );}
  
 if((digitalRead(POWER)==LOW||ir.value==POWER_IR)&&power==1){power=0;menu=0;vol_reg=vol_old;times=millis();w=1;w1=1;
  u8g.firstPage();do {u8g.drawStr(42,30,"POWER ON");} while( u8g.nextPage() );delay(1500);audio();}

if(power==0){digitalWrite(POWER_OUT_PIN,HIGH);}else{digitalWrite(POWER_OUT_PIN,LOW);} 

if(power==0){
 if(digitalRead(ENC_SW)==LOW||ir.value==MENU){menu++;cl();if(menu>4){menu=0;}times=millis();w=1;w1=1;delay(200);}
 if(digitalRead(IN)==LOW||ir.value==INPUT_IR){menu=10;cl();in_reg++;times=millis();w=1;w1=1;www=1;if(in_reg>4){in_reg=1;};delay(200);}
 
 if((digitalRead(MUTE)==LOW||ir.value==MUTE_IR)&&mute==0){mute=1;menu=100;cl();vol_old=vol_reg;vol_reg=0;audio();
     u8g.firstPage();do {u8g.setFont(u8g_font_profont12r);u8g.drawStr(53,30,"MUTE");} while( u8g.nextPage() );}
 if((digitalRead(MUTE)==LOW||ir.value==MUTE_IR)&&mute==1){mute=0;times=millis();w=1;w1=1;menu=0;cl();vol_reg=vol_old;audio();}
}
//////// VOLUME //////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  if(menu==0){
   if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
   vol_reg=vol_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;vol_func();audio();}
 
   if(ir.value==UP){vol_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка > 
   if(ir.value==0xFFFFFFFF and gr1==1){vol_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка >>>>>>
   if(ir.value==DW){vol_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка <
   if(ir.value==0xFFFFFFFF and gr2==1){vol_reg--;gr1=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка <<<<<<
 
  if(w==1){w=0;
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"VOLUME");u8g.drawStr(0,18,"IN");
  u8g.setPrintPos(20, 18);u8g.print(in_reg);u8g.drawStr(0,28,"GAIN");u8g.setPrintPos(30, 28);u8g.print(gain0);
  u8g.drawLine(0, 32, 128, 32);
  u8g.drawStr(0,44,"TREBLE");u8g.setPrintPos(80, 44);u8g.print(treb_reg*2);u8g.drawStr(95,44,"dB");
  u8g.drawStr(0,54,"MIDDLE");u8g.setPrintPos(80, 54);u8g.print(mid_reg*2);u8g.drawStr(95,54,"dB");
  u8g.drawStr(0,64,"BASS");u8g.setPrintPos(80, 64);u8g.print(bass_reg*2);u8g.drawStr(95,64,"dB");
  u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(vol_reg);
   } while( u8g.nextPage() );
  }}
/////////////////////////////////////////////////////////////////

//////// TRABLE //////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  if(menu==1){
   if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
   treb_reg=treb_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;treb_func();audio();}
 
   if(ir.value==UP){treb_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка > 
   if(ir.value==0xFFFFFFFF and gr1==1){treb_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка >>>>>>
   if(ir.value==DW){treb_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка <
   if(ir.value==0xFFFFFFFF and gr2==1){treb_reg--;gr1=0;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка <<<<<<
   
   if(w==1){w=0;
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(treb_reg*2);
  u8g.drawLine(0, 32, 128, 32);
  u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"TREBLE");u8g.drawStr(0,44,"MIDDLE");u8g.setPrintPos(80, 44);u8g.print(mid_reg*2);u8g.drawStr(95,44,"dB");
  u8g.drawStr(0,54,"BASS");u8g.setPrintPos(80, 54);u8g.print(bass_reg*2);u8g.drawStr(95,54,"dB");
  u8g.drawStr(0,64,"BALANCE");u8g.setPrintPos(80, 64);u8g.print(balans);u8g.drawStr(95,64,"dB");
   } while( u8g.nextPage() );
  }}
/////////////////////////////////////////////////////////////////

//////// MIDDLE //////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  if(menu==2){
   if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
   mid_reg=mid_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;mid_func();audio();}
 
   if(ir.value==UP){mid_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка > 
   if(ir.value==0xFFFFFFFF and gr1==1){mid_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка >>>>>>
   if(ir.value==DW){mid_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка <
   if(ir.value==0xFFFFFFFF and gr2==1){mid_reg--;gr1=0;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка <<<<<<
   
   if(w==1){w=0;
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(mid_reg*2);
  u8g.drawLine(0, 32, 128, 32);
  u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"MIDDLE");u8g.drawStr(0,44,"BASS");u8g.setPrintPos(80, 44);u8g.print(bass_reg*2);u8g.drawStr(95,44,"dB");
  u8g.drawStr(0,54,"BALANCE");u8g.setPrintPos(80, 54);u8g.print(balans);u8g.drawStr(95,54,"dB");
  u8g.drawStr(0,64,"VOLUME");u8g.setPrintPos(80, 64);u8g.print(vol_reg);u8g.drawStr(95,64,"dB");
   } while( u8g.nextPage() );
  }}
/////////////////////////////////////////////////////////////////

//////// BASS //////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  if(menu==3){
   if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
   bass_reg=bass_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;bass_func();audio();}
 
   if(ir.value==UP){bass_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка > 
   if(ir.value==0xFFFFFFFF and gr1==1){bass_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка >>>>>>
   if(ir.value==DW){bass_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка <
   if(ir.value==0xFFFFFFFF and gr2==1){bass_reg--;gr1=0;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка <<<<<<
   
 if(w==1){w=0;
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(bass_reg*2);
  u8g.drawLine(0, 32, 128, 32);
  u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"BASS");
  u8g.drawStr(0,44,"BALANCE");u8g.setPrintPos(80, 44);u8g.print(balans);u8g.drawStr(95,44,"dB");
  u8g.drawStr(0,54,"VOLUME");u8g.setPrintPos(80, 54);u8g.print(vol_reg);u8g.drawStr(95,54,"dB");
  u8g.drawStr(0,64,"TREBLE");u8g.setPrintPos(80, 64);u8g.print(treb_reg*2);u8g.drawStr(95,64,"dB");
   } while( u8g.nextPage() );
  }}
/////////////////////////////////////////////////////////////////

//////// BALANCE //////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  if(menu==4){
  if (newPosition != oldPosition){oldPosition = newPosition;balans=balans+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;ball_func();audio();}
 
   if(ir.value==UP){balans++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка > 
   if(ir.value==0xFFFFFFFF and gr1==1){balans++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка >>>>>>
   if(ir.value==DW){balans--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка <
   if(ir.value==0xFFFFFFFF and gr2==1){balans--;gr1=0;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка <<<<<<
 
  if(w==1){w=0;
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"BALANCE");u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(abs(balans));
  u8g.setFont(u8g_font_profont12r);
  if(balans<=0){u8g.drawStr(50,20,"LCH");}
  if(balans>=0){u8g.drawStr(105,20,"RCH");}
  u8g.drawLine(0, 32, 128, 32);
  u8g.drawStr(0,44,"VOLUME");u8g.setPrintPos(80, 44);u8g.print(vol_reg);u8g.drawStr(95,44,"dB");
  u8g.drawStr(0,54,"TREBLE");u8g.setPrintPos(80, 54);u8g.print(mid_reg*2);u8g.drawStr(95,54,"dB");
  u8g.drawStr(0,64,"MIDDLE");u8g.setPrintPos(80, 64);u8g.print(treb_reg*2);u8g.drawStr(95,64,"dB");
  } while( u8g.nextPage() );
  }}
//////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////// INPUT GAIN ///////////////////////////////////////////////////////////////////
 if(menu==10){
  switch(in_reg){
    case 1: gain0=gain1;break;
    case 2: gain0=gain2;break;
    case 3: gain0=gain3;break;
    case 4: gain0=gain4;break;
    }
  if (newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
   gain0=gain0+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;www=1;gain_func();}

   if(ir.value==UP){gain0++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка > 
   if(ir.value==0xFFFFFFFF and gr1==1){gain0++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка >>>>>>
   if(ir.value==DW){gain0--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка <
   if(ir.value==0xFFFFFFFF and gr2==1){gain0--;gr1=0;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка <<<<<<

  switch(in_reg){
    case 1: gain1=gain0;break;
    case 2: gain2=gain0;break;
    case 3: gain3=gain0;break;
    case 4: gain4=gain0;break;
    } 
  if(www==1){audio();www=0;}
  if(w==1){w=0;
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(in_reg);  
  u8g.drawLine(0, 32, 128, 32);
  u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"INPUT");u8g.drawStr(0,44,"GAIN");
  u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 60);u8g.print(gain0);
    } while( u8g.nextPage() );
  }}


if(millis()-times>5000 && w1==1 && power==0 && mute==0){
     EEPROM.update(0,vol_reg);EEPROM.update(1,treb_reg+7);EEPROM.update(2,mid_reg+7);EEPROM.update(3,bass_reg+7);
     EEPROM.update(4,in_reg);EEPROM.update(5,gain1);EEPROM.update(6,gain2);EEPROM.update(7,gain3);EEPROM.update(8,gain4);EEPROM.update(9,balans+8);
     menu=0;w1=0;w=1;myEnc.write(0);}

}

void to_Timer(){newPosition = myEnc.read()/4;}
void cl(){ir.value=0;delay(200);}
void vol_func(){if(vol_reg<0){vol_reg=0;}if(vol_reg>48){vol_reg=48;}}
void treb_func(){if(treb_reg<-7){treb_reg=-7;}if(treb_reg>7){treb_reg=7;}}
void mid_func(){if(mid_reg<-7){mid_reg=-7;}if(mid_reg>7){mid_reg=7;}}
void bass_func(){if(bass_reg<-7){bass_reg=-7;}if(bass_reg>7){bass_reg=7;}}
void gain_func(){if(gain0>15){gain0=15;}if(gain0<0){gain0=0;}}
void ball_func(){if(balans>8){balans=8;}if(balans<-8){balans=-8;}}
void audio(){
  tda.setInput(in_reg); // 1 to 4 // номер канала
  tda.inputGain(gain0); // 0 to 15 // усиление 
  tda.setVolume(vol_reg); // 0 to 48 ( 0 is mute) // громкость
  tda.setSnd(bass_reg, 1); //-7 to +7 , 1 - Bass | 2 - Mids | 3 - Trebble
  tda.setSnd(mid_reg, 2);
  tda.setSnd(treb_reg, 3); 
  tda.spkAtt(8 + balans ,8 - balans); // баланс R L от 0 to 79 (db) 
 }

ИК пульт дублирует работу энкодера и кнопок. Для управления регулятором подойдет практически любой пульт ИК, для поддержки Вашего пульта необходимо прописать коды кнопок в скетч:

#define MENU 0x33B820DF // button encoder
#define UP 0x33B810EF // >>>
#define DW 0x33B8E01F // <<<
#define INPUT_IR 0x33B88877 // IN
#define POWER_IR 0x33B800FF // POWER
#define MUTE_IR 0x33B811FF // MUTE

Для получения кодов кнопок Вашего пульта загрузите скетч и откройте монитор порта, при нажатии кнопки пульта его код будет отображен в мониторе порта.

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=592

Comments

  1. Здравствуйте,собрал все, но при подключении совместно с экраном, ничего не работает, пробовал 2 тдахи и сканером они тоже не определятся, на форуме в переделках написал подробнее (Arduino+tda+анализатор спектра)

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

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