Como controlar fita de leds por wifi usando ESP8266 25

Em um post anterior, ESP8266: Gravando dados permanentes na memória flash, aprendemos como usar a memória Flash SPI presente no módulo Wemos D1 Mini Pro, para salvar dados de maneira permanente. Como exemplo mostramos como salvar o estado de um LED, que persiste mesmo na falta de energia. Aprendemos também como salvar e carregar da memória flash uma página Web bem simples. Neste post, vamos usar vários desses conceitos para criar um circuito para controlar fita de leds por wifi, usando o ESP8266.

Fita de led com ESP8266

Iremos gravar uma página Web na Flash que contém uma interface de controle de cores para fitas de LED RGB endereçável. Iremos também agregar um novo conceito: uma técnica de comunicação entre página Web (cliente) e o ESP8266 (servidor) usando XMLHTTPRequest.

Controle de fita de leds por wifi – Material utilizado

Para realizar este tutorial foram usados os seguintes materiais:

O circuito foi montado da seguinte maneira:

CIrcuito Wemos Fita de LED

Biblioteca I2S para controle de LEDs endereçáveis

Um desenvolvedor, JoDaNI, desenvolveu uma biblioteca para controle de LEDs endereçáveis utilizando a interface I2S presente no ESP8266. A biblioteca pode ser usada dentro da IDE Arduino e envolve conceitos de uso da RAM para armazenar os dados a serem enviados aos LEDs e DMA(Direct Memory Access) para acessar esses dados e transferi-los a interface I2S.

Uma das vantagens de usar I2S é que este pino é o mesmo pino Rx presente nos módulos ESP8266 inclusive no ESP-01. Uma desvantagem é que seria necessário desconectar qualquer coisa do pino Rx quando o módulo fosse programado usando interface serial.

Baixe a biblioteca esp8266_ws2812_i2s para a pasta libraries da IDE Arduino.

A utilização da biblioteca é bem simples. Comece incluindo-a no seu sketch:

#include <ws2812_i2s.h>

Declare algumas configurações iniciais da biblioteca, como um nome qualquer para identificar a fita de LED e o número de LEDs presentes na fita:

static WS2812 ledstrip;
static Pixel_t pixels[NUM_LEDS];

Para mudar as cores da fita basta seguir a lógica abaixo:

int i;
for(i=0;i<NUM_LEDS;i++) {
    pixels[i].R = <valor tom de vermelho>;
    pixels[i].G = <valor tom de verde>;
    pixels[i].B = <valor tom de azul>;
}  
ledstrip.show(pixels);

O loop for irá percorrer o número de LEDs da fita colocando os valores de tons de vermelho, verde e azul.

Por exemplos se quisermos ligar apenas o primeiro LED da fita na cor vermelha, usamos o seguinte:

pixels[0].R = 255;
pixels[0].G = 0;
pixels[0].B = 0;
ledstrip.show(pixels);

Interface Web de controle RGB

Para este tutorial desenvolvemos uma página Web que irá controlar a cor dos LEDs da fita. Essa página ficará salva na memória Flash do Wemos. Já aprendemos a fazer isso no post Gravando dados na memória Flash. Essa página irá conter uma interface com um selecionador de cores RGB e em seu backend usaremos XMLHTTPRequest para enviar os dados do selecionador de cores ao ESP8266. O resultado da página será o seguinte:

Interface Web

