Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
BuddyC
Published © GPL3+

MKR1000 Universal Remonster!

WiFi connected universal remote with smart phone webapp.

IntermediateFull instructions provided3 hours11,494
MKR1000 Universal Remonster!

Things used in this project

Hardware components

Arduino MKR1000
Arduino MKR1000
×1
Arduino Nano R3
Arduino Nano R3
×1
General Purpose Transistor NPN
General Purpose Transistor NPN
Triggers the PNP transistors of IR LED array
×1
Resistor 1k ohm
Resistor 1k ohm
pulls down NPN transistor
×1
IR transmitter (generic)
IR LEDs. Get wide angle if you have a choice
×2
General Purpose Transistor PNP
General Purpose Transistor PNP
One PNP transistor per IR LED; you can do much more than two
×2

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Schematic

Used the NodeMCU board since the MKR1000 wasn't available in Fritzing yet

Code

WiFi_IR_Blaster_MKR1000

C/C++
Web server running on MKR1000 that sends IR codes to another MCU via serial
/*
 *  Adapted from NodeMCU/ESP8266 WiFi IR Blaster by Buddy Crotty
 *  
 *  This sketch requires an Arduino MKR1000 for the web server and WiFi portions
 *  and then sends the parsed IR codes to another device that supports the IRremote.h libraries
 *  (like ATtiny85 or Arduino Uno/Nano/Mini) over software serial.
 *  
 *  This works best with another web server acting as a front end that 
 *  sends cURL requests based on which buttons are pressed. 
 *  GET request URL format: http://[ip_address]/[IRcode]
 *  
 *  IR codes can be strung together to create macros 
 *  
 */

#include <SPI.h>
#include <WiFi101.h>

char ssid[] = "SSID";      // your network SSID (name)
char pass[] = "PASSWORD";   // your network password
//int keyIndex = 0;                 // your network key Index number (needed only for WEP)

// MKR1000 Hardware Serial1(13, 14); // RX, TX
int status = WL_IDLE_STATUS;

WiFiServer server(80);

#define DEBUG true

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
  
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  server.begin();
  // you're connected now, so print out the status:
  
  Serial.println("...:: WiFi IR Blaster ::...");
  Serial.println("Webserver Started");
  printWifiStatus();
  Serial.println("");
}
 
void loop()
{
  // listen for incoming clients
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
    Serial.println("new client");
    // Wait until the client sends some data
    while(!client.available()){
      delay(1);
    }
    
  // Read the first line of the request (the GET string)
  String req = client.readStringUntil('\r');
  Serial.println(req);
  Serial1.println(req);   
  client.flush();

    // give the client time to receive the data
     delay(1);

    // close the connection
    client.stop();
    client.flush();
    Serial.println("client disconnected");
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

WiFi_IR_Blaster_Nano

C/C++
IR Blaster code running running on additional MCU (in this case an Arduino Nano). Using the vendor codes rather than Raw IR is much more efficient, but I couldn't get it to work on my appliances.
/*
 *  Adapted from NodeMCU/ESP8266 WiFi IR Blaster by Buddy Crotty
 *  
 *  To be used in conjunction with an Arduino MKR1000 running 
 *  the web server and connecting to WiFi.  
 *  
 *  This sketch runs on another Arduino and only parsed requests coming 
 *  in over serial to then send out the requested IR signal. 
 *  
 *  IR codes can be strung together to create macros 
 *  
 */
 
#include <IRremote.h>

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

IRsend irsend; //an IR led is connected to GPIO1 (physical pin 6 on an ATtiny85)
/*
  // 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

String req = "";

void setup() {
  delay(1000);
  Serial.begin(9600);
  Serial.setTimeout(100);
  //irsend.begin();
}

void loop() {
  // Wait for serial data
  if (Serial.available() ){
    // read the incoming data from MKR1000
    req = Serial.readString();

    // Match the request
/*    if (req.indexOf("/irTVpwr") != -1){
        irsend.sendRaw(irTVpwr, sizeof(irTVpwr) / sizeof(irTVpwr[0]), khz);   
        // Serial.println("IRreq irTVpwr received");
    }
    else if (req.indexOf("/irTVsrc") != -1){
        irsend.sendRaw(irTVsrc, sizeof(irTVsrc) / sizeof(irTVsrc[0]), khz);   
        // Serial.println("IRreq irTVsrc received");
    }
    else if (req.indexOf("/irTVmute") != -1){
        irsend.sendRaw(irTVmute, sizeof(irTVmute) / sizeof(irTVmute[0]), khz);   
        // Serial.println("IRreq irTVmute received");
    }
    else if (req.indexOf("/irTVvdn") != -1){
        irsend.sendRaw(irTVvdn, sizeof(irTVvdn) / sizeof(irTVvdn[0]), khz);   
        // Serial.println("IRreq irTVvdn received");
    }
    else if (req.indexOf("/irTVvup") != -1){
        irsend.sendRaw(irTVvup, sizeof(irTVvup) / sizeof(irTVvup[0]), khz);   
        // Serial.println("IRreq irTVvup received");
    }
    else if (req.indexOf("/irTVchup") != -1){
        irsend.sendRaw(irTVchup, sizeof(irTVchup) / sizeof(irTVchup[0]), khz);   
        // Serial.println("IRreq irTVchup received");
    }
    else if (req.indexOf("/irTVchdn") != -1){
        irsend.sendRaw(irTVchdn, sizeof(irTVchdn) / sizeof(irTVchdn[0]), khz);   
        // Serial.println("IRreq irTVchdn received");
    }
    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 received");
    } */
    if (req.indexOf("/irRECpwr") != -1){
        irsend.sendRaw(irRECpwr, sizeof(irRECpwr) / sizeof(irRECpwr[0]), khz);   
        // Serial.println("IRreq irRECpwr received");
    }
    else if (req.indexOf("/irRECpwrON") != -1){
        irsend.sendRaw(irRECpwrON, sizeof(irRECpwrON) / sizeof(irRECpwrON[0]), khz);   
        // Serial.println("IRreq irRECpwrON received");
    }
    else if (req.indexOf("/irRECpwrOFF") != -1){
        irsend.sendRaw(irRECpwrOFF, sizeof(irRECpwrOFF) / sizeof(irRECpwrOFF[0]), khz);   
        // Serial.println("IRreq irRECpwrOFF received");
    }
    else if (req.indexOf("/irRECmute") != -1){
        irsend.sendRaw(irRECmute, sizeof(irRECmute) / sizeof(irRECmute[0]), khz);   
        // Serial.println("IRreq irRECmute received");
    }  
    else if (req.indexOf("/irRECvdn") != -1){
        irsend.sendRaw(irRECvdn, sizeof(irRECvdn) / sizeof(irRECvdn[0]), khz);   
        // Serial.println("IRreq irRECvdn received");
    }
    else if (req.indexOf("/irRECvup") != -1){
        irsend.sendRaw(irRECvup, sizeof(irRECvup) / sizeof(irRECvup[0]), khz);   
        // Serial.println("IRreq irRECvup received");
    } 
    else {
      // Serial.println("invalid request");
      return;
    }
  }
}

Credits

BuddyC
10 projects • 102 followers
I collect hobbies.

Comments