Ethernet multi-function Interface


From SamyGO
Revision as of 13:30, 30 June 2012 by Oga83 (talk | contribs)
Jump to: navigation, search

Using an Arduino Ethernet board, you can send IR codes to your TV or BD

With the same board, you can also interface to the Serial Console.


What you can do

  • Send IR codes to your TV, PVR or BD, with an URL in your browser
  • Use telnet to have the Serial Console on your PC or smartphone


Arduino interface.jpg


Bill of materials

  • Arduino Ethernet board (see Arduino)

Alternatively, an Arduino Uno with an Ethernet shield could also be used

  • IR led (SFH4510 for example)
  • 220 ohms resistor to limit current in the IR led
  • If you plan to use the telnet interface to the Serial Console, make sure you have a 100 ohms resistor on both RX and TX signals (Arduino TX/RX are 5v !)


How to use it

  • Upload the following sketch into your Arduino
  • Connect the IR led with its resistor on pin 8 on the Arduino
  • Connect power and network
  • Find the IP address of the board on your DHCP (or use the static IP embedded in the sketch if you don't have DHCP)
  • Use your browser to send an URL to the board (see format below)
  • If you want to use telnet to connect to the Serial Console :
  • Connect your Serial Console signals to RX/TX on the Arduino board (with 100 ohms resistors)
  • Use Putty with options 'Local Echo' and 'Local line editing' forced to OFF


URL format to send IR codes

The format is http://IP/ir.htm?data=XX&type=Y&device=ZZZZ where

  • IP is the Arduino board IP address
  • XX is the IR code to send
  • Y is 0 for TV/PVR frame format and 1 for BD frame format
  • ZZZZ is the device code (0707 for TV, 0505 for PVR, 301A for BD)


The IR codes are listed at Key codes

  • For TV/PVR, use the 'code' column
  • For BD, use the 'BD-IR code' column


Examples

To get the Service Menu on your TV, use the 2 following URLs :

Please note that you cannot send KEY_FACTORY to a BD, as the corresponding code is not know yet


To have a kind of Wake Up on LAN on your BD player, use


To switch to channel 1 :


IR frames format

BD players use a modified IR frame format that TV and PVR. The reason is that samsung increased the data field length from 8 to 12 bits The general format is now :

  • Start bit
  • Device ID (16 bits - 0707 for TV, 301A for BD)
  • For BD only : Stop bit and data MSB on 4 bits
  • Data LSB
  • Data LSB 1's complement


A frame for BD :

335px‎


Arduino sketch

 // ---------------------------------------------------------------------
 // Samsung IR and Serial Console Ethernet Interface
 // 29-06-2012 / Initial version / oga83
 //----------------------------------------------------------------------
 
 #include <SPI.h>
 #include <Ethernet.h>
 
 #define IRPIN      8    // IR led is connected on pin 8
 #define LEDPIN     9    // Onboard led - blink at 2 Hz
 
 byte mac[] = { 0x90, 0xA2, 0xda, 0x00, 0xe6, 0x5e }; // Arduino Ethernet board MAC address
 
 IPAddress ip(192,168,1,178);     // Default static IP if no DHCP 
 EthernetServer HttpServer(80);   // HTTP is used to send IR commands
 EthernetServer TelnetServer(23); // Telnet is used for Serial Console
 
 
 // Convert a hex string to unsigned int
 unsigned int HexToUInt(char *s)
 {
   unsigned u=0;
   while (*s)
   {
     char c=*s++;
     // Convert to uppercase
     if (c>='a') c&=0xdf;
     // Exit if not hex digit
     if ((c<'0' || c>'9') && (c<'A' || c>'F')) break;
     // Convert digit
     u<<=4;
     u|=c-((c>'9') ? 'A'-0xa:'0');
   }
   return u;
 }
 
 
 // ---------------------------------------------------------------------
 // Samsung IR class
 // ---------------------------------------------------------------------
 
 class Samsung
 {
   private:
   // Send a 36kHz-modulated pulse
   static void Pulse(void)
   {
     byte i;
     for (i=0; i<21; i++)
     {
       digitalWrite(IRPIN, HIGH);
       delayMicroseconds(10); // Value adjusted with oscilloscope
       digitalWrite(IRPIN, LOW);
       delayMicroseconds(10); // Value adjusted with oscilloscope
     }
   }
   // Send a bit
   static void SendIRBit(byte b)
   {
     Pulse(); 
     if (b) 
       delayMicroseconds(1390);
     else
       delayMicroseconds(430);
   }
   // Send 4 bits
   static void SendIRNibble(byte b)
   {
     byte i;
     for (i=0; i<4; i++)
       SendIRBit((b>>i)&1);
   }
   // Send a byte
   static void SendIRByte(byte b)
   {
     byte i;
     for (i=0; i<8; i++)
       SendIRBit((b>>i)&1);
   }
 
   public:
   // Send an IR command
   // Type is 0 for TV, 1 for BD
   // Device is 0x0707 for TV, 0x301A for BD
   static void SendCommand(char Type, unsigned int Device, unsigned int Command)
   {
     byte i;
    
     // Disable interrupts
     cli();
   
     // Start bit
     for (i=0; i<8; i++)	Pulse();
     delayMicroseconds(4500);
 
     // Send Device Id
     SendIRByte(Device>>8);
     SendIRByte(Device&0xff);
 
     // BD Player
     if (Type==1)
     {
       // Stop bit
       Pulse();
       delayMicroseconds(4500);
       // Send Data
       SendIRNibble(Command>>8);
     }
     
     SendIRByte(Command);
     SendIRByte(~Command);
 
     // Stop bit
     Pulse();
     delayMicroseconds(4500);
   
     // Re-enable interrupts
     sei();
   }
 };
 
 
 // ---------------------------------------------------------------------
 // Initialization
 // ---------------------------------------------------------------------
 
 void setup()
 {
   // Led
   pinMode(LEDPIN, OUTPUT);
   digitalWrite(LEDPIN, HIGH);
 
   // IR Led
   pinMode(IRPIN, OUTPUT);
   digitalWrite(IRPIN, HIGH);
 
   // Serial Console
   Serial.begin(115200);
 
   // Initialize Ethernet. Try DHCP, otherwise static IP
   if (Ethernet.begin(mac)==0)
     Ethernet.begin(mac, ip);
   // Initialize HTTP server
 
   HttpServer.begin();
   // Initialize Telnet server
   TelnetServer.begin();
 }
 
 
 // ---------------------------------------------------------------------
 // Main Program
 // ---------------------------------------------------------------------
 
 char NetworkFrame[256];        // General buffer for frames
 boolean iStateLed=false;       // Used for led blinking
 unsigned long timeLastLedMs=0; // Used for blinking delay
 
 void loop()
 {
   // -------------------------------------------------
   // LED blinks at 2Hz
   // -------------------------------------------------
   if (millis()>timeLastLedMs+250)
   {
     timeLastLedMs=millis();
     digitalWrite(LEDPIN, (iStateLed) ? HIGH:LOW);
     iStateLed=!iStateLed;
   }
 
   // -------------------------------------------------
   // Handle HTTP requests
   // Example : 
   //   To send KEY_1 on BD :
   //   http://IP/ir.htm?data=81&type=1&device=301a
   // -------------------------------------------------
   EthernetClient client = HttpServer.available();
   if (client) 
   {
     char *ptr=NetworkFrame;
     int n=0;
     while (client.connected() && client.available())
     {
       if (n++<sizeof(NetworkFrame))
         *ptr++=client.read();
       else
         client.flush(); 
     }
     *ptr=0;
     if (n>0)
     {
       __FlashStringHelper *Header=F("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n");
 
       // -------------------------------------------------
       // Samsung IR command
       // -------------------------------------------------
       ptr=strstr(NetworkFrame, "/ir.htm?data=");
       if (ptr)
       {
         ptr+=13;
         byte Type=0;
         unsigned int Device=0x0707, Data=HexToUInt(ptr);
         ptr=strstr(ptr, "type=");
         if (ptr) Type=HexToUInt(ptr+5);
         ptr=strstr(ptr, "device=");
         if (ptr) Device=HexToUInt(ptr+7);
 
         Samsung::SendCommand(Type, Device, Data);
         client.println(Header);
         client.println("OK !");
         delay(100); 
         client.stop();
         return;
       }
 
       // send an error !
       client.println(Header);
       client.println(F("Error !"));
       delay(1);
     }
     client.stop();
   }
 
   // -------------------------------------------------
   // Telnet Serial Console Interface
   // Configure Putty with :
   //   - "Local Echo : Force off"
   //   - "Local line editing : Force off"
   // -------------------------------------------------
   client = TelnetServer.available();
   if (client) 
   {
     char *ptr=NetworkFrame;
     int n=0;
     while (client.connected() && client.available())
       if (n++<sizeof(NetworkFrame)) *ptr++=client.read();
     *ptr=0;
     
     // Sends telnet buffer to Serial Console
     if (n>0) Serial.write(NetworkFrame);
   }
   // Anything received from Serial Console ?
   char *ptr=NetworkFrame;
   while (Serial.available()) *ptr++=Serial.read();
   *ptr=0;
   // Send it to telnet
   TelnetServer.write(NetworkFrame);
 }
 
 // ---------------------------------------------------------------------