<!DOCTYPE html>
<html>
   <head>
       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
       <script src="https://cdn.rawgit.com/giobauermeister/836975dcbe2fd05a5a2a9dcee6bcec4d/raw/49db24b1ecb60d361f3119ba7e2519f9e2b39101/iro.min.js"></script>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
   </head>
   <body>
       <div class="container">
           <h2 id="title" class="light center">Wemos Color Picker</h2>
           <div class="centered">
               <div id="color-picker-container"></div>
           </div>
           <div class="centered">
               <input placeholder="IP Address" id="ipAddress" type="text" class="validate" style="text-align: center;">            
           </div>
       </div>
       <script>           
           var xhttp = new XMLHttpRequest();        
           var demoColorPicker = new iro.ColorPicker("#color-picker-container", {
               width: 300,
               height: 300,
               color: "#5b9aff"
           });
           demoColorPicker.on("color:change", function (color, changes) {
               console.log(color.rgb);
               var ipAddress = document.getElementById("ipAddress").value;
               var url = "http://" + ipAddress + "/colordata";
               document.getElementById('title').style.color = color.hexString;                               
               xhttp.open("POST", url);
               xhttp.send(JSON.stringify(color.rgb));
           });
       </script>
       <style>
           .centered {
               margin: 0 auto;
               max-width: 300px;
           }
       </style>
   </body>
</html>

Selecionador de cores em javascript

