senden der RC1 codes mit Arduino

Sämtliche Gerätetypen Braun atelier
Antworten
Nachricht
Autor
sven.schnelle
Foren-As
Foren-As
Beiträge: 105
Registriert: 13.09.2017, 08:18

senden der RC1 codes mit Arduino

#1 Beitrag von sven.schnelle » 13.09.2017, 08:56

Hallo,

da ich meine Braun Anlage mit einer Universalfernbedienung bedienen will, und keine RC1 habe (hat mir optisch nie gefallen, und ich möchte nur zum Tasten kopieren keine kaufen), habe ich mir schnell mit einem Arduino MEGA2560 Board eine Software geschrieben mit dem man die Codes senden kann. An Hardware ist nur eine Infrarot LED gegen 5V an Pin 9 notwendig. Man kann ueber serielle Schnittstelle einen Tastencode eingeben, der dann gesendet wird. Die Codes sind gleich mit den Codes fuer die serielle Schnittstelle am R4/CC4:

Code: Alles auswählen

01 - 5
02 - 4
03 - 3
04 - 2
05 - 1
06 - Prog +
07 - Prog -
08 - Memo
09 - P10
0a - 9
0b - 8
0c - 7
0d - 6
0e - TAPE1
0f - TAPE2
10 - TREB OFF
11 - FORWARD
12 - REWIND
13 - STOP
14 - PAUSE
15 - START
16 - ?
17 - LBASS
18 - H BLEND
19 - RESET
1a - SET
1b - MEMO
1c - SPACE
1d - REC
1e - MAN TUNE +
1f - MAN TUNE -
20 - BASS OFF
21 - SP1/2 3/4
22 - CLOCK
23 - MONO
24 -
25 - MONITOR
26 - BASS+
27 - BASS-
28 - BAL RESET
29 - BAL R
2a - BAL L
2b - TREB OFF
2c - BASS OFF
2d - LOUDN
2e - TREB +
2f - TREB -
30 - 20 HZ
31 - STBY
32 - VOL+
33 - VOL-
34 - MUTE
35 - EQ OFF
36 - VOL2+
37 - VOL2-
38 - AM
39 - T-
3a - TV
3b - AM/FM
3c - PHONO
3d - CD
3e - SPEAKER 1
3f - SPEAKER 2
Die Software:

Code: Alles auswählen

void setup()
{
  Serial.begin(115200);
  pinMode(3, OUTPUT);
  pinMode(9, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS21);
  OCR2A = 0;
  OCR2B = 39;
}

void send_bit(uint16_t state)
{
  OCR2A=59;
  delayMicroseconds(160);
  OCR2A=0;
  // H: 8.64ms, L=5.76ms
  delayMicroseconds(state ? 8340: 5500);
}

volatile uint8_t gtoggle = 0;

void transmit_recs80(uint8_t dev, uint8_t toggle, uint8_t command)
{
  uint8_t i;
  uint16_t val = (1 << 11) | (toggle << 10) | ((dev & 7) << 7) | ((command & 0x3f) << 1);
  for(i = 0; i < 12; i++) {
      send_bit(val & (1 << (11 - i)));
  }
}

void loop()
{
  int i;
  String s;
  uint8_t val;
  for(;;) {
    s = Serial.readStringUntil('\n');
    if (s.length() > 0) {
      val = strtoul(s.c_str(), NULL, 16);
      Serial.println(val, 16);
      for(i = 0; i < 16; i++) {
        transmit_recs80(2, gtoggle, val);
        delay(52);
      }
    gtoggle ^= 1;
  }
    
  }
}
Vielleicht ist das ja fuer den einen oder anderen nuetzlich.

Benutzeravatar
Paparierer
Moderator
Moderator
Beiträge: 2607
Registriert: 28.12.2010, 15:36
Wohnort: 85077 Manching

Re: senden der RC1 codes mit Arduino

#2 Beitrag von Paparierer » 13.09.2017, 09:22

