Project tutorial
WiFi IR Blaster

WiFi IR Blaster © GPL3+

A connected universal remote.

  • 97,360 views
  • 44 comments
  • 102 respects

Components and supplies

Esp01
Espressif ESP8266 ESP-01
You could do this with a standard ESP8266 instead or the NodeMCU development kit
×1
Ard nano
Arduino Nano R3
×1
Fairchild semiconductor pn2222abu. image
General Purpose Transistor NPN
×1
Adafruit IR LEDs
×1

Necessary tools and machines

09507 01
Soldering iron (generic)

Apps and online services

About this project

Two Steps Forward...

It seems like the major phone manufacturers are moving away from built in IR blasters so I'm looking for a way to future-proof my "dumb" devices that don't currently integrate with my IoT infrastructure. I have a mesh-networked smart home, but I need to find a physical remote to turn on my TV? There has to be a better way.

I recently built an IR blaster that controls stand alone air conditioners in my house and another previous project was a connected HVAC vent with an android connected webapp.  Essentially, all I need to do is combine these two things into a web-connected IR blaster with a webapp frontend so I can press buttons on my phone and have IR signals sent to my media centers.  These can be deployed in every room and controlled anywhere from a single interface, so the applications for this are extreamly broad.

Rapid Prototyping

I grabbed some unused hardware and wired up everything I'd need to get connected to my WiFi, accept HTTP connections and send IR signals.

This worked just fine in that I could request a specific URL on the IP assigned to the ESP8266 and have the Arduino output a "Power" signal to the IR LED.   I just needed to find out where to host the webapp, have that send the URLs to the IR blaster and then have those requests parsed into specific IR codes.  This was very tedious to do using AT commands with the ESP8266, and there was something causing a 1-2 second delay between sending the request and the LED blinking.

NodeMCU