Para selecionar as cores utilizamos o Iro.js, um belo color picker em javascript. Com ele podemos obter as cores em formato RGB. As linhas abaixo definem as configurações de tamanho(300×300) e cor inicial(#5b9aff) do color picker:

var demoColorPicker = new iro.ColorPicker("#color-picker-container", {
    width: 300,
    height: 300,
    color: "#5b9aff"
});

E as linhas abaixo monitoram o evento color:change, enviando os dados RGB em formato Json para o servidor do ESP8266, através de requisição HTTP POST.

demoColorPicker.on("color:change", function (color, changes) {
    console.log(color.rgb);
    var ipAddress = document.getElementById("ipAddress").value;
    var url = "http://" + ipAddress + "/colordata";
    document.getElementById('title').style.color = color.hexString;                               
    xhttp.open("POST", url);
    xhttp.send(JSON.stringify(color.rgb));
});

A documentação completa do color picker Iro.js pode ser encontrada aqui.

XMLHTTPRequest

Para que a página Web se comunique com o ESP8266 e controle a fita de leds por wifi, iremos utilizar um recurso da linguagem Javascript chamado XMLHTTPRequest. Isso nos possibilita realizar requisições GET e POST ao servidor rodando no ESP8266. Basta que o ESP8266 esteja programado para receber tais requisições.

Primeiramente criamos um novo objeto XMLHTTPRequest:

var xhttp = new XMLHttpRequest();

Definimos a URL do ESP8266.

var url = "http://" + ipAddress + "/colordata";

Lembre-se de digitar na página Web o IP que seu ESP8266 recebeu ao conectar-se ao roteador, assim a variável ipAddress vai conter o IP do ESP8266. A URL ficará como a seguir:

http://192.168.0.xx/colordata

Quando fazemos alguma mudança de cor na página Web, abrimos uma conexão POST na URL definida acima:

xhttp.open("POST", url);

E finalmente enviamos ao ESP8266 os dados de cor RGB em formato JSON:

xhttp.send(JSON.stringify(color.rgb));

Programa Servidor ESP8266 Wemos D1 mini

Para que o sistema mostrado acima usando XMLHTTPRequest funcione, o ESP8266 precisa atender as requisições de acordo.

Para isso foi desenvolvido um pequeno Webserver que atende a requisições POST nas URLs raiz “/” e “/colordata”.

// aguarda por requisições na URL raiz "/" ou "/colordata"
server.on("/", handleRoot);
server.on("/colordata", handleColorData);

Quando acessamos o ESP8266 através de seu IP usando um navegador, o navegador faz uma requisição GET na raiz “/”, o que faz o ESP8266 executar a função handleRoot. Essa função basicamente retorna ao navegador a página Web com nossa interface de controle RGB. Então cada vez que mudamos a cor no color picker, o navegador envia uma requisição POST com os dados RGB na URL “/colordata”. O ESP8266 por sua vez chama a função handleColorData, que faz a mudança de cores nos LEDs.

// envia a página Web quando algum cliente conecta na raiz "/"
void handleRoot() {
  server.send(200, "text/html", webPage);
}
// recebe os dados RGB, imprime na serial e chama funcao para mudanca de cor da fita de LED
void handleColorData() {
  String data = server.arg("plain");
  server.send(204,"");
  StaticJsonBuffer<200> jBuffer;
  JsonObject& jObject = jBuffer.parseObject(data);
  int colorR = jObject["r"];
  int colorG = jObject["g"];
  int colorB = jObject["b"];
  Serial.print(colorR);
  Serial.print(" : ");
  Serial.print(colorG);
  Serial.print(" : ");
  Serial.println(colorB);
  changeColor(colorR, colorG, colorB);
  digitalWrite(led, !digitalRead(led));  
}
// muda a cor da fita de LED
void changeColor(int r, int g, int b) {
  int i;
  for(i=0;i<NUM_LEDS;i++) {
    pixels[i].R = r;
    pixels[i].G = g;
    pixels[i].B = b;
  }  
  ledstrip.show(pixels);
}

Veja o código completo do servidor abaixo:

//Programa: Controle de fita de leds por wifi

#include <FS.h>
#include <ArduinoJson.h>
#include <ws2812_i2s.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

#define NUM_LEDS 30 //quantidade de LEDs presentes na fita

const char* ssid = "nome da rede WiFi";
const char* password = "senha da rede WiFi";

String webPage = "";

int led = LED_BUILTIN;

static WS2812 ledstrip;
static Pixel_t pixels[NUM_LEDS];

ESP8266WebServer server(80);

// envia a página Web quando algum cliente conecta na raiz "/"
void handleRoot() {
  server.send(200, "text/html", webPage);
}

// recebe os dados RGB, imprime na serial e chama funcao para mudanca de cor da fita de LED
void handleColorData() {
  String data = server.arg("plain");
  server.send(204,"");
  StaticJsonBuffer<200> jBuffer;
  JsonObject& jObject = jBuffer.parseObject(data);
  int colorR = jObject["r"];
  int colorG = jObject["g"];
  int colorB = jObject["b"];
  Serial.print(colorR);
  Serial.print(" : ");
  Serial.print(colorG);
  Serial.print(" : ");
  Serial.println(colorB);
  changeColor(colorR, colorG, colorB);
  digitalWrite(led, !digitalRead(led));  
}

// muda a cor da fita de LED
void changeColor(int r, int g, int b) {
  int i;
  for(i=0;i<NUM_LEDS;i++) {
    pixels[i].R = r;
    pixels[i].G = g;
    pixels[i].B = b;
  }  
  ledstrip.show(pixels);
}

//Faz a leitura do arquivo HTML
void readFile(void) {
  File rFile = SPIFFS.open("/index.html","r");
  Serial.println("Lendo arquivo HTML...");
  webPage = rFile.readString();
  rFile.close();  
}

void setup() {
  pinMode(led, OUTPUT);
  
  Serial.begin(9600);
  SPIFFS.begin();

  if(SPIFFS.exists("/index.html"))
  {
    Serial.println("\n\nfile exists!");
  }
  else Serial.println("\n\nNo File :(");

  readFile();

  WiFi.begin(ssid, password);
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("iotlamp")) {
    Serial.println("MDNS responder started");
  }

  // aguarda por requisições na URL raiz "/" ou "/colordata"
  server.on("/", handleRoot);
  server.on("/colordata", handleColorData);
  
  server.begin();

  ledstrip.init(NUM_LEDS);
}

void loop() {
  server.handleClient();
}

Conclusão

Neste tutorial aprendemos como criar uma interface Web para controle de fitas de LED por wifi, utilizando recursos Web como o color picker Iro.js e XHTMLRequest para comunicação cliente-servidor.

Veja abaixo o projeto de controle de fita de leds por wifi, onde montamos uma estrutura de luminária DIY e colocamos a fita de LED juntamente com o Wemos D1 Mini Pro. Utilizamos um papel fosco para dar um aspecto difuso à fita de LED. Coloque sua criatividade em ação montando uma luminária bem legal com as fitas de LED.

