PGA2311 — регулятор громкости (Arduino)

ИМС PGA2311 представляет собой электронный стерео регулятор громкости, управление регулятором громкости осуществляется при помощи трех проводной шины передачи данных. PGA2311 имеет большой динамический диапазон, сверх малый коэффициент нелинейных искажений, малый уровень шумов.

Основные характеристики PGA2311:

  • Диапазон регулировки громкости от -95,5 дБ до +31.5 дБ с шагом 0,5 дБ (255 ступеней)
  • Динамический диапазон 120 дБ
  • Коэффициент нелинейных искажений не более 0.0002%
  • Межканальные перекрестные помехи не более -130 дБ
  • Входное напряжение 2.5 Vrms
  • Режим MUTE

Регулятор громкости питается от двух полярного напряжения +/- 5 В для аналогового питания, дополнительно +5 В используется для питания цифровой части микросхемы.

Используя платформу Arduino (Nano, Uno), можно сделать качественный регулятор громкости. В регуляторе громкости дополнительно использован энкодер KY-040 для управления громкостью и балансом, дополнительно используется кнопка для активации режима MUTE. Информация о режимах работы регулятора выводится на LCD дисплея LCD1602 на базе контроллера HD44780 совместно с модулем I2C. I2C модуль на базе микросхемы PCF8574 позволяют подключить символьный дисплей 1602 к плате Arduino всего по двум проводам SDA и SCL (А4 и А5), что дает возможность не использовать цифровые выходы Arduino при подключении дисплея.

Регулятор на базе Arduino имеет диапазон регулировки громкости от -95,5 дБ до +21.5 дБ (10 дБ отведено регулятору баланса), регулировка баланса от +/- 10 дБ на канал.

#include <Wire.h> 
#include <EEPROM.h>
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <CS3310.h>
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
  LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
  Encoder myEnc(9, 8);//CLK, DT
  CS3310 pga(2,3,4);//CS,SCLK,SDATAI
 
  byte a1[8] = {0b00000,0b10101,0b10101,0b10101,0b10101,0b10101,0b10101,0b00000};
  byte a2[8] = {0b00000,0b10100,0b10100,0b10100,0b10100,0b10100,0b10100,0b00000};
  byte a3[8] = {0b00000,0b10000,0b10000,0b10000,0b10000,0b10000,0b10000,0b00000};  
  int vol,vol_d,z,z0,z1,vol_old,balanc;
  byte w,w1,mute,menu;
  unsigned long times,oldPosition  = -999,newPosition;
 
void setup(){
  Wire.begin();Serial.begin(9600);
  lcd.init();lcd.backlight();
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  lcd.createChar(0,a1);lcd.createChar(1,a2);lcd.createChar(2,a3);
  lcd.setCursor(0,0);lcd.print("    PGA2311   ");
  lcd.setCursor(0,1);lcd.print(" Volume Control ");delay(1000);lcd.clear();
  vol = EEPROM.read(0);
  balanc = EEPROM.read(1)-20;
  pinMode(7,INPUT);       // кнопка энкодера MENU   
  pinMode(6,INPUT_PULLUP);// кнопка MUTE
  pinMode(5,OUTPUT);      //выход управления MUTE
  digitalWrite(5,HIGH);   // MUTE OFF
  audio();
  }
 
void loop(){ 
   /// MENU /////////////////////////////////////// 
   if(digitalRead(7)==LOW){menu++;if(menu>1){menu=0;}lcd.clear();times=millis();w=1;w1=1;delay(200);}
   /// MUTE ///////////////////////////////////////
   if(digitalRead(6)==LOW&&mute==0){mute=1;digitalWrite(5,LOW);lcd.clear();lcd.setCursor(0,0);lcd.print("      MUTE   ");delay(300);}
   if(digitalRead(6)==LOW&&mute==1){mute=0;digitalWrite(5,HIGH);lcd.clear();w1=1;delay(300);}
 
   /////////////// VOLUME /////////////////////////////////////////////////////////
   if(menu==0&&mute==0){
   if (newPosition != oldPosition&&mute==0){oldPosition = newPosition;
   vol=vol+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;vol_func();audio();} 
   vol_d=map(vol,0,235,0,45);
   if(w1==1){
   for(z=0,z0=0,z1=0;z<=vol_d;z++,z1++){if(z1>2){z1=0;z0++;}
   if(z1==1){lcd.setCursor(z0,1);lcd.write((uint8_t)0);lcd.setCursor(z0+1,1);lcd.print("   ");}}
   if(z1==3){lcd.setCursor(z0,1);lcd.write((uint8_t)1);}
   if(z1==2){lcd.setCursor(z0,1);lcd.write((uint8_t)2);}w1=0;}
 
     lcd.setCursor(0,0);lcd.print("VOLUME ");
     if(vol*0.5-96>=0){lcd.print("+");}
     lcd.print(vol*0.5-96,1);lcd.print(" ");
     lcd.setCursor(14,0);lcd.print("dB");
   } // menu == 0  
 
   /////////////// BALANCE +/- 10 dB /////////////////////////////////////////////////////////
   if(menu==1&&mute==0){
   if (newPosition != oldPosition&&mute==0){oldPosition = newPosition;
   balanc=balanc+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;balanc_func();audio();} 
   lcd.setCursor(0,0);lcd.print("BALANCE ");if(balanc>=0){lcd.print("+");}lcd.print(balanc*0.5,1);lcd.print(" ");lcd.setCursor(14,0);lcd.print("dB");
   if(w1==1){
   if(balanc<0){lcd.setCursor(balanc/4-2+7,1);lcd.print("  ");lcd.write((uint8_t)0);lcd.print("  ");}
   if(balanc==0){lcd.setCursor(balanc/4-2+7,1);lcd.print("  ");lcd.write((uint8_t)0);lcd.write((uint8_t)0);lcd.print("  ");}
   if(balanc>0){lcd.setCursor(balanc/4-2+8,1);lcd.print("  ");lcd.write((uint8_t)0);lcd.print("  ");}
   w1=0;}
   }// menu == 1
 
 
 //////// EEPROM //////////////////////////////////////////////////
  if(millis()-times>10000 && w==1 && mute == 0){EEPROM.update(0,vol);EEPROM.update(1,balanc+20);w=0;menu=0;w1=1;lcd.clear();}
  } // LOOP
 
void audio(){
  pga.setVol(vol+balanc+20,vol-balanc+20);// byte 1...255 === -95.5...+31.5 dB (step 0.5 dB)
  }
void to_Timer(){newPosition = myEnc.read()/4;}
void vol_func(){if(vol<0){vol=0;}if(vol>235){vol=235;}}
void balanc_func(){if(balanc<-20){balanc=-20;}if(balanc>20){balanc=20;}}

Библиотеки:

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

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