I went ahead with the NodeMCU ESP8266 dev board because it has onboard power regulation, USB to serial interface, and plenty of I/O pins in this small package (it's also breadboard friendly).  It turns out there is already an ESP8266 WebServer library that accepts GET requests that I was able to adapt for sending IR codes and the regular IRremote library works out of the box.

The ESP8266 on the NodeMCU isn't powerful enough to host the webapp itself, so I'll run it on an underutilized C.H.I.P. $9 computer that is already running to my home network.  Another limitation is that the ESP8266 is that it's a 3.3v board, so the IR LEDs driven directly from an I/O pin were very dim and had to be right next to the appliance it was sending a signal to.  I instead used the I/O pin to drive an npn transistor to switch the 5v supply voltage on/off.

REST...ish

After doing some research, I found a great tutorial for implementing a REST API for Arduino to control LEDs on adafruit.  I used their JavaScript and PHP files to submit the cURL requests and loaded that on the CHIP which is already running apache but could just as easily be hosted in the cloud. After creating a basic HTML page for the remote control, I added the manifest.json and icon files so it can run as a native webapp on an Android phone.

On the Arduino side, I trimmed down the webserver to just accept a GET request, parse the URL, send a 200 OK, and then disconnect.  Based off the URL, the Arduino would send the IR code that was mapped to the button pressed.

Universal Remonster

Everything is working flawlessly with zero delay.  I discovered that the IR LEDs I'm using have a very narrow angle, so I have to be careful that they are pointed correctly.  Some industrial velcro lets me mount it under a shelf, out of sight, and makes sure it stays pointed at the IR receivers on the other end.  I added some thick gauge wire to the LED leads so they can be fine tuned.

See it in action

Having resistors for the IR LEDs caused them to be almost unusable, so the transistor is powering them with an unregulated 5v.  This allows me to bounce IR off walls and mount the blaster across the room, but will definitely have an effect on longevity.  I'm hoping that since they are used very infrequently and the IR signals are super short pulses (lower duty cycle than most dim PWM signals) I won't need to replace the LEDs for some time.  I made sure to order some wide angle and higher output IR LEDs for version 2, so when these finally die, I'll replace them along with an inline resistor.

3 Month Update and Future Features

I use this every day and it has worked flawlessly. I've even added a second device in our family room to control our window AC unit and another TV.

Plans for the future:

  • Migrate the web UI to a cloud service
  • Integrate with Amazon Echo for voice commands (Done)
  • Next hardware iteration will also have a DHT22 temperature sensor and I'm researching ways to transmit RF for my ceiling fans
  • Add an IR receiver for a learning feature so that you can "teach" the IR blaster commands from existing remotes
  • Integrate with my home automation/security to turn off appliances when not in use

This small connected IR blaster is slowly filling the gap between my smart home and legacy appliances.

Code

WiFi IR Blaster for ESP8266 Arduino SketchC/C++
You'll need the ESP8266 wifi library and IRremote.h. You should also opt to not use the Raw IR codes if your remote is supported in the library. I adapted this sketch from an air conditioner controller I built that used non-standard IR codes.
/*
 * WiFi IR Blaster by Buddy Crotty
 *  Use an ESP8266 module or dev board to receive HTTP GET request
 *  and then send IR codes to an attached IR LED based on those requests.
 *  This works best with another web server acting as a front end that 
 *  sends cURL requests based on which buttons are pressed. 
 *  cURL format: http://ESP8266/IRcode
 */

#include <ESP8266WiFi.h>
#include <IRremoteESP8266.h>
#include <ESP8266mDNS.h>

const char* ssid = "AP_SSID";
const char* password = "AP_Pass";
MDNSResponder mdns;

int khz = 38; // 38kHz carrier frequency for both NEC and Samsung

IRsend irsend(4); //an IR led is connected to GPIO4 (pin D2 on NodeMCU)

  // Insert RAW IR signal for "TV Power"
unsigned int irTVpwr[] = {4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,500, 600,500, 600,500, 600,550, 550,1700, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,1650, 600,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600,1650, 600,500, 600,1650, 550,1700, 550,1650, 600,1650, 550,1650, 600,1650, 600};  // SAMSUNG E0E040BF

  // Insert RAW IR signal for "TV Source"
unsigned int irTVsrc[] = {4600,4300, 700,1550, 650,1550, 650,1600, 650,450, 650,450, 600,550, 550,550, 600,500, 600,1650, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 550,550, 600,1650, 550,550, 550,550, 600,500, 600,500, 600,550, 550,550, 600,500, 600,550, 550,1650, 550,1700, 550,1650, 600,1600, 600,1650, 600,1600, 600,1650, 550};  // SAMSUNG E0E0807F
  
  // Insert RAW IR signal for "TV Mute"
unsigned int irTVmute[] = {4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,500, 600,500, 600,500, 600,500, 600,1650, 600,1600, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,1650, 550,1650, 600,1650, 550,1650, 600,550, 550,550, 550,550, 600,500, 600,550, 550,550, 550,550, 600,500, 600,1650, 550,1650, 600,1650, 550,1650, 600};  // SAMSUNG E0E0F00F
  
  // Insert RAW IR signal for "TV Volume Down"
unsigned int irTVvdn[] = {4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,450, 650,450, 600,550, 550,550, 600,1650, 550,1650, 550,1650, 600,550, 550,550, 550,550, 600,500, 600,500, 600,1650, 600,1600, 600,500, 600,1650, 550,550, 600,500, 600,500, 600,550, 550,550, 600,500, 600,1650, 550,550, 550,1650, 600,1650, 550,1650, 600,1650, 550};  // SAMSUNG E0E0D02F
  
  // Insert RAW IR signal for "TV Volume Up"
unsigned int irTVvup[] = {4600,4300, 650,1600, 650,1550, 650,1600, 600,500, 600,550, 600,500, 600,550, 550,550, 550,1700, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,1650, 600,1650, 550,1650, 600,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,550, 600,1600, 600,1650, 600,1650, 550,1650, 600,1650, 600};  // SAMSUNG E0E0E01F
  
  // Insert RAW IR signal for "TV Channel Up"
unsigned int irTVchup[] = {4650,4250, 700,1550, 650,1600, 650,1550, 650,500, 600,500, 600,500, 650,500, 600,500, 600,1650, 550,1650, 600,1650, 600,500, 600,500, 600,550, 550,550, 600,550, 550,550, 550,1650, 600,550, 600,500, 600,1650, 550,550, 600,500, 600,550, 550,1650, 600,550, 550,1650, 600,1650, 600,500, 600,1650, 600,1600, 600,1650, 600};  // SAMSUNG E0E048B7
  
  // Insert RAW IR signal for "TV Channel Down"
unsigned int irTVchdn[] = {4600,4350, 650,1550, 650,1600, 650,1600, 600,500, 600,500, 600,550, 550,550, 600,550, 550,1650, 600,1650, 550,1700, 550,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,550, 550,550, 600,1650, 600,500, 600,500, 600,550, 550,1650, 600,1650, 600,1650, 550,1650, 600,550, 550,1650, 600,1650, 600,1650, 550};  // SAMSUNG E0E008F7
  
  // Insert RAW IR signal for "Receiver Power"
unsigned int irRECpwr[] = {9050,4350, 650,500, 600,1600, 600,500, 650,500, 600,1600, 600,550, 600,1600, 600,1650, 550,550, 600,500, 600,1600, 650,1600, 600,500, 600,1650, 600,1600, 600,500, 600,1650, 600,1600, 600,550, 600,1600, 600,500, 600,550, 600,1600, 600,1600, 650,500, 600,500, 600,1600, 650,500, 600,1600, 600,1650, 600,500, 600,500, 600};  // NEC 4B36D32C

  // Insert RAW IR signal for "Receiver Power On"
unsigned int irRECpwrON[] = {9000,4400, 600,550, 600,1600, 600,500, 600,550, 600,1600, 600,500, 600,1600, 650,1600, 600,1600, 600,500, 650,1600, 600,1600, 600,500, 650,1600, 600,1600, 600,500, 600,550, 600,500, 600,1600, 600,550, 600,500, 600,500, 650,500, 600,500, 600,1600, 650,1600, 600,500, 600,1600, 650,1600, 600,1600, 600,1600, 600,1600, 650};  // NEC 4BB620DF
  
  // Insert RAW IR signal for "Receiver Power Off"
unsigned int irRECpwrOFF[] = {9000,4400, 600,550, 550,1650, 600,550, 550,550, 600,1650, 550,550, 600,1650, 550,1650, 600,550, 550,550, 550,1650, 600,1650, 600,550, 550,1650, 600,1650, 550,550, 600,1650, 550,1650, 600,1650, 600,500, 600,550, 550,550, 600,1650, 550,550, 600,500, 600,550, 550,550, 550,1700, 550,1650, 600,1650, 550,550, 600,1650, 550};  // NEC 4B36E21D

  // Insert RAW IR signal for "Receiver Mute"
unsigned int irRECmute[] = {9000,4400, 650,450, 650,1600, 600,500, 600,500, 650,1600, 600,500, 600,1650, 600,1600, 600,1600, 650,500, 600,1600, 650,1600, 600,500, 600,1600, 650,1600, 600,500, 600,1650, 600,500, 600,1600, 650,500, 600,500, 600,500, 600,500, 650,500, 600,500, 600,1600, 650,500, 600,1600, 600,1600, 650,1600, 600,1650, 600,1600, 600};  // NEC 4BB6A05F
  
  // Insert RAW IR signal for "Receiver Volume Down"
unsigned int irRECvdn[] = {9150,4250, 750,350, 700,1550, 700,400, 700,450, 650,1550, 700,450, 600,1600, 650,1600, 600,1650, 600,500, 600,1650, 600,1600, 600,550, 600,1600, 600,1650, 600,500, 600,1650, 600,1600, 650,500, 600,500, 600,500, 650,500, 600,500, 600,500, 600,550, 600,500, 600,1650, 600,1600, 600,1650, 600,1650, 600,1600, 600,1650, 600};  // NEC 4BB6C03F
  
  // Insert RAW IR signal for "Receiver Volume Up"
unsigned int irRECvup[] = {9050,4400, 650,500, 600,1600, 600,550, 600,500, 600,1650, 600,500, 600,1600, 650,1600, 600,1600, 600,550, 600,1600, 600,1600, 650,500, 600,1600, 650,1600, 600,500, 600,550, 600,1600, 600,550, 600,500, 600,550, 600,500, 600,550, 600,500, 600,1600, 650,500, 600,1600, 600,1650, 600,1600, 600,1650, 600,1600, 600,1600, 600};  // NEC 4BB640BF

  // Insert RAW IR signal for "Receiver Source CBL/SAT"
unsigned int irRECsrc[] = {8950,4450, 600,500, 600,1650, 600,500, 600,500, 600,1650, 600,500, 600,1600, 600,1650, 600,1600, 600,550, 600,1600, 600,1650, 600,500, 600,1600, 600,1650, 600,500, 600,500, 600,1650, 600,1600, 600,1650, 600,500, 600,500, 600,500, 650,500, 600,1600, 600,500, 600,550, 600,500, 600,1600, 600,1650, 600,1600, 600,1650, 600};  // NEC 4BB6708F

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);