controle de fita de leds por wifi

Gostou do projeto de controle de fita de leds por wifi? Ajude-nos a melhorar o blog comentando abaixo sobre este tutorial. 

Faça seu comentário

Acesse sua conta e participe

25 Comentários

  1. Muito legal! Essa fita do link funciona com Raspberry também?

    1. Caio,

      É possível, mas vocÊ precisa utilizar um divisor de tensão para ter uma tensão de 3,3V chegando no Pi.

      Abraços!
      Diogo – Equipe MakerHero

  2. Olá.
    Estou com esse erro! Podem me ajudar?

    exit status 1
    ‘class ArduinoJson6152_0000010::StaticJsonDocument’ has no member named ‘parseObject’

    Parece que mudou a versão do Json (5 para o 6) e alguns comandos eles mudaram.
    Um outro comando consegui alterar de acordo com o site (https://arduinojson.org/v6/doc/upgrade/) mas esse ele ainda para com os erros.

    1. Olá. Ainda não consegui solução… Alguém tem.uma dica ou a solução?

      Estou tentando com a W2812 de 8 Leds para tentar juntar ao projeto de analizador de Wifi…

      1. Giovane,

        Voce já tentou usar uma versão mais antiga tanto da IDE, quanto da placa ESP (na IDE)?

        Abraços!
        Diogo – Equipe MakerHero

        1. Não! Utilizei somente a versão da IDE atual!
          Achei esse link, mas ele programa em LUA e não consegui converter!
          https://randomnerdtutorials.com/esp8266-rgb-color-picker/

          Existe um outro caminho, parecido com o do link, para programar em IDE em ESP8266?

  3. Se o value do input não funcionar(que foi o meu caso), rola de fazer assim também, para passar um IP fixo:

      1. input value=”192.168.0.101″ placeholder=”IP Address” id=”ipAddress” type=”text” class=”validate” style=”text-align: center;”
        onfocus=”if (this.value == ‘192.168.0.101’) {this.value = ”;}” onblur=”if (this.value == ”) {this.value = ‘192.168.0.101’;}”

        1. Brunin,

          Você salvou a página HTML em questão na memória da Wemos?

          Abraços!
          Diogo – Equipe MakerHero

          1. Não, pq não conseguir fazer a ferramente de upload funcionar.

            https://github.com/esp8266/arduino-esp8266fs-plugin

          2. Brunin,

            Refaça o tutorial passo a passo e se der erro, favor iniciar um tópico no nosso fórum para que eu possa acompanhar melhor os problemas 🙂

            Abraços!
            Diogo – Equipe MakerHero

            Diogo Zimmermann
  4. Excelente!!! No site MakerHero os projetos são sempre muito com!!! Parabéns

    1. *bons

    2. Olá Marcelo!

      É sempre bom saber que nosso trabalho ajuda as pessoas!

      Abraços!

      André – Equipe MakerHero

  5. Boa noite, belo projeto, voce teria algum relacionado com termometro que mostre a temperatura com esta placa de wif?

    1. Olá Enio! Obrigado pela leitura.

      Infelizmente não temos nenhum tutorial de temperatura com ESP8266

      Mas pela internet você pode encontrar vários tutoriais sobre o tema. Por exemplo: https://randomnerdtutorials.com/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide/

      Abraço!

  6. Olá, vou deixar algumas dicas pra quem for tentar fazer:

    1- Utilize a biblioteca ArduinoJson.h na versão 5.13.2 ou inferior, as versões 6.x.x o código não compila.

    2- No meu caso estou utilizando o lolin nodemcu v3 e para o programa funcionar é necessário uma alimentação externa para placa independente da quantidade de leds (no meu caso 8), como comentado nesse trecho do artigo “Uma desvantagem é que seria necessário desconectar qualquer coisa do pino Rx quando o módulo fosse programado usando interface serial.”

    3- Eu programei meu ESP para ter um ip fixo, o que facilita na hora de acessar, basta adicionar essas linhas no código:

    const char* ssid = “nome da rede WiFi”;
    const char* password = “senha da rede WiFi”;
    IPAddress ip(192, 168, 0, 101); // escolha um ip fixo pro esp
    IPAddress gateway(192, 168, 0, 1); // gateway da sua rede
    IPAddress subnet(255, 255, 255, 0); // máscara da sua rede

    WiFi.config(ip, gateway, subnet);
    WiFi.begin(ssid, password);

    4- Alterei a página html para que o campo ip já venha preenchido com o ip fixo do ESP, basta alterar esta linha:

    Por essa:

    Coloque o ip fixo do seu esp no campo value.

    5 – O código está configurado o mDNS do ESP neste trecho:

    if (MDNS.begin(“iotlamp”)) {
    Serial.println(“MDNS responder started”);
    }
    Caso queira outro dns basta alterar o campo iotlamp

    Então pelo seu navegador você consegue acessar o ESP pelo endereço iotlamp.local caso você tenha MAC, com o windows você tem que instalar o software Bonjour da apple.

    Obrigado pelo artigo Giovanni.

    1. Obrigado pelas dicas Viktor!

  7. olá, belo post!

    uma dúvida, é possível controlar mais do que uma fita de led simultâneamente e de forma independente cada fita?
    tipo assim:
    static WS2812 ledstrip1;

    static WS2812 ledstrip2;

    abraço

    1. https://github.com/FastLED/FastLED/blob/master/examples/Multiple

      acho que com essa biblioteca rola, vc faria um teste com varias fitas em um esp8266?

      agradeço desde já 🙂

      1. Obrigado pela ideia de biblioteca! Iremos avaliar a viabilidade do teste. 🙂

    2. Olá André!

      Infelizmente não fizemos teste declarando mais de um objeto da classe WS2812 para usar com mais de uma fita de LED.

      O problema é que o ESP8266 tem apenas um pino I2S que é o pino RX0. Aì de qualquer maneira as duas fitas de LED estariam no mesmo pino e os dados enviados seriam os mesmos para as duas.

      Mas creio que não há necessidade de usar mais de uma fita de LED. Os LEDs são endereçáveis então é possível ligar o LED que desejar de forma independente.

      Caso tiver mais dúvidas sobre a biblioteca creio que o próprio autor responderia muito melhor que nós. Entre em contato por aqui com ele: https://github.com/cnlohr/esp8266ws2812i2s

  8. Olá, muito bom este post e simples o circuito, gostei. Minha única dúvida seria quanto ao código da página web. Onde é gravado não fica junto com o software do arduino ? isso realmente não entendi. Obrigado.

    1. Olá Ricardo!

      Veja na introdução do post o seguinte trecho:

      “Em um post anterior, ESP8266: Gravando dados permanentes na memória flash, aprendemos como usar a memória Flash SPI presente no módulo Wemos D1 Mini Pro, para salvar dados de maneira permanente. Como exemplo mostramos como salvar o estado de um LED, que persiste mesmo na falta de energia. Aprendemos também como salvar e carregar da memória flash uma página Web bem simples. Neste post, vamos usar vários desses conceitos para criar um circuito para controlar fita de leds por wifi, usando o ESP8266.

      Iremos gravar uma página Web na Flash que contém uma interface de controle de cores para fitas de LED RGB endereçável. Iremos também agregar um novo conceito: uma técnica de comunicação entre página Web (cliente) e o ESP8266 (servidor) usando XMLHTTPRequest.”

      Agora, como gravar a página Web na memória Flash? Isso você aprende no seguinte post:
      https://www.makerhero.com/blog/esp8266-gravando-dados-memoria-flash/

      Obrigado pela leitura! Abraço e bons estudos!