Moin.
Bedeutet das, Du sagst mit den Nummerntasten Deiner Universalfernbedienung dem Arduino, er soll das entsprechende Signal senden?
Oder bedienst Du den Arduino über Tastatur und gibst im Zehnerblock den Code ein?
Gruß, Gereon
_______________________________
meistens ist es was mechanisches...
_______________________________
The price of anything is the amount of life you exchange for it.
Henry David Thoreau

sven.schnelle
Foren-As
Foren-As
Beiträge: 105
Registriert: 13.09.2017, 08:18

Re: senden der RC1 codes mit Arduino

#3 Beitrag von sven.schnelle » 13.09.2017, 09:31

Hallo,

ich gebe mit dem Computer den Code in den Arduino ein, und der Arduino sendet dann den entsprechenden Code.

Viele Grüße
Sven

Benutzeravatar
eleflo
Foren-As
Foren-As
Beiträge: 108
Registriert: 17.11.2011, 23:50
Wohnort: 70191 Stuttgart
Kontaktdaten:

Re: senden der RC1 codes mit Arduino

#4 Beitrag von eleflo » 28.10.2017, 00:27

Hallo Sven,

hast du dich zufällig auch mal mit dem Empfang der RC1 Codes über einen Arduino beschäftigt?

Gruß Flo
Gruß Flo

sven.schnelle
Foren-As
Foren-As
Beiträge: 105
Registriert: 13.09.2017, 08:18

Re: senden der RC1 codes mit Arduino

#5 Beitrag von sven.schnelle » 28.10.2017, 22:17

Hallo eleflo,
eleflo hat geschrieben: hast du dich zufällig auch mal mit dem Empfang der RC1 Codes über einen Arduino beschäftigt?
Ja, habe ich - wobei ich nicht sagen wie stabil das ganze funktioniert, aber bevor ich mit dem senden der Codes angefangen habe, hatte ich ein kleines Testprogramm zum empfangen geschrieben. Da ist allerdings schon etwas code mit drin um die Audioprozessoren zu programmieren, aber vielleicht hilft dir das ja als Grundlage:

Code: Alles auswählen

static volatile uint8_t ir_bitcnt = 0;
static volatile uint16_t ir_cmd;
static volatile uint16_t times[32];
static volatile uint8_t tmp_bitcnt;
static volatile uint8_t tmo = 0;

#define STR7976 40
#define STR789 43
#define CLOCK 45
#define DATA 47

static void icp_setup(void)

{
  TCCR4A = 0;
  TCCR4B = _BV(CS41);
  TIMSK4 = _BV(ICIE4) | _BV(TOIE4);
  
  TCCR1A = 0;
  TCCR1B = _BV(CS10) | _BV(CS11);
  TIMSK1 = _BV(TOIE1);
}