void setup() {
  Serial.begin(115200);
  delay(10);

  irsend.begin();
  
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected");

  // Start the server
  server.begin();
  Serial.println("HTTP Server Started");

  // Print the IP address
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  if (mdns.begin("IRBlasterLR", WiFi.localIP())) {
    Serial.println("MDNS Responder Started");
  }

  Serial.println();
  Serial.println();
}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
  
  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  
  // Match the request
  if (req.indexOf("/irTVpwr") != -1){
      irsend.sendRaw(irTVpwr, sizeof(irTVpwr) / sizeof(irTVpwr[0]), khz);   
      Serial.println("IRreq irTVpwr sent");
  }
  else if (req.indexOf("/irTVsrc") != -1){
      irsend.sendRaw(irTVsrc, sizeof(irTVsrc) / sizeof(irTVsrc[0]), khz);   
      Serial.println("IRreq irTVsrc sent");
  }
  else if (req.indexOf("/irTVmute") != -1){
      irsend.sendRaw(irTVmute, sizeof(irTVmute) / sizeof(irTVmute[0]), khz);   
      Serial.println("IRreq irTVmute sent");
  }
  else if (req.indexOf("/irTVvdn") != -1){
      irsend.sendRaw(irTVvdn, sizeof(irTVvdn) / sizeof(irTVvdn[0]), khz);   
      Serial.println("IRreq irTVvdn sent");
  }
  else if (req.indexOf("/irTVvup") != -1){
      irsend.sendRaw(irTVvup, sizeof(irTVvup) / sizeof(irTVvup[0]), khz);   
      Serial.println("IRreq irTVvup sent");
  }
  else if (req.indexOf("/irTVchup") != -1){
      irsend.sendRaw(irTVchup, sizeof(irTVchup) / sizeof(irTVchup[0]), khz);   
      Serial.println("IRreq irTVchup sent");
  }
  else if (req.indexOf("/irTVchdn") != -1){
      irsend.sendRaw(irTVchdn, sizeof(irTVchdn) / sizeof(irTVchdn[0]), khz);   
      Serial.println("IRreq irTVchdn sent");
  }
  else if (req.indexOf("/irALLpwr") != -1){
      irsend.sendRaw(irRECpwrON, sizeof(irRECpwrON) / sizeof(irRECpwrON[0]), khz);   
      irsend.sendRaw(irTVpwr, sizeof(irTVpwr) / sizeof(irTVpwr[0]), khz);   
      delay(2000);
      irsend.sendRaw(irRECsrc, sizeof(irRECsrc) / sizeof(irRECsrc[0]), khz);         
      Serial.println("IRreq irALLpwr sent");
  }
  else if (req.indexOf("/irRECpwr") != -1){
      irsend.sendRaw(irRECpwr, sizeof(irRECpwr) / sizeof(irRECpwr[0]), khz);   
      Serial.println("IRreq irRECpwr sent");
  }
  else if (req.indexOf("/irRECpwrON") != -1){
      irsend.sendRaw(irRECpwrON, sizeof(irRECpwrON) / sizeof(irRECpwrON[0]), khz);   
      Serial.println("IRreq irRECpwrON sent");
  }
  else if (req.indexOf("/irRECpwrOFF") != -1){
      irsend.sendRaw(irRECpwrOFF, sizeof(irRECpwrOFF) / sizeof(irRECpwrOFF[0]), khz);   
      Serial.println("IRreq irRECpwrOFF sent");
  }
  else if (req.indexOf("/irRECmute") != -1){
      irsend.sendRaw(irRECmute, sizeof(irRECmute) / sizeof(irRECmute[0]), khz);   
      Serial.println("IRreq irRECmute sent");
  }  
  else if (req.indexOf("/irRECvdn") != -1){
      irsend.sendRaw(irRECvdn, sizeof(irRECvdn) / sizeof(irRECvdn[0]), khz);   
      Serial.println("IRreq irRECvdn sent");
  }
  else if (req.indexOf("/irRECvup") != -1){
      irsend.sendRaw(irRECvup, sizeof(irRECvup) / sizeof(irRECvup[0]), khz);   
      Serial.println("IRreq irRECvup sent");
  } 
  else {
    Serial.println("invalid request");
    client.stop();
    return;
  }
  
  client.flush();
   
  // Send the response to the client
  //client.print(s);
  client.print("HTTP/1.1 200 OK\r\n");
  delay(1);
  Serial.println("Client Disconnected");
  Serial.println();
  // The client will actually be disconnected 
  // when the function returns and 'client' object is detroyed
}
script.jsJavaScript
javascript for webapp (requires jquery)
// Function to send IR commands
function buttonClick(clicked_id){

    if (clicked_id == "irTVpwr"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irTVpwr"} );  
    } 

    if (clicked_id == "irTVsrc"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irTVsrc"} );  
    } 

    if (clicked_id == "irTVmute"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irTVmute"} );  
    } 

    if (clicked_id == "irTVvdn"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irTVvdn"} );  
    } 

	if (clicked_id == "irTVvup"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irTVvup"} );  
    } 
	
    if (clicked_id == "irTVchup"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irTVchup"} );  
    } 

	if (clicked_id == "irTVchdn"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irTVchdn"} );  
    } 
	
    if (clicked_id == "irRECpwr"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irRECpwr"} );  
    } 

    if (clicked_id == "irALLpwr"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irALLpwr"} );  
    } 

	if (clicked_id == "irRECpwrON"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irRECpwrON"} );  
    } 

	if (clicked_id == "irRECpwrOFF"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irRECpwrOFF"} );  
    } 

    if (clicked_id == "irRECmute"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irRECmute"} );  
    } 

    if (clicked_id == "irRECvdn"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irRECvdn"} );  
    } 

	if (clicked_id == "irRECvup"){
        $.get( "curl.php", {
        room: "192.168.1.62", button: "irRECvup"} );  
    } 
 
}
index.htmlHTML
Basic html to display buttons.
<html>
<head>
<LINK href="style.css" rel="stylesheet" type="text/css" />

