Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

Composants et fournitures

Composant Quantité Remarques
ESP8266 ESP-01 (Espressif) 1 Ou ESP8266 standard / kit NodeMCU
Arduino Nano R3 1
Transistor NPN usage général 1 Pour driver la LED IR
LED IR (Adafruit) 1

Outils nécessaires

Applications et services en ligne

À propos du projet

Deux pas en avant…

Les grands fabricants de smartphones abandonnent les blasters IR intégrés. Je voulais rendre mes appareils « bêtes » (TV, clim, etc.) pilotables depuis mon infrastructure IoT. J'ai une maison connectée en mesh, mais il me faut encore une télécommande physique pour la TV ? Il doit y avoir mieux.

J'avais déjà construit un blaster IR pour clims autonomes et un projet de ventilo connecté avec webapp Android. Il suffisait de combiner les deux : un blaster IR connecté au WiFi avec interface web pour envoyer des codes IR depuis le téléphone. Déployable dans chaque pièce, pilotable depuis une interface unique — applications immenses.

Prototypage rapide

J'ai récupéré du matériel inutilisé et câblé le nécessaire : WiFi, réception HTTP, émission IR.

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

Ça marchait : une requête HTTP sur l'IP de l'ESP8266 déclenchait le code IR « Power ». Mais il fallait héberger la webapp, parser les URLs en codes IR, et les commandes AT sur l'ESP-01 étaient fastidieuses avec 1-2 s de latence.

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

NodeMCU : la solution

Passage au NodeMCU (ESP8266 dev board) : régulation intégrée, USB-série, nombreuses E/S, compatible breadboard. La bibliothèque ESP8266WebServer gère les requêtes GET nativement, et IRremoteESP8266 fonctionne out-of-the-box.

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

L'ESP8266 ne peut pas héberger la webapp complète — je l'héberge sur un C.H.I.P. $9 (déjà sur mon réseau). Autre limite : l'ESP8266 est en 3,3V, les LED IR directes étaient trop faibles. Solution : transistor NPN pour commuter le 5V sur les LED IR.

API REST…-ish

J'ai adapté un tutoriel Adafruit (REST API pour Arduino) : JavaScript + PHP envoient des requêtes cURL vers l'ESP8266. Hébergé sur le C.H.I.P. (Apache) ou dans le cloud. Interface HTML basique + manifest.json + icônes pour webapp Android native.

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

Côté Arduino : serveur allégé, accepte GET, parse l'URL, répond 200 OK, déconnecte, puis émet le code IR correspondant.

Universal Remonster

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

Fonctionne parfaitement, zéro latence. Les LED IR ont un angle étroit — viser précisément. Velcro industriel pour fixation discrète sous étagère. Fils rigides pour ajuster l'orientation.

Note : sans résistance, les LED IR sont alimentées en 5V direct via le transistor. Portée excellente (rebond sur murs), mais durée de vie réduite. Utilisation sporadique et impulsions courtes (faible duty cycle) devraient limiter l'usure. J'ai commandé des LED IR grand angle et plus puissantes pour v2, avec résistance en série.

Mise à jour 3 mois et futures évolutions

Utilisé quotidiennement, impeccable. Deuxième appareil ajouté au salon pour clim et TV.

Projets :

Ce petit blaster IR connecté comble peu à peu le fossé entre ma maison intelligente et mes appareils legacy.

Code

Sketch Arduino : WiFi IR Blaster pour ESP8266 (C/C++)

Nécessite bibliothèques ESP8266WiFi, IRremoteESP8266, ESP8266mDNS. Préférez les codes IR standards de la bibliothèque si votre télécommande est supportée. Adapté d'un contrôleur de clim utilisant des codes IR non standard.

/* WiFi IR Blaster par Buddy Crotty
 * ESP8266 reçoit requêtes HTTP GET et émet codes IR vers LED IR selon la requête.
 * Fonctionne mieux avec un serveur web frontal envoyant des cURL selon boutons pressés.
 * Format cURL : https://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; // Fréquence porteuse 38 kHz (NEC, Samsung)
IRsend irsend(4); // LED IR sur GPIO4 (pin D2 NodeMCU)

// --- Codes IR bruts (RAW) pour TV Samsung ---
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};
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};
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};
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};
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,500, 600,550, 550,550, 600,1600, 600,1650, 600,1650, 550,1650, 600,1650, 600};
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};
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};

// --- Codes IR pour Récepteur (NEC) ---
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};
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};
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};
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};
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};
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};
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};

WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);
  irsend.begin();
  
  Serial.println(); Serial.println();
  Serial.print("Connexion à "); Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
  Serial.println(""); Serial.println("WiFi connecté");
  
  server.begin();
  Serial.println("Serveur HTTP démarré");
  Serial.print("Adresse IP : "); Serial.println(WiFi.localIP());
  
  if (mdns.begin("IRBlasterLR", WiFi.localIP())) 
    Serial.println("Répondeur MDNS démarré");
  Serial.println(); Serial.println();
}

void loop() {
  WiFiClient client = server.available();
  if (!client) return;
  
  Serial.println("nouveau client");
  while (!client.available()) delay(1);
  
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  
  // Routage des commandes
  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 if (req.indexOf("/irRECsrc") != -1)   { irsend.sendRaw(irRECsrc, sizeof(irRECsrc)/sizeof(irRECsrc[0]), khz); Serial.println("IRreq irRECsrc sent"); }
  else { Serial.println("requête invalide"); client.stop(); return; }
  
  client.flush();
  client.print("HTTP/1.1 200 OK\r\n");
  delay(1);
  Serial.println("Client déconnecté"); Serial.println();
}

script.js (JavaScript, requiert jQuery)

function buttonClick(clicked_id) {
  const base = "192.168.1.62"; // IP de l'ESP8266
  const buttons = [
    "irTVpwr","irTVsrc","irTVmute","irTVvdn","irTVvup","irTVchup","irTVchdn",
    "irRECpwr","irALLpwr","irRECpwrON","irRECpwrOFF","irRECmute","irRECvdn","irRECvup"
  ];
  if (buttons.includes(clicked_id)) {
    $.get("curl.php", { room: base, button: clicked_id });
  }
}

index.html (HTML)

<html>
<head>
  <link href="style.css" rel="stylesheet" type="text/css" />
  <script src="jquery-2.0.3.min.js"></script>
  <script 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" id="irTVpwr" onClick="buttonClick(this.id)">Power</button><br><br>
    <button class="btn" id="irTVvup" onClick="buttonClick(this.id)">Vol +</button>
    <button class="btn" id="irTVsrc" onClick="buttonClick(this.id)">Source</button>
    <button class="btn" id="irTVchup" onClick="buttonClick(this.id)">Ch +</button><br><br>
    <button class="btn" id="irTVvdn" onClick="buttonClick(this.id)">Vol -</button> &nbsp;&nbsp;
    <button class="btn" id="irTVmute" onClick="buttonClick(this.id)">&nbsp;Mute&nbsp;</button> &nbsp;&nbsp;
    <button class="btn" id="irTVchdn" onClick="buttonClick(this.id)">Ch -</button>
    <br><br><br>
    <h1>Récepteur</h1>
    <button class="btn" id="irRECpwr" onClick="buttonClick(this.id)">Power</button><br><br>
    <button class="btn" id="irRECmute" onClick="buttonClick(this.id)">Mute</button>
    <button class="btn" id="irRECvdn" onClick="buttonClick(this.id)">Vol -</button>
    <button class="btn" id="irRECvup" onClick="buttonClick(this.id)">Vol +</button>
  </div>
</body>
</html>

curl.php (PHP)

<?php
$room = $_GET['room'];
$button = $_GET['button'];
$service_url = 'https://' . $room . '/' . $button;
$curl = curl_init($service_url);
curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$curl_response = curl_exec($curl);
curl_close($curl);
echo $curl_response;
?>

manifest.json (JSON)

{
  "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"
}

Schémas

Alimentation + une pin pilotant un transistor NPN pour driver deux LED IR en série (sans résistance) sur le 5V.

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

Pour plus de LED ou moins de chute de tension depuis du 3,3V : transistor NPN commutant plusieurs transistors PNP (un par LED). Permet d'utiliser autant de LED que le courant le permet.

Blaster IR WiFi DIY : contrôlez vos appareils via ESP8266 et Arduino

Processus de fabrication

  1. Limites clés des systèmes de localisation temps réel (RTLS) Wi‑Fi
  2. Technologies sans fil émergentes 2015 : Guide pour M2M et IoT
  3. Déployer un serveur web TLS sur un ESP8266 à 3 $ en moins de 30 minutes
  4. Intégration MQTT transparente : capteurs NodeMCU DHT22 avec Raspberry Pi 3 B+ comme broker
  5. Construire un robot piloté Wi‑Fi avec Raspberry Pi & Smartphone Android
  6. Construire un robot Raspberry Pi piloté Wi-Fi avec Python – Guide pas à pas
  7. Appels Wi-Fi expliqués : fonctionnement et importance
  8. Serrure connectée WiFi avec Arduino et ESP8266 – Déverrouillage par smartphone
  9. Le grenaillage par microbilles expliqué : guide ultime pour des finitions lisses et polies