void setup()
{
  Serial.begin(115200);
  pinMode(30, INPUT);
  digitalWrite(STR7976, 0);
  digitalWrite(STR789, 0);
  digitalWrite(CLOCK, 0);
  digitalWrite(DATA, 0);
  
  pinMode(STR7976, OUTPUT);
  pinMode(STR789, OUTPUT);
  pinMode(CLOCK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(7, OUTPUT);
  icp_setup();
}
#define DELAY 300

void send_789(uint16_t value)
{
  int i;
  for(i = 0; i < 16; i++) {
    digitalWrite(DATA, !(value & (0x8000 >> i)));
    delayMicroseconds(DELAY);
    digitalWrite(CLOCK, 1);
    delayMicroseconds(DELAY);
    digitalWrite(CLOCK, 0);
    delayMicroseconds(DELAY);
  }
  digitalWrite(DATA, 0);
  delayMicroseconds(DELAY);
  digitalWrite(STR789, 1);
  delayMicroseconds(DELAY*2);
  digitalWrite(STR789, 0);
}


void send_7976(uint16_t value)
{
  int i;
  for(i = 0; i < 11; i++) {
    digitalWrite(DATA, !(value & (0x400 >> i)));
    delayMicroseconds(DELAY);
    digitalWrite(CLOCK, 1);
    delayMicroseconds(DELAY);
    digitalWrite(CLOCK, 0);
    delayMicroseconds(DELAY);
  }
  digitalWrite(DATA, 0);
  delayMicroseconds(DELAY);
  digitalWrite(STR7976, 1);
  delayMicroseconds(DELAY*2);
  digitalWrite(STR7976, 0);
}

uint16_t encode789_volume(int left, int right)
{
  uint16_t ret = 0x8080;
  
  ret |= (left % 10) + 6;
  ret |= ((right % 10) + 6) << 8;
  ret |= (left / 10) << 4;
  ret |= (right / 10) << 12;
  return ret;
}

uint16_t encode789_contro(int input, int monitor, int mute, int treble, int bass)
{
  uint16_t ret = 0x4200;
  
  ret |= ((input & 3) << 14);
  ret |= ((monitor & 3) << 10);
  ret |= ((mute & 1) << 8);
  ret |= ((treble & 15) << 4);
  ret |= (bass & 15);
  return ret;
}

void loop()
{
  uint16_t tmp;
  static uint8_t vol = 20;

  if (ir_cmd & 0x8000) {
    Serial.println(ir_cmd & 0x3f, HEX);
    //tmp = encode789(0, 1, 1, 0x9, 0xa);
    //Serial.println(tmp, HEX);
    //send_789(0xa7a7);
    switch(ir_cmd & 0x3f) {
      case 0x36:
        /* Volume up */
        vol++;
        if (vol > 80)
          vol = 80;
        break;
      case 0x37:
        /* volume down */
        if (vol > 0)
          vol--;
      case 0x34:
        send_7976(0x0091);
        send_7976(0x0051);
        break; 
      default:
         break;     
    }
    //send_789(encode789_volume(vol, vol));
    ir_cmd = 0;
  }
}

ISR(TIMER4_CAPT_vect)
{
  uint16_t val = ICR4;
  bool rising_edge = TCCR4B & _BV(ICES4);
  
  TCCR4B ^= _BV(ICES4);
  TCNT4 = 0;
  TIFR4 |= _BV(ICF4);

  if (ir_cmd & 0x8000)
      return;

  if (ir_bitcnt == 0 && !rising_edge) {
    if (val > 20000)
      ir_bitcnt++;
    /* ignore first falling edge */
    return;
  }

  if ((rising_edge && (val < 200 || val > 800)) ||
     ((!rising_edge && (val < 10000 || val > 18000)))) {
       /* invalid bit length */
        ir_bitcnt = 0;
        ir_cmd = 0;
        return;
  }
  
  /* data is only encoded in the low bit length */
  if (rising_edge)
      return;

  ir_cmd |= (((val > 13000) ? 1 : 0) << (11-ir_bitcnt));
  ir_bitcnt++;
  
  if (ir_bitcnt == 12) {
    ir_cmd |= 0x8000;
    ir_bitcnt = 0;
  }
}

ISR(TIMER4_OVF_vect)
{
  int i;
  TCCR4B &= ~_BV(ICES4);
  TIFR4 |= _BV(ICF4);
  TCNT4 = 0x20001;
  ir_bitcnt = 0;
  ir_cmd = 0;
}

ISR(TIMER1_OVF_vect)
{
  static int value;
  TCNT1 = 0xcf20;
  value ^= 1;
  digitalWrite(7, value);
}

Viele Grüße
Sven

braunb@r
Experte
Experte
Beiträge: 258
Registriert: 30.09.2016, 22:17
Wohnort: Erkrath bei Düsseldorf

Re: senden der RC1 codes mit Arduino

#6 Beitrag von braunb@r » 26.10.2018, 13:57

Hallo Sven,

ich habe deine Codes auf einen Arduino Uno umgesetzt, und es läuft.
Ich kann die IR Signale dekodieren und ich kann auch welche senden.

ich habe da noch eine Frage zu deinem Sendecode.
Im Bereich send_bit werden ja die Pulse für die IR-Diode erzeugt. Du hast auch in einer Kommentarzeile die Delayzeiten für ein High und ein Low angegeben.
Wenn ich aber von diesen Zeiten die 160us für den Burst abziehe, kommen etwas höhere Werte raus als du bei delayMicroseconds warten lässt. Hat das einen tieferen Grund?

MfG

Rainer

Antworten