R2A15908SP — простой но высококачественный аудиопроцессор с микроконтроллерным управлением (I2C).
Основные характеристики аудиопроцессора R2A15908SP:
- Регулировка громкости от -87 до 0 дБ (шаг 1 дБ)
- 5-и канальный коммутатор входов
- Режим MUTE
- Независимый для каждого входа предусилитель с диапазоном регулировки от 0 до 20 дБ (шаг 2 дБ)
- Регуляторы тембра ВЧ и НЧ с диапазоном регулировки от -14 до +14 дБ (шаг 2 дБ)
- Режимы: Surround Low / High
- Напряжение питания от 4,75 до 9,7 В (9 В — рекомендуемое)
- Ток потребления 15 мА
- Максимальное входное напряжение 2,5 Vrms
- Коэффициент нелинейных искажений 0.01 %
- Разделение каналов 100 дБ
Тестовый скетч:
#include <Wire.h> #include <R2A15908SP.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=765&download=1 R2A15908SP ra; void setup(){ audio(); delay(1000); } void loop(){} void audio(){ ra.setVolume_left(80); // -87...0 dB === int 0...87 ra.setVolume_right(80);// -87...0 dB === int 0...87 ra.setIn_Gain(0,0); // IN 1...5 === byte 0...4 /// int 7 === mute // GAIN 0...20 dB step 2 dB === int 0...10 ra.setStereo(0,1); // 0 = stereo / 1 = Lch / 2 = Rch // 0 = bypass / 1 = tone / 2 = tone&surround_hi / 3 = tone&surround_low ra.setTone(0,0); // bass and treb -14...14 dB step 2 dB === int -7...7 }
На R2A15908SP совместно с Arduino Nano можно собрать простой регулятор громкости и тембра. Для управления регулятором будет использоваться энкодер KY-040 и ИК-датчик для управления функциями регулятора при помощи ИК пульта. Вся информация о состоянии регулятора будет выводится на LCD дисплей 1602 (I2C).
Меню регулятора состоит 6-и категорий:
Регулировка громкости
Регулировка НЧ
Режим стерео/моно
Дополнительно, при нажатии и удержании кнопки энкодера можно перейти в меню выбора входа и регулировки предусилителя. ИК пульт дублирует работу энкодера и дополнительно дает доступ к функциям MUTE и STANDBY. Для управления регулятором подойдет практически любой пульт ИК, для поддержки Вашего пульта необходимо прописать коды кнопок в скетч:
#define IR_1 0x2FDD02F // Кнопка вверх #define IR_2 0x2FD32CD // Кнопка вниз #define IR_3 0x2FD906F // Кнопка > #define IR_4 0x2FDF20D // Кнопка < #define IR_5 0x2FD708F // Кнопка IN #define IR_6 0x2FD00FF // Кнопка POWER #define IR_7 0x2FD2AD5 // Кнопка MUTE
Для получения кодов кнопок Вашего пульта загрузите скетч и откройте монитор порта, при нажатии кнопки пульта его код будет отображен в мониторе порта.
Все изменяемые параметры регулятора записываются в энергонезависимую память.
#define IR_1 0x2FDD02F // Кнопка вверх #define IR_2 0x2FD32CD // Кнопка вниз #define IR_3 0x2FD906F // Кнопка > #define IR_4 0x2FDF20D // Кнопка < #define IR_5 0x2FD708F // Кнопка IN #define IR_6 0x2FD00FF // Кнопка POWER #define IR_7 0x2FD2AD5 // Кнопка MUTE #include <Wire.h> #include <EEPROM.h> #include <R2A15908SP.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=765&download=1 #include <boarddefs.h> #include <IRremote.h> // http://rcl-radio.ru/wp-content/uploads/2019/06/IRremote.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 R2A15908SP ra; Encoder myEnc(8, 9);// D8, D9 = CLK, DT IRrecv irrecv(12); // D12 = IR decode_results ir; LiquidCrystal_I2C lcd(0x27,16,2); // SDA, SCL 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}; unsigned long oldPosition = -999,newPosition,times,times1; byte z,z0,z1,w,w2,power,gr1,gr2,in,in_old,xd,www,mute; int mode,menu,vol,menu_in,x,gain0,gain1,gain2,gain3,gain4,gain5,bas,treb,ball,stereo; void setup(){ Serial.begin(9600); pinMode(7,INPUT); // кнопка энкодера pinMode(13,OUTPUT); // выход управления Standby OCR2A = 200; TCCR1B |= (1 << WGM22)|(1 << CS20)|(1 << CS21); TIMSK2 |= (1 << OCIE2A); // timer2 Wire.begin();lcd.init();lcd.backlight();irrecv.enableIRIn(); lcd.createChar(0,a1);lcd.createChar(1,a2);lcd.createChar(2,a3); lcd.setCursor(0,0);lcd.print(F(" R2A15908SP ")); delay(2000);lcd.clear(); if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}} vol = EEPROM.read(0);in = EEPROM.read(1);bas = EEPROM.read(2)-7;treb = EEPROM.read(3)-7;ball = EEPROM.read(4)-6; stereo = EEPROM.read(5);mode = EEPROM.read(6); gain1 = EEPROM.read(10);gain2 = EEPROM.read(11);gain3 = EEPROM.read(12);gain4 = EEPROM.read(13);gain5 = EEPROM.read(14); switch(in){ case 0: gain0 = gain1;break; case 1: gain0 = gain2;break; case 2: gain0 = gain3;break; case 3: gain0 = gain4;break; case 4: gain0 = gain5;break;} audio(); } void loop(){ if(power==0){digitalWrite(13,HIGH);}else{digitalWrite(13,LOW);} /////////////////// IR /////////////////////////////////// if ( irrecv.decode( &ir )) {Serial.print("0x");Serial.println( ir.value,HEX);irrecv.resume();times=millis();w=1;}// IR приемник - чтение, в мониторе порта отображаются коды кнопок if(ir.value==0){gr1=0;gr2=0;}// запрет нажатий не активных кнопок пульта if(power==0){ if(ir.value==IR_2 && mute==0){menu++;gr1=0;gr2=0;cl2();times=millis();w=1;w2=1;if(menu>5){menu=0;}}// меню кнопка вверх if(ir.value==IR_1 && mute==0){menu--;gr1=0;gr2=0;cl2();times=millis();w=1;w2=1;if(menu<0){menu=5;}}// меню кнопка вниз if(ir.value==IR_5){menu=0;in++;gr1=0;gr2=0;cl2();times=millis();w=1;w2=1;if(in>4){in = 0;}audio();}// IN if(ir.value==IR_7 && mute==0){mute=1;menu=100;;gr1=0;gr2=0;cl2();times=millis();w=1;w2=1;in_old=in;in=7;audio();lcd.setCursor(0,0);lcd.print(F(" MUTE "));delay(300);}// MUTE if(ir.value==IR_7 && mute==1){mute=0;menu=0;;gr1=0;gr2=0;cl2();times=millis();w=1;w2=1;in=in_old;audio();delay(300);}// MUTE } if(ir.value==IR_6 && power==0){power=1;menu=100;gr1=0;gr2=0;cl2();times=millis();w=1;w2=1;in_old=in;in=7;audio();lcd.setCursor(0,0);lcd.print(F(" POWER OFF "));delay(3000);lcd.noBacklight();}// кнопка POWER OFF if(ir.value==IR_6 && power==1){power=0;menu=0;gr1=0;gr2=0;cl2();times=millis();w=1;w2=1;in=in_old;audio();lcd.setCursor(0,0);lcd.backlight();lcd.print(F(" POWER ON "));delay(1000);lcd.clear();}// кнопка POWER OFF //////////////// INPUT MENU ////////////////////////////////////////////////////////// if(power==0){ if(digitalRead(7)==LOW && menu_in==0 && mute==0){x++;xd=1;delay(200);} if(digitalRead(7)==HIGH && menu_in==0 && x>0 && mute==0){xd=1;x=0;times=millis();times1=millis();w=1;w2=1;} if(x > 5){menu_in=1;lcd.clear();lcd.setCursor(0,0);lcd.print(F(" INPUT MENU "));delay(1000);lcd.clear(); times1 = millis();} if(menu_in==1){menu=0;x=0;if(digitalRead(7)==LOW){times=millis();times1=millis();w=1;w2=1;in++;www=1;if(in>4){in = 0;}delay(200); } //gain switch(in){ case 0: gain0 = gain1;break; case 1: gain0 = gain2;break; case 2: gain0 = gain3;break; case 3: gain0 = gain4;break; case 4: gain0 = gain5;break;} if (newPosition != oldPosition) { oldPosition = newPosition; gain0=gain0+newPosition;myEnc.write(0);newPosition=0;times=millis();times1=millis();w=1;w2=1;www=1;gain_func();audio();} switch(in){ case 0: gain1 = gain0;break; case 1: gain2 = gain0;break; case 2: gain3 = gain0;break; case 3: gain4 = gain0;break; case 4: gain5 = gain0;break;} if(www==1){audio();www=0;} lcd.setCursor(5,1);lcd.print(" ");lcd.print(gain0*2);lcd.print(" ");lcd.setCursor(8,1);lcd.print(F(" dB")); // end gain lcd.setCursor(3,0);lcd.print(F("INPUT ")); switch(in){ case 0: lcd.print(F("AUX1"));break; case 1: lcd.print(F("AUX2"));break; case 2: lcd.print(F("AUX3"));break; case 3: lcd.print(F("AUX4"));break; case 4: lcd.print(F("AUX5"));break;}} if(digitalRead(7)==HIGH && millis()-times1>3000 && menu_in==1){x=0;menu=-1;menu_in=0;times=millis();times1=millis();w=1;w2=1;lcd.clear();} if(digitalRead(7)==HIGH && xd == 1 && menu_in==0){menu++;times=millis();w=1;w2=1;xd=0;lcd.clear();if(menu>5){menu=0;}} } ///////////////// END INPUT MENU /////////////////////////////////////////////////////// //////////////////// VOLUME ///////////////////////////////// if(menu==0 && menu_in==0 && power==0){ if(ir.value==IR_3){vol++;gr1=1;gr2=0;cl();times=millis();w=1;w2=1;vol_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){vol++;gr2=0;cl();times=millis();w=1;w2=1;vol_func();audio();}// кнопка >>>>>> if(ir.value==IR_4){vol--;gr1=0;gr2=1;cl();times=millis();w=1;w2=1;vol_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){vol--;gr1=0;cl();times=millis();w=1;w2=1;vol_func();audio();}// кнопка <<<<<< if (newPosition != oldPosition){oldPosition = newPosition; vol=vol+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;vol_func();audio();} lcd.setCursor(0,0);lcd.print(F("VOLUME ")); if(vol<10){lcd.setCursor(8,0);}else{lcd.setCursor(7,0);}lcd.print(" ");lcd.print(vol-12);lcd.print(" "); lcd.setCursor(12,0); switch(in){ case 0: lcd.print(F("AUX1"));break; case 1: lcd.print(F("AUX2"));break; case 2: lcd.print(F("AUX3"));break; case 3: lcd.print(F("AUX4"));break; case 4: lcd.print(F("AUX5"));break;} if(w2==1){ for(z=0,z0=0,z1=0;z<=map(vol, 12,87, 0, 48);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(F(" "));}} if(z1==3){lcd.setCursor(z0,1);lcd.write((uint8_t)1);} if(z1==2){lcd.setCursor(z0,1);lcd.write((uint8_t)2);}w2=0;}} ///////////////////////// BASS +/-14 dB ///////////////////////////////////////////////////////// if(menu==1){ if(ir.value==IR_3){bas++;gr1=1;gr2=0;cl3();times=millis();w=1;w2=1;bass_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){bas++;gr2=0;cl3();times=millis();w=1;w2=1;bass_func();audio();}// кнопка >>>>>> if(ir.value==IR_4){bas--;gr1=0;gr2=1;cl3();times=millis();w=1;w2=1;bass_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){bas--;gr1=0;cl3();times=millis();w=1;w2=1;bass_func();audio();}// кнопка <<<<<< if (newPosition != oldPosition) { oldPosition = newPosition; bas=bas+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;bass_func();audio();} lcd.setCursor(0,0);lcd.print(F("BASS ")); if(bas>=0){lcd.print(F("+"));}lcd.print(bas*2);lcd.print(" ");lcd.setCursor(13,0);lcd.print(F("dB")); if(w2==1){ for(z=0,z0=0,z1=0;z<=(bas*2+14+1);z++,z1++){if(z1>2){z1=0;z0++;} if(z1==1){lcd.setCursor(z0+3,1);lcd.write((uint8_t)0);lcd.setCursor(z0+1+3,1);lcd.print(F(" "));}} if(z1==3){lcd.setCursor(z0+3,1);lcd.write((uint8_t)1);} if(z1==2){lcd.setCursor(z0+3,1);lcd.write((uint8_t)2);}w2=0;}} /////////////////////// END BASS ////////////////////////////////// ///////////////////////// TREBLE +/-14 dB ///////////////////////////////////////////////////////// if(menu==2){ if(ir.value==IR_3){treb++;gr1=1;gr2=0;cl3();times=millis();w=1;w2=1;treb_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){treb++;gr2=0;cl3();times=millis();w=1;w2=1;treb_func();audio();}// кнопка >>>>>> if(ir.value==IR_4){treb--;gr1=0;gr2=1;cl3();times=millis();w=1;w2=1;treb_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){treb--;gr1=0;cl3();times=millis();w=1;w2=1;treb_func();audio();}// кнопка <<<<<< if (newPosition != oldPosition) { oldPosition = newPosition; treb=treb+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;treb_func();audio();} lcd.setCursor(0,0);lcd.print(F("TREBLE ")); if(treb>=0){lcd.print(F("+"));}lcd.print(treb*2);lcd.print(" ");lcd.setCursor(13,0);lcd.print(F("dB")); if(w2==1){ for(z=0,z0=0,z1=0;z<=(treb*2+14+1);z++,z1++){if(z1>2){z1=0;z0++;} if(z1==1){lcd.setCursor(z0+3,1);lcd.write((uint8_t)0);lcd.setCursor(z0+1+3,1);lcd.print(F(" "));}} if(z1==3){lcd.setCursor(z0+3,1);lcd.write((uint8_t)1);} if(z1==2){lcd.setCursor(z0+3,1);lcd.write((uint8_t)2);}w2=0;}} /////////////////////// END TREBLE ////////////////////////////////// ////////////////// BALANCE ///////////////////////////////////////////////////////////////// if(menu==3){ if(ir.value==IR_3){ball++;gr1=1;gr2=0;cl3();times=millis();w=1;w2=1;ball_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){ball++;gr2=0;cl3();times=millis();w=1;w2=1;ball_func();audio();}// кнопка >>>>>> if(ir.value==IR_4){ball--;gr1=0;gr2=1;cl3();times=millis();w=1;w2=1;ball_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){ball--;gr1=0;cl3();times=millis();w=1;w2=1;ball_func();audio();}// кнопка <<<<<< if (newPosition != oldPosition) { oldPosition = newPosition; ball=ball+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;ball_func();audio();} lcd.setCursor(0,0); if(ball>=0){lcd.print("-");}else{lcd.print("+");} lcd.print(abs(ball));lcd.print(" dB "); lcd.print(" <> "); if(ball>=0){lcd.print("+");}else{lcd.print("-");} lcd.print(abs(ball));lcd.print(" dB "); if(w2==1){lcd.setCursor(ball+5,1);lcd.print(F(" ")); if(ball==0){lcd.setCursor(ball+7,1);lcd.write((uint8_t)0);lcd.write((uint8_t)0);} if(ball>0){ lcd.setCursor(ball+8,1);lcd.write((uint8_t)0);} if(ball<0){ lcd.setCursor(ball+7,1);lcd.write((uint8_t)0);} lcd.print(F(" "));w2=0;}} /////////////// Stereo / Mono ////////////////////////// if(menu==4){ if(ir.value==IR_3){stereo++;gr1=1;gr2=0;cl3();times=millis();w=1;w2=1;if(stereo>2){stereo=0;}audio();}// кнопка > if(ir.value==IR_4){stereo--;gr1=0;gr2=1;cl3();times=millis();w=1;w2=1;if(stereo<0){stereo=2;}audio();}// кнопка < if (newPosition != oldPosition) { oldPosition = newPosition; stereo=stereo+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;if(stereo>2){stereo=0;};if(stereo<0){stereo=2;}audio();} lcd.setCursor(0,0);lcd.print(" Stereo / Mono "); lcd.setCursor(0,1); switch(stereo){ case 0: lcd.print(" STEREO ");break; case 1: lcd.print(" Lch Mono ");break; case 2: lcd.print(" Rch Mono ");break; }} /////////////// Mode Selector ////////////////////////// if(menu==5){ if(ir.value==IR_3){mode++;gr1=1;gr2=0;cl3();times=millis();w=1;w2=1;if(mode>3){mode=0;}audio();}// кнопка > if(ir.value==IR_4){mode--;gr1=0;gr2=1;cl3();times=millis();w=1;w2=1;if(mode<0){mode=3;}audio();}// кнопка < if (newPosition != oldPosition) { oldPosition = newPosition; mode=mode+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;if(mode>3){mode=0;};if(mode<0){mode=3;}audio();} lcd.setCursor(0,0);lcd.print(" Mode Selector "); lcd.setCursor(0,1); switch(mode){ case 0: lcd.print(" BYPASS ");break; case 1: lcd.print(" TONE ");break; case 2: lcd.print("Tone&Surround Hi");break; case 3: lcd.print("Tone&Surround Lo");break; }} ///////////// EEPROM //////////////////////////////////////// if(millis()-times>5000 && w==1){ EEPROM.write(0,vol);EEPROM.write(1,in);EEPROM.write(2,bas+7);EEPROM.write(3,treb+7);EEPROM.write(4,ball+6); EEPROM.write(5,stereo);EEPROM.write(6,mode); EEPROM.write(10,gain1);EEPROM.write(11,gain2);EEPROM.write(12,gain3);EEPROM.write(13,gain4);EEPROM.write(14,gain5); menu=0;w=0;w2=1;cl2();} }// LOOP void ball_func(){if(ball>6){ball=6;}if(ball<-6){ball=-6;}} void treb_func(){if(treb>7){treb=7;}if(treb<-7){treb=-7;}} void bass_func(){if(bas>7){bas=7;}if(bas<-7){bas=-7;}} void gain_func(){if(gain0>10){gain0=10;}if(gain0<0){gain0=0;}} void vol_func(){if(vol>87){vol=87;}if(vol<12){vol=12;}} void cl(){ir.value=0;} void cl1(){ir.value=0;delay(20);} void cl2(){ir.value=0;lcd.clear();} void cl3(){ir.value=0;delay(100);} void audio(){ ra.setVolume_left(vol-6+ball); // -87...0 dB === int 0...87 ra.setVolume_right(vol-6-ball);// -87...0 dB === int 0...87 ra.setIn_Gain(in,gain0); // IN 1...5 === byte 0...4 /// int 7 === mute // GAIN 0...20 dB step 2 dB === int 0...10 ra.setStereo(stereo,mode); // 0 = stereo / 1 = Lch / 2 = Rch // 0 = bypass / 1 = tone / 2 = tone&surround_hi / 3 = tone&surround_low ra.setTone(bas,treb); // bass and treb -14...14 dB step 2 dB === int -7...7 } ISR (TIMER2_COMPA_vect){newPosition = myEnc.read()/4;}