<script type="text/javascript" src="jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="script.js"></script>

<link rel="manifest" href="manifest.json">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="icon" type="image/png" href="favicon.ico" />

</head>

<body>
	<div align="center" class="div_text_shadow">
	  <button class="btn2" type="button" id="irALLpwr" onClick="buttonClick(this.id)">Power Up Everything</button><BR><BR><BR>
		<H1>TV</H1>
			<button class="btn" type="button" id="irTVpwr" onClick="buttonClick(this.id)">Power</button><BR><BR>
			<button class="btn" type="button" id="irTVvup" onClick="buttonClick(this.id)">Vol +</button>
			<button class="btn" type="button" id="irTVsrc" onClick="buttonClick(this.id)">Source</button>
			<button class="btn" type="button" id="irTVchup" onClick="buttonClick(this.id)">Ch +</button><BR><BR>
			<button class="btn" type="button" id="irTVvdn" onClick="buttonClick(this.id)">Vol -</button>
			&nbsp;&nbsp;
			<button class="btn" type="button" id="irTVmute" onClick="buttonClick(this.id)">&nbsp;Mute&nbsp;</button>
			&nbsp;&nbsp;
			<button class="btn" type="button" id="irTVchdn" onClick="buttonClick(this.id)">Ch -</button>
			<br>
			<br>
			<br>
		<H1>Receiver</H1>
			<button class="btn" type="button" id="irRECpwr" onClick="buttonClick(this.id)">Power</button><BR><BR>
			<button class="btn" type="button" id="irRECmute" onClick="buttonClick(this.id)">Mute</button>
			<button class="btn" type="button" id="irRECvdn" onClick="buttonClick(this.id)">Vol -</button>
			<button class="btn" type="button" id="irRECvup" onClick="buttonClick(this.id)">Vol +</button>
			<br>
			<br>
	</div>
</body>
</html>
curl.phpPHP
php script to send GET requests to ESP8266
<?php

  $room = $_GET['room'];
  $button = $_GET['button'];

  // Create cURL call
  $service_url = 'http://' . $room . '/' . $button;
  $curl = curl_init($service_url);
   
  // Send cURL to Yun board
  curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); 
  $curl_response = curl_exec($curl);
  curl_close($curl);

  //Print answer
  echo $curl_response;

?>
manifest.jsonJSON
This will allow the webpage to run as a native webapp in android.
{
  "name": "WiFi Remote",
  "icons": [
	{
      "src": "remote_icon_36.png",
      "sizes": "36x36",
      "type": "image/png",
      "density": 0.75
    },
    {
      "src": "remote_icon_48.png",
      "sizes": "48x48",
      "type": "image/png",
      "density": 1.0
    },
    {
      "src": "remote_icon_128.png",
      "sizes": "128x128",
      "type": "image/png",
      "density": 1.0
    },
    {
      "src": "remote_icon_192.png",
      "sizes": "192x192",
      "type": "image/png",
      "density": 1.0
    }
  ],
  "scope": "/remote/",
  "start_url": "/remote/index.html",
  "display": "fullscreen",
  "orientation": "portrait"
}

Schematics

Simple Schem
Nothing really to it, just power and a single pin connected to an NPN transistor to drive two IR LEDs in series (with no resistors) off the 5v supply voltage.
Wifi ir blaster esp8266 schem
Adding LEDs
If you want to run additional LEDs or need less voltage drop from a 3.3v source, you can use a NPN transistor to switch multiple PNP transistors (one per LED). This configuration allows you to use as many LEDs as your source voltage can supply current for.
Schematic%20view 2

Comments

Similar projects you might like

IR Controller for Air Conditioner

Project in progress by BuddyC

  • 32,432 views
  • 8 comments
  • 22 respects

Developing an IR Remote and Software Controller

Project tutorial by Steve

  • 18,070 views
  • 0 comments
  • 35 respects

WiFi Robot

Project tutorial by Team Kartik

  • 2,231 views
  • 1 comment
  • 8 respects

Add WiFi to Arduino UNO

by Jefferson Paredes

  • 145,148 views
  • 58 comments
  • 93 respects
Add projectSign up / Login