1

Тема: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Тестовый запуск

http://forum.rcl-radio.ru/uploads/images/2022/10/d910c7ddf74e227fd4835a815a7cb033.png

http://forum.rcl-radio.ru/uploads/images/2022/10/e473e10554e05aa4d083f18955829bb5.png

Подключаем к Arduino шину I2C
http://forum.rcl-radio.ru/uploads/images/2022/10/fcb4c4d69a2e614fe481d806c90f25c0.png

http://forum.rcl-radio.ru/uploads/images/2022/10/b6b5f936f05e7121d93d193273dcff59.png

На шину I2C нужно поставить подтягивающие резисторы 4,7 К на +5В

#include <Wire.h>
#include <R2S15900SP.h>  // https://github.com/liman324/R2S15900SP.git
  R2S15900SP r2s;

bool sur_3d=0;
int bass=14,treb=5,vol;

void setup() {
  audio();
}

void loop() {
 
    
  audio();
  delay(1000);
  
}

void audio(){             
  r2s.setVol_l(10);  // volume left >> int 84...0 === -84...0 dB
  r2s.setVol_r(10);  // volume_right >> int 84...0 === -84...0 dB
  r2s.setInput(2, 1, 1);     
             // input >> int 0 === all off | int 1...5 === input 1...5 
             // gain >> int 0...1 === 0 dB...+4.5 dB
             // mute >> int 1...0 === mute off...mute on
  r2s.set_Bass(sur_3d, 3, bass);
             // surround mode >> int 0...1 === low level...high level
             // mode selector >> int 0...3 === bypass tone tone&Pseudo_stereo tone&Surround
             // tone control bass >> int -15...15 === -15dB...+15dB
  r2s.set_Treb(treb);   // tone control treble >> int -15...15 === -15dB...+15dB
}

2

Re: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Мой контроллер от MICROLAB FC550 исправен, если кому надо оставьте сообщение (меняю на коды кнопок пульта, родного пульта у меня нет)

3

Re: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Основная статья - http://rcl-radio.ru/?p=129576

#define IR_1 0x2FDD02F // VOLUME UP
#define IR_2 0x2FD32CD // VOLUME DOWN
#define IR_3 0x2FDAA55 // BASS UP
#define IR_4 0x2FDCA35 // BASS DOWN
#define IR_5 0x2FDE817 // TREB UP
#define IR_6 0x2FDA857 // TREB DOWN
#define IR_7 0x2FD6A95 // 3D
#define IR_8 0x2FD00FF // POWER
#define IR_9 0x2FDB04F // INPUT

#include <Wire.h> 
#include <R2S15900SP.h>         // https://github.com/liman324/R2S15900SP.git  
#include <boarddefs.h>          // входит в состав библиотеки IRremote
#include <IRremote.h>           // http://rcl-radio.ru/wp-content/uploads/2019/06/IRremote.zip
#include <EEPROM.h>


  R2S15900SP r2s;
  IRrecv irrecv(12); // указываем вывод модуля IR приемника
  decode_results ir; 

  int an, segm,data,i;
  byte a[2];
  bool w,sur_3d;
  unsigned long times,times0;

  volatile uint8_t _prevValueAB = 0;    
  volatile uint8_t _currValueAB = 0;
  volatile int16_t _counter = 0;
  
  int position = -999;
  int old_vol,volume,in,bass,treb;
  int menu;
  bool power=1,bassf,trebf,in1,in2,ddd;
  bool gr1,gr2,q1,q2,q3,q4,q5,q6,mute,k=1;
  

 
void setup(){  
    Wire.begin();
    Serial.begin(9600);
    irrecv.enableIRIn();
    cli();
    TCCR2B |= (1<<CS20)|(1<<CS22); 
    TIMSK2 |= (1<<TOIE2); 
    //F_TIMER2 = 16 000 000 / 128 / 256 = 488 Hz  
    sei();
    sur_3d=1;audio();delay(500);sur_3d=0;audio();delay(500);pin1();
    pinMode(10,INPUT);  // enc clk
    pinMode(11,INPUT);  // enc dt
    pinMode(A0,INPUT);  // A0 button input 
    volume = EEPROM.read(0);in = EEPROM.read(1);bass = EEPROM.read(2)-15;treb = EEPROM.read(3)-15;sur_3d = EEPROM.read(4);
    if(in>2 || in<1){in=1;}
    inn();
    audio();
}
 
void loop(){ 
  if(irrecv.decode( &ir )) {Serial.print("0x");Serial.println(ir.value,HEX);irrecv.resume();}
  
  if(ir.value==0){gr1=0;gr2=0;q1=0;q2=0;q4=0;q5=0;q5=0;q6=0;}// запрет нажатий не активных кнопок пульта
//// volume 
  old_vol=volume; 
  if(getPosition() != position){position = getPosition();volume = volume+getPosition();
    setPosition(0);menu=0;vol_conf();audio();w=1;times=millis();k=1;}
  v_old();
  if(power==0){
  if(ir.value==IR_1){q1=1;q2=0;gr1=1;gr2=0;volume--;vol_conf();cl1();menu=0;}
  if(ir.value==IR_2){q1=0;q2=1;gr1=0;gr2=1;volume++;vol_conf();cl1();menu=0;}
  if(ir.value==0xFFFFFFFF && gr1==1 && q1==1){gr2=0;volume--;vol_conf();cl1();menu=0;}
  if(ir.value==0xFFFFFFFF && gr2==1 && q2==1){gr1=0;volume++;vol_conf();cl1();menu=0;}
  v_old();
//// bass
  if(ir.value==IR_4){q5=1;q6=0;gr1=1;gr2=0;bass--;if(bass<-15){bass=-15;}cl1();bassf=1;menu=1;}
  if(ir.value==IR_3){q5=0;q6=1;gr1=0;gr2=1;bass++;if(bass>15){bass=15;}cl1();bassf=1;menu=1;}
  if(ir.value==0xFFFFFFFF && gr1==1 && q5==1){gr2=0;bass--;if(bass<-15){bass=-15;}cl1();bassf=1;menu=1;}
  if(ir.value==0xFFFFFFFF && gr2==1 && q6==1){gr1=0;bass++;if(bass>15){bass=15;}cl1();bassf=1;menu=1;}  
//// treb
  if(ir.value==IR_6){q3=1;q4=0;gr1=1;gr2=0;treb--;if(treb<-15){treb=-15;}cl1();trebf=1;menu=2;}
  if(ir.value==IR_5){q3=0;q4=1;gr1=0;gr2=1;treb++;if(treb>15){treb=15;}cl1();trebf=1;menu=2;}
  if(ir.value==0xFFFFFFFF && gr1==1 && q3==1){gr2=0;treb--;if(treb<-15){treb=-15;}cl1();trebf=1;menu=2;}
  if(ir.value==0xFFFFFFFF && gr2==1 && q4==1){gr1=0;treb++;if(treb>15){treb=15;}cl1();trebf=1;menu=2;}    
//// input
  if((digitalRead(A0)==0 || ir.value==IR_9) && in==1){in=2;in1=1;in2=0;cl1();}
  if((digitalRead(A0)==0 || ir.value==IR_9) && in==2){in=1;in1=0;in2=1;cl1();}
  inn();
//// 3d
  if(ir.value==IR_7 && sur_3d==0){sur_3d=1;ddd=1;cl1();}
  if(ir.value==IR_7 && sur_3d==1){sur_3d=0;ddd=0;cl1();}
  if(sur_3d==1){ddd=1;}else{ddd=0;}
  }
  
  if(menu==0){data=84-volume;a[0]=data/10;a[1]=data%10;}
  if(menu==1){trebf=0;
    if(bass>=-9&&bass<=-1){data=abs(bass);a[0]=11;a[1]=data%10;}
    if(bass<=-10){data=abs(bass);a[0]=12;a[1]=data%10;}
    if(bass>=0){data=bass;a[0]=data/10;a[1]=data%10;}
    }
  if(menu==2){bassf=0;
    if(treb>=-9&&treb<=-1){data=abs(treb);a[0]=11;a[1]=data%10;}
    if(treb<=-10){data=abs(treb);a[0]=12;a[1]=data%10;}
    if(treb>=0){data=treb;a[0]=data/10;a[1]=data%10;}
    }  
  if(menu==3){a[0]=10;a[1]=10;}  
  

 if(ir.value==IR_8 && power==1){k=1;power=0;menu=0;cl1();}
 if(ir.value==IR_8 && power==0){k=1;power=1;cl1();}
 if(power==0&&k==1){k=0;mute=1;audio();}
 if(power==1&&k==1){k=0;mute=0;audio();menu=3;in1=0;in2=0;ddd=0;} 

 
 if(millis()-times>5000&&power==0){w=0;bassf=0;trebf=0;menu=0;
   EEPROM.update(0,volume);EEPROM.update(1,in);EEPROM.update(2,bass+15);EEPROM.update(3,treb+15);EEPROM.update(4,sur_3d);
   }

 
 }// loop
void vol_conf(){if(volume<0){volume=0;}if(volume>84){volume=84;}} 
void v_old(){if(old_vol!=volume){menu=0;bassf=0;trebf=0;power=0;}} 
void inn(){if(in==1){in1=1;in2=0;}if(in==2){in2=1;in1=0;}}
void cl1(){ir.value=0;delay(200);w=1;times=millis();audio();}
void pin0(){pinMode(A1,INPUT);pinMode(A2,INPUT);pinMode(A3,INPUT);pinMode(2,INPUT);pinMode(3,INPUT);pinMode(4,INPUT);pinMode(5,INPUT);  
    pinMode(6,INPUT);pinMode(7,INPUT);pinMode(8,INPUT);pinMode(9,INPUT);pinMode(13,INPUT);} 
void pin1(){
    pinMode(A3,OUTPUT);pinMode(A2,OUTPUT);pinMode(2,OUTPUT);pinMode(3,OUTPUT);pinMode(4,OUTPUT);pinMode(5,OUTPUT);pinMode(6,OUTPUT);  
    pinMode(7,OUTPUT);pinMode(8,OUTPUT);pinMode(9,OUTPUT);pinMode(13,INPUT); pinMode(A1,INPUT);  }  
void audio(){            
  r2s.setVol_l(volume);  // volume left >> int 84...0 === -84...0 dB
  r2s.setVol_r(volume);  // volume_right >> int 84...0 === -84...0 dB
  r2s.setInput(in, 1, mute);     
             // input >> int 0 === all off | int 1...5 === input 1...5 
             // gain >> int 0...1 === 0 dB...+4.5 dB
             // mute >> int 1...0 === mute off...mute on
  r2s.set_Bass(sur_3d, 3, bass);
             // surround mode >> int 0...1 === low level...high level
             // mode selector >> int 0...3 === bypass tone tone&Pseudo_stereo tone&Surround
             // tone control bass >> int -15...15 === -15dB...+15dB
  r2s.set_Treb(treb);   // tone control treble >> int -15...15 === -15dB...+15dB
} 

ISR(TIMER2_OVF_vect){
  switch(i){
    case 0: pin1();segm = 10;segment();segm=a[0]; an=0; anod(); segment();break;
    case 1: pin1();segm = 10;segment();segm=a[1]; an=1; anod(); segment();break;
    case 2: pin0();pinMode(A1,OUTPUT);
              if(power==1){pinMode(8,OUTPUT);ch(8,1);ch(A1,0);}
              if(bassf==1){pinMode(5,OUTPUT);ch(5,1);ch(A1,0);}
              if(trebf==1){pinMode(4,OUTPUT);ch(4,1);ch(A1,0);}
              if(in2==1){pinMode(13,OUTPUT);ch(13,1);ch(A1,0);}
              if(ddd==1){pinMode(2,OUTPUT);ch(2,1);ch(A1,0);}
            break;
    case 3: pin0();pinMode(A3,OUTPUT);
              if(in1==1){pinMode(13,OUTPUT);ch(13,1);ch(A3,0);}            
    }
    i++;if(i>3){i=0;}
  
  bool pinA = digitalRead(10);
  bool pinB = digitalRead(11);
   _currValueAB  = pinA << 1;
   _currValueAB |= pinB;
   switch ((_prevValueAB | _currValueAB)){
    case 0b0001: _counter++;break;
    case 0b0100: _counter--;break;
  }
  _prevValueAB = _currValueAB << 2;     
  }
 
int16_t getPosition(){return _counter;}
void setPosition(int16_t position){_counter = position;}
void segment(){
  switch(segm){                                                                 
             //  A       B       C       D       E       F       G  
    case 0: ch(4,1);ch(8,1);ch(9,1);ch(6,1);ch(7,1);ch(5,1);ch(2,0);break;// 0 
    case 1: ch(4,0);ch(8,1);ch(9,1);ch(6,0);ch(7,0);ch(5,0);ch(2,0);break;// 1
    case 2: ch(4,1);ch(8,1);ch(9,0);ch(6,1);ch(7,1);ch(5,0);ch(2,1);break;// 2
    case 3: ch(4,1);ch(8,1);ch(9,1);ch(6,1);ch(7,0);ch(5,0);ch(2,1);break;// 3   
    case 4: ch(4,0);ch(8,1);ch(9,1);ch(6,0);ch(7,0);ch(5,1);ch(2,1);break;// 4 
    case 5: ch(4,1);ch(8,0);ch(9,1);ch(6,1);ch(7,0);ch(5,1);ch(2,1);break;// 5 
    case 6: ch(4,1);ch(8,0);ch(9,1);ch(6,1);ch(7,1);ch(5,1);ch(2,1);break;// 6 
    case 7: ch(4,1);ch(8,1);ch(9,1);ch(6,0);ch(7,0);ch(5,0);ch(2,0);break;// 7 
    case 8: ch(4,1);ch(8,1);ch(9,1);ch(6,1);ch(7,1);ch(5,1);ch(2,1);break;// 8
    case 9: ch(4,1);ch(8,1);ch(9,1);ch(6,1);ch(7,0);ch(5,1);ch(2,1);break;// 9 
    case 10: ch(4,0);ch(8,0);ch(9,0);ch(6,0);ch(7,0);ch(5,0);ch(2,0);break;//
    case 11: ch(4,0);ch(8,0);ch(9,0);ch(6,0);ch(7,0);ch(5,0);ch(2,1);break;// - 
    case 12: ch(4,0);ch(8,1);ch(9,1);ch(6,0);ch(7,0);ch(5,0);ch(2,1);break;// -1 
  }}
void anod(){
  switch(an){                                                             
    case 0:ch(A2,0);ch(A3,1);  break;  
    case 1:ch(A2,1);ch(A3,0);  break; 
  }}
void ch(int pin, int logic){digitalWrite(pin,logic);}

http://forum.rcl-radio.ru/uploads/images/2022/11/1590966b891c0d7f8ded353ca123fc30.png

4

Re: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Александр из скетча понял что кнопкой управляется только выбор входа. Так же как в стоковом варианте этого устройства. Хотелось бы что бы этой кнопкой можно было не только управлять переключением входов, но и регулировкой высоких и низких частот.

5

Re: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Не вижу возможности как совместить кнопку выбора входа с регулировкой тембра. В оригинале эта кнопка управляет только селектором входов, регулировка тембра только с пульта. Если бы энкодер был с кнопкой, тогда проблем бы не было реализовать регулировку тембра, но в АС применяется энкодер без кнопки.

Но какие то переделки более не предполагаются, проект завершен, функционал АС полностью восстановлен.

6

Re: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Например в штатном режиме  энкодером идет управление громкостью , первое короткое нажатие на кнопку регулировка высоких частот энкодером, второе короткое нажатие нажатие регулировка низких частот энкодером. Длительное нажатие на кнопку переключение  входа. В стандартном функционале этой акустической системы это не  реализовано, только регулировка громкости всё остальное через пульт, а он как правило не всегда есть под рукой.

7

Re: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Я подумаю над этим, но есть другая проблема:

Скетч использует 15774 байт (99%) памяти устройства. Всего доступно 15872 байт.

8

Re: Восстановление MICROLAB FC550 (Управление - замена микроконтроллера)

Можно под  атмегу 328 или ее клон китайских братьев тем более что LGT8F328P довольно дешевле оригинала