Bypassing IR control on HDMI switcher

So I bought a cheap HDMI switcher that has an IR receiver and remote attachment that I'm wanting to bypass. The IR receiver plugs in to the switcher using an 1/8" headphone jack, my goal is to just plug the arduino directly into that jack and send hardwired signals captured from the remote to the switcher to choose which hdmi feed is outputting.

I'm aware that I could simply add an IR led and fit all the components next to each other in the case. I'm wanting to hardwire this directly, bypassing the IR altogether, so I don't have to worry about the LED becoming unaligned with the receiver, or any other signal problems that could arise from not having it hardwired.

The goal of this is to control the HDMI switcher from a computer over USB.

EDIT: I uploaded some images of the HDMI switcher and IR receiver that came with it. Imgur: The magic of the Internet

The pink cable plugged into the board is my arduino, where the IR receiver should plug into

Someone else had essentially the same question:
http://forum.arduino.cc/index.php?topic=300886.msg2095975#msg2095975

Use the IRremote library examples to decode the remote control.

Cool looking switcher...looks like it could have a multitude of other switching uses!

What is the model number of that HDMI switcher / Link?
If possible, could you post the model#s of the 2 main chips on that board...tnx

As John said follow the link & beware that IR receivers output inverted logic.

Thanks for the reply, I've looked at that post and some others on the forum and I think I'm still missing something.

Also, here is the HDMI switcher I'm working with if it helps. HDMI 5x1 Switch (5-In to 1-Out) | HDMSWITCH5X1 | Cirago

Here is what I have attempted to do so far. I've used Ken Shirriffs IRemote library, along with the receiver from the HDMI switch, to access the codes from the remote. The codes appear to be in an unknown format, so I will have to send the raw data.

The remote has codes to switch to each input 1-5 and a button to just cycle the inputs. I've copied the code to cycle the switcher and am trying to send it back via hardwire.

This next part is where I get lost. I've tried taking the 3 wires from where the IR receiver plugs in (red,black,white) and hardwiring them to the arduino. Red to nothing, Black to GND, and the White line to the output pin(3) from the arduino. This did not affect the HDMI switch, whereas the remote would cycle the inputs.

After searching around for other options I went and picked up an Optocoupler (NTE3045 an NPN Darlington) and tried to send the signal from the arduino, through it. I connected the anode to the output(3), and cathode to GND. Then the Positive lead from the HDMI to the collector, and the signal line from the HDMI to the emitter. This also hasn't done anything so far.

In both of the above attempts I was using a modified version of the IR library's IRrecord example.

I've also taken the Hex value (87EAA93D) of the command I am trying to send, and made a simple Serial.write() function to send the value over the signal wire. Signal line to the TX on the arduino, and the GND to GND. Again, nothing has happened.

I'm pretty confused, and any guidance would be much appreciated. Do any of these approaches seem like I am on the right track?

I'll try and make sketches of the circuits I used tomorrow.

Maybe it would be easier to start if someone could help me narrow down which approach I should be trying first. I feel like maybe because I'm jumping between different ideas i'm making mistakes.

First of all:

  • what voltage is the switch running at and also the Arduino? Same?
  • Because IR receivers provide an inverted signal at the output pin, you need to somehow invert the signal you are putting into the switch
  • Because IR receivers de-modulate the signal, you also need to provide a de-modulated signal. IRremote outputs a modulated signal.

The best way to achieve this is to make code changes to IRremote to output an inverted de-modulated signal, as has been covered previously.

A good starting point would be to post a wiring diagram with voltages.

For a good introduction to IR remote control, visit this site:

wystem:
I've also taken the Hex value (87EAA93D) of the command I am trying to send, and made a simple Serial.write() function to send the value over the signal wire. Signal line to the TX on the arduino, and the GND to GND. Again, nothing has happened.

Ignore the hex value. If the signal format is not known you have to send the RAW pulses.
Ignore the first RAW value. That's just the time between the IR receiver starting to watch for a signal and the time the synchronizing 'MARK' arrived. From the second value (long synchronizing MARK) onward you alternate turning the signal LOW for MARK and HIGH for SPACE. The RAW pulse lengths are in microseconds so use delayMicroseconds() after each change. It doesn't matter which pin you use for output. The library uses a specific pin because it needed a timer output to generate the carrier frequency.
The library samples every 50 microseconds so the RAW pulse widths are always in intervals of 50 microseconds. Usually after the first long MARK there are only two or three pulse widths used. If you find a bunch of 250 microsecond pulses and a few 300 microsecond pulses you might want to change them all to 250 or 260. Likewise if the other pulses are mostly 600 with a few 550's you might want to use 600 or 590 for all of them. It just makes for a cleaner signal. :slight_smile:

Based on John's code example from the IR library, I've come up with these values for sending my code.

I'm still not able to cause effect to the switcher.

// pulse parameters in usec
#define HDR_MARK	8800
#define HDR_SPACE	4600
#define BIT_MARK	400
#define ONE_SPACE	1800
#define ZERO_SPACE	700

#define TOPBIT 0x80000000

const int OutputPin = 11;

void send() {
  Serial.println("Sending");
  mark(HDR_MARK);
  space(HDR_SPACE);

  
  for (int i = 0; i < 7; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 8; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
  for (int i = 0; i < 1; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 5; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
   for (int i = 0; i < 8; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 3; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
  mark(BIT_MARK);
  space(0);
}

void mark(int time) {
  digitalWrite(OutputPin, LOW);
  delayMicroseconds(time);
}

void space(int time) {
  digitalWrite(OutputPin, HIGH);
  delayMicroseconds(time);
}


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(OutputPin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    char inChar = Serial.read();
    if(inChar == 33 ){
      
      send();
      
    }
  }
}

I have also attached a simple image of how I am connecting my arduino to the HDMI switcher. The IR receiver in the sketch represents the connections on the board, not the receiver itself.

The switcher is using 5v, and the two chips on board are these 3:1 hdmi/dvi switches

// pulse parameters in usec

#define HDR_MARK 8800
#define HDR_SPACE 4600
#define BIT_MARK 400
#define ONE_SPACE 1800
#define ZERO_SPACE 700

These look like NEC protocol timings & if so the correct values are:
9000, 4500, 560, 1690, 560 respectively.

No need to change if its working (particularly as you are directly wired-up), but less chance of errors with the correct times.

One more Q:

How do you know which pin is 5v and which pin is GND in the switcher?

Does the switcher have an LED to indicate it is receiving an "IR" signal?

If you set OutputPin to 13 does the LED on the Arduino blink when you tell it to send?

What does the example sketch IRrecvDump display when you use the original remote?


That's the receiver that came with the switcher, I followed the wires back to the board.

The switcher does not have anything to indicate it is receiving commands, but there are 5 LED's on top showing which output is selected. The code I am trying to send should cycle between the inputs, so I should see the LEDs change if the correct code is submitted.

But nothing to say it is receiving codes, but not the correct codes.

when I change the output to 13, the LED lights up and stays light, it does not blink or turn off.

the IRrecvDump:

1FEF807
Decoded NEC: 1FEF807 (32 bits)
Raw (68): -20130 8900 -4500 500 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -1650 550 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -1700 550 -1650 550 -600 550 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -1650 550 -1700 500 -1700 550
1FE
Decoded JVC: 1FE (16 bits)
Raw (68): -23906 8900 -4450 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 500 -1700 550 -1700 500 -1700 550 -1700 500 -1700 550 -1650 550 -1700 500 -1700 550 -600 550 -1700 500 -1700 550 -1650 550 -1700 500 -1700 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 500 -650 500 -650 500 -1700 550 -1700 500 -1700 550
87EAA93D
Unknown encoding: 87EAA93D (32 bits)
Raw (68): -11838 8900 -4500 550 -600 550 -600 550 -600 500 -650 500 -650 500 -650 500 -650 500 -1700 550 -1700 500 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -1700 550 -600 550 -1650 550 -1700 500 -1650 600 -1700 500 -1700 550 -600 550 -600 500 -650 500 -650 500 -650 500 -650 500 -650 500 -600 550 -1700 500 -1700 550 -1700 500
87EAA93D
Unknown encoding: 87EAA93D (32 bits)
Raw (68): -8902 8900 -4500 500 -650 500 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -1700 500 -1700 550 -1700 500 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -600 550 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -1650 550 -1700 500 -1700 600
1FEF807
Decoded NEC: 1FEF807 (32 bits)
Raw (68): 4558 8900 -4450 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -1700 500 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -1700 550 -1650 550 -600 550 -1700 500 -1700 550 -1700 500 -1700 550 -1650 550 -600 650 -500 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 500 -1700 550 -1700 500 -1700 550
87EAA93D
Unknown encoding: 87EAA93D (32 bits)
Raw (68): 20346 8900 -4500 500 -650 500 -600 550 -650 500 -600 550 -600 550 -600 550 -600 550 -1700 500 -1700 550 -1650 550 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -600 550 -1700 500 -1700 550 -1700 500 -1700 550 -1700 500 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -600 550 -1650 550 -1700 500 -1700 550

That's me pressing the same button multiple times with a pause in between.

I have now tried updating the timings to be NEC, still no luck.

set outputpin HIGH in the setup function. otherwise your first signal will always fail.

You code seems to be sending 0x01FEF807, based on a quick review - which seems correct.

As it is NEC, stick with the timings I posted.

Ignore any captures that are not 32 bits.

There is a possibility that it is also expecting one repeat signal, but best to exclude other stuff first.

Thanks for your assistance so far, here's the updated code so far

// pulse parameters in usec
#define HDR_MARK	9000
#define HDR_SPACE	4500
#define BIT_MARK	560
#define ONE_SPACE	1690
#define ZERO_SPACE	560

const int OutputPin = 13;

void send() {
  Serial.println("Sending");
  mark(HDR_MARK);
  space(HDR_SPACE);

  
  for (int i = 0; i < 7; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 8; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
  for (int i = 0; i < 1; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 5; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
   for (int i = 0; i < 8; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 3; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
  mark(BIT_MARK);
  space(0);
}

void mark(int time) {
  digitalWrite(OutputPin, LOW);
  delayMicroseconds(time);
}

void space(int time) {
  digitalWrite(OutputPin, HIGH);
  delayMicroseconds(time);
}


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(OutputPin, OUTPUT);

  
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    char inChar = Serial.read();
    if(inChar == 33 ){
      digitalWrite(OutputPin, HIGH);
      send();
      digitalWrite(OutputPin, LOW);
    }
  }
}

I also made it so it makes the pin HIGH before issuing the send command, and LOW after.

Something is still wrong though, the switcher is still not changing.

OK

I loaded your script up to a UNO & there is a slight wobble in the LED when 13 is configured (when sending).

I also checked it on the scope and it looks fine.

Q: What character are you sending over serial to kick off each transmission?

    if(inChar == '!' ){ //easier to see the actual char
      //////////////////digitalWrite(OutputPin, HIGH);
      send();
      ////////////////////digitalWrite(OutputPin, LOW);
    }

See suggested changes above

Also, make sure you are using pin 11 when testing the correct timings & put

digitalWrite(OutputPin, HIGH);

into the setup function

// pulse parameters in usec
#define HDR_MARK	9000
#define HDR_SPACE	4500
#define BIT_MARK	560
#define ONE_SPACE	1690
#define ZERO_SPACE	560

#define TOPBIT 0x80000000

const int OutputPin = 11;

void send() {
  Serial.println("Sending");
  mark(HDR_MARK);
  space(HDR_SPACE);

  
  for (int i = 0; i < 7; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 8; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
  for (int i = 0; i < 1; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 5; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
   for (int i = 0; i < 8; i++) {
      mark(BIT_MARK);
      space(ZERO_SPACE);
  }
  for (int i = 0; i < 3; i++) {
      mark(BIT_MARK);
      space(ONE_SPACE);
  }
  mark(BIT_MARK);
  space(0);
}

void mark(int time) {
  digitalWrite(OutputPin, LOW);
  delayMicroseconds(time);
}

void space(int time) {
  digitalWrite(OutputPin, HIGH);
  delayMicroseconds(time);
}


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(OutputPin, OUTPUT);
digitalWrite(OutputPin, HIGH);

  
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    char inChar = Serial.read();
    if(inChar == '!' ){
      //digitalWrite(OutputPin, HIGH);
      send();
      //digitalWrite(OutputPin, LOW);
    }
  }
}

Changed the pin back to 11, put the digitalwrite back into the setup function, made the serial ascii more readable. Still no luck.

Is it possible I'm wiring the uno to the switcher incorrectly? The receiver has 3 pins that plug into the switcher, of those I'm only using the ground and signal wire.

post a photo of your wiring etc

Just as I said that I was checking one of the cables I was using and the signal/positive wires were backwards.

It's working now! Thanks John and AnalysIR very helpful