Arduino UNO R4 - Sensor de Cor via Web

Este projeto divertido combina o sensor de cor TCS3200D/TCS230 com um personagem Minion na web. O Arduino UNO R4 WiFi lê as cores do sensor e envia a cor detectada para um navegador web via WebSocket. O Minion na página web muda a cor da pele em tempo real para combinar com qualquer cor que você colocar na frente do sensor! Para facilitar a criação da interface web e o tratamento da comunicação em tempo real, vamos usar a biblioteca DIYables WebApps.

Também oferecemos um vídeo com instruções passo a passo no final deste tutorial.

Arduino UNO R4 TCS3200 TCS230 sensor de cor web Minion

Sobre o Sensor de Cor TCS3200D/TCS230 e o DIYables WebApps

Saiba mais sobre o sensor de cor TCS3200D/TCS230, a biblioteca DIYables WebApps e como criar aplicativos web personalizados nos tutoriais abaixo:

Diagrama de Ligação

Esta imagem mostra como conectar o sensor de cor TCS3200 ao Arduino UNO R4 WiFi:

Sensor de Cor TCS3200Arduino UNO R4
VCC5V
GNDGND
S0Pino 4
S1Pino 3
S2Pino 6
S3Pino 5
OUTPino 7
Diagrama de ligação do Arduino UNO R4 e do sensor de cor TCS3200 mostrando a conexão entre os pinos

This image is created using Fritzing. Click to enlarge image

Veja A melhor forma de alimentar o Arduino Uno R4 e outros componentes.

Como Funciona

  1. O Arduino lê o sensor de cor a cada 1 segundo.
  2. Em cada leitura, ele seleciona os filtros vermelho, verde e azul, um de cada vez, usando os pinos S2/S3, e depois mede a largura de pulso no pino OUT.
  3. Os valores brutos de largura de pulso são mapeados para valores RGB de 0-255 usando valores de calibração (do passo de calibração).
  4. Os valores RGB são convertidos em uma string de cor HEX (por exemplo, #FF8000).
  5. A string de cor HEX é enviada ao navegador web via WebSocket usando a biblioteca DIYables WebApps.
  6. A página web recebe a cor e atualiza o corpo, os braços e as pálpebras do Minion para essa cor em tempo real.

Código Arduino UNO R4 - Aplicativo Web Minion com Sensor de Cor

O código é composto por 4 arquivos:

  • ColorSensor.ino - Sketch principal do Arduino: lê o sensor de cor e envia a cor para a página web
  • CustomWebApp.h - Arquivo de cabeçalho: define a classe da página do aplicativo web personalizado
  • CustomWebApp.cpp - Arquivo de implementação: trata a comunicação WebSocket com o identificador "Color Sensor:"
  • custom_page_html.h - Página web: contém o HTML/CSS/JavaScript do Minion animado que recebe as cores e atualiza a pele do Minion

ColorSensor.ino

/* * Este código de Arduino UNO R4 foi desenvolvido por pt.newbiely.com * Este código de Arduino UNO R4 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-uno-r4/arduino-uno-r4-color-sensor-via-web */ #include <DIYablesWebApps.h> #include "CustomWebApp.h" // CHANGE THESE TO YOUR WIFI DETAILS const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; int status = WL_IDLE_STATUS; // TCS3200 Pins const int S0 = 4, S1 = 3, S2 = 6, S3 = 5, sensorOut = 7; UnoR4ServerFactory serverFactory; DIYablesWebAppServer webAppsServer(serverFactory, 80, 81); DIYablesHomePage homePage; CustomWebAppPage customPage; unsigned long lastColorRead = 0; void setup() { Serial.begin(9600); // Initialize TCS3200 pins pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); pinMode(sensorOut, INPUT); digitalWrite(S0, HIGH); digitalWrite(S1, LOW); // 20% frequency scaling webAppsServer.addApp(&homePage); webAppsServer.addApp(&customPage); // Check for the WiFi module if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); // Stop program execution while (true); } String fv = WiFi.firmwareVersion(); if (fv < WIFI_FIRMWARE_LATEST_VERSION) { Serial.println("Please upgrade the firmware"); } // Attempt to connect to WiFi network while (status != WL_CONNECTED) { // Connect to WPA/WPA2 network (change if using open or WEP) status = WiFi.begin(WIFI_SSID, WIFI_PASSWORD); // Wait 10 seconds for connection delay(10000); } webAppsServer.begin(); Serial.println("Color Web Server Ready!"); } void loop() { webAppsServer.loop(); // Read color every 1 second if (millis() - lastColorRead > 1000) { // Read Red color digitalWrite(S2, LOW); digitalWrite(S3, LOW); int r = map(pulseIn(sensorOut, LOW), 31, 150, 255, 0); // Read Green color digitalWrite(S2, HIGH); digitalWrite(S3, HIGH); int g = map(pulseIn(sensorOut, LOW), 35, 180, 255, 0); // Read Blue color digitalWrite(S2, LOW); digitalWrite(S3, HIGH); int b = map(pulseIn(sensorOut, LOW), 30, 150, 255, 0); // Convert to HEX and send to Web char hexColor[8]; sprintf(hexColor, "#%02X%02X%02X", constrain(r, 0, 255), constrain(g, 0, 255), constrain(b, 0, 255)); customPage.sendToWeb(String(hexColor)); Serial.println("Sent to Minion: " + String(hexColor)); lastColorRead = millis(); } }

CustomWebApp.h

/* * Este código de Arduino UNO R4 foi desenvolvido por pt.newbiely.com * Este código de Arduino UNO R4 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-uno-r4/arduino-uno-r4-color-sensor-via-web */ #ifndef CUSTOM_WEBAPP_H #define CUSTOM_WEBAPP_H #include <DIYablesWebApps.h> /** * Simple Custom WebApp Page * * This is a template for creating your own custom web applications. * It provides basic controls like buttons and sliders that communicate * with your Arduino in real-time. */ class CustomWebAppPage : public DIYablesWebAppPageBase { private: // WebSocket message identifier for this custom app static const String APP_IDENTIFIER; public: CustomWebAppPage(); // ======================================== // REQUIRED METHODS - USED BY LIBRARY - DON'T CHANGE THESE! // ======================================== void handleHTTPRequest(IWebClient& client) override; void handleWebSocketMessage(IWebSocket& ws, const char* message, uint16_t length) override; const char* getPageInfo() const override; String getNavigationInfo() const override; // ======================================== // YOUR METHODS - USE THESE IN YOUR CODE! // ======================================== void onCustomMessageReceived(void (*callback)(const String& payload)); void sendToWeb(const String& message); }; #endif

CustomWebApp.cpp

/* * Este código de Arduino UNO R4 foi desenvolvido por pt.newbiely.com * Este código de Arduino UNO R4 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-uno-r4/arduino-uno-r4-color-sensor-via-web */ #include "CustomWebApp.h" #include "custom_page_html.h" // Define the static member - WebSocket message identifier for this custom app const String CustomWebAppPage::APP_IDENTIFIER = "Color Sensor:"; // Callback function for handling messages from web browser void (*customMessageCallback)(const String& payload) = nullptr; CustomWebAppPage::CustomWebAppPage() : DIYablesWebAppPageBase("/custom") { } void CustomWebAppPage::handleHTTPRequest(IWebClient& client) { // Send the HTML page to web browser sendHTTPHeader(client); client.print(CUSTOM_PAGE_HTML); } void CustomWebAppPage::handleWebSocketMessage(IWebSocket& ws, const char* message, uint16_t length) { String messageStr = String(message, length); Serial.print("Color Sensor WebApp received: "); Serial.println(messageStr); // Only handle messages that start with our app identifier if (messageStr.startsWith(APP_IDENTIFIER)) { String payload = messageStr.substring(APP_IDENTIFIER.length()); // Remove identifier // Call your callback function with the payload if (customMessageCallback) { customMessageCallback(payload); } } } void CustomWebAppPage::onCustomMessageReceived(void (*callback)(const String& payload)) { customMessageCallback = callback; } void CustomWebAppPage::sendToWeb(const String& message) { // Send message to web browser with app identifier String fullMessage = APP_IDENTIFIER + message; broadcastToAllClients(fullMessage.c_str()); } const char* CustomWebAppPage::getPageInfo() const { return "🔧 Color Sensor WebApp"; } String CustomWebAppPage::getNavigationInfo() const { String result = "<a href=\""; result += getPagePath(); result += "\" class=\"app-card custom\" style=\"background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);\">"; result += "<h3>🔧 Color Sensor WebApp</h3>"; result += "<p>Simple template for your own apps</p>"; result += "</a>"; return result; }

custom_page_html.h

/* * Este código de Arduino UNO R4 foi desenvolvido por pt.newbiely.com * Este código de Arduino UNO R4 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-uno-r4/arduino-uno-r4-color-sensor-via-web */ #ifndef CUSTOM_PAGE_HTML_H #define CUSTOM_PAGE_HTML_H const char CUSTOM_PAGE_HTML[] PROGMEM = R"HTML_WRAPPER( <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>Mobile Laughing Minion</title> <style> body { margin: 0; padding: 20px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: flex-start; align-items: center; background-color: #f0f8ff; font-family: sans-serif; overflow-x: hidden; } .text { font-size: clamp(16px, 5vw, 24px); font-weight: bold; color: #333; margin-bottom: 20px; text-align: center; z-index: 10; } .scale-wrapper { transform-origin: top center; display: flex; justify-content: center; align-items: flex-start; } .minion-container { position: relative; width: 200px; height: 400px; } .body { position: absolute; top: 20px; left: 25px; width: 150px; height: 300px; background-color: #FFD90F; border-radius: 75px; box-shadow: inset -10px -10px 20px rgba(0,0,0,0.1); overflow: hidden; z-index: 2; transition: background-color 0.5s; } .overalls { position: absolute; bottom: 0; width: 100%; height: 90px; background-color: #225A94; border-radius: 0 0 75px 75px; box-shadow: inset -10px -10px 20px rgba(0,0,0,0.2); } .pocket { position: absolute; bottom: 30px; left: 50px; width: 50px; height: 40px; background-color: #1A4674; border-radius: 10px 10px 20px 20px; border: 2px dashed #fce144; } .strap { position: absolute; top: 65px; left: 0; width: 100%; height: 25px; background-color: #333; z-index: 1; } .goggles-wrapper { position: absolute; top: 50px; left: -5px; width: 160px; display: flex; justify-content: center; z-index: 3; } .goggle { position: relative; width: 50px; height: 50px; background-color: white; border: 12px solid #999; border-radius: 50%; box-shadow: 3px 3px 8px rgba(0,0,0,0.2), inset 3px 3px 8px rgba(0,0,0,0.1); margin: 0 -2px; overflow: hidden; } .pupil { position: absolute; top: 50%; left: 50%; width: 20px; height: 20px; background-color: #4B3621; border-radius: 50%; transform: translate(-50%, -50%); transition: transform 0.2s ease-out; } .pupil::after { content: ''; position: absolute; top: 4px; left: 4px; width: 6px; height: 6px; background-color: black; border-radius: 50%; } .catchlight { position: absolute; top: 2px; right: 4px; width: 4px; height: 4px; background-color: white; border-radius: 50%; z-index: 4; } .eyelid { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: #FFD90F; border-bottom: 3px solid #D4B200; transform-origin: top; transform: scaleY(0); z-index: 5; animation: blink 4s infinite; } .mouth { position: absolute; top: 145px; left: 35px; width: 80px; height: 45px; background-color: #3E2723; border-radius: 10px 10px 60px 60px; overflow: hidden; z-index: 3; box-shadow: inset 0 5px 10px rgba(0,0,0,0.5); animation: laugh 0.2s infinite alternate ease-in-out; } .teeth { position: absolute; top: 0; left: 0; width: 100%; height: 14px; background-color: #fff; border-radius: 0 0 5px 5px; } .tongue { position: absolute; bottom: -5px; left: 20px; width: 40px; height: 25px; background-color: #FF5252; border-radius: 50%; animation: wag 0.2s infinite alternate ease-in-out; } .arm { position: absolute; top: 140px; width: 25px; height: 80px; background-color: #FFD90F; border-radius: 12px; z-index: 1; transition: background-color 0.5s; } .arm.left { left: 10px; transform: rotate(35deg); } .arm.right { right: 15px; transform: rotate(-35deg); } .glove { position: absolute; bottom: -15px; left: -5px; width: 35px; height: 35px; background-color: #333; border-radius: 50%; } .leg { position: absolute; bottom: 50px; width: 25px; height: 40px; background-color: #225A94; z-index: 1; } .leg.left { left: 60px; } .leg.right { left: 115px; } .shoe { position: absolute; bottom: -15px; left: -10px; width: 45px; height: 20px; background-color: #222; border-radius: 20px 20px 5px 5px; border-bottom: 5px solid #111; } @keyframes blink { 0%, 94%, 100% { transform: scaleY(0); } 97% { transform: scaleY(1); } } @keyframes laugh { 0% { height: 40px; transform: scaleX(1); } 100% { height: 55px; transform: scaleX(1.05); } } @keyframes wag { 0% { transform: translateY(0); } 100% { transform: translateY(-3px); } } </style> </head> <body> <div class="text" id="status-text">Just watch him look around! 👀</div> <div class="scale-wrapper" id="minionWrapper"> <div class="minion-container"> <div class="arm left" id="armL"><div class="glove"></div></div> <div class="arm right" id="armR"><div class="glove"></div></div> <div class="leg left"><div class="shoe"></div></div> <div class="leg right"><div class="shoe"></div></div> <div class="body" id="minionBody"> <div class="overalls"> <div class="pocket"></div> </div> <div class="strap"></div> <div class="goggles-wrapper"> <div class="goggle"><div class="pupil"><div class="catchlight"></div></div><div class="eyelid" id="eyelidL"></div></div> <div class="goggle"><div class="pupil"><div class="catchlight"></div></div><div class="eyelid" id="eyelidR"></div></div> </div> <div class="mouth"> <div class="teeth"></div> <div class="tongue"></div> </div> </div> </div> </div> <script> const APP_IDENTIFIER = 'Color Sensor:'; let ws = null; function connectWebSocket() { ws = new WebSocket('ws://' + location.hostname + ':81'); ws.onopen = () => document.getElementById('status-text').textContent = "Arduino Uno R4 - Color Sensor"; ws.onclose = () => setTimeout(connectWebSocket, 2000); ws.onmessage = (event) => { if (event.data.startsWith(APP_IDENTIFIER)) { let color = event.data.substring(APP_IDENTIFIER.length); // Cập nhật màu cho thân, tay và mí mắt document.getElementById('minionBody').style.backgroundColor = color; document.getElementById('armL').style.backgroundColor = color; document.getElementById('armR').style.backgroundColor = color; document.getElementById('eyelidL').style.backgroundColor = color; document.getElementById('eyelidR').style.backgroundColor = color; document.getElementById('status-text').style.color = color; } }; } function resizeMinion() { const wrapper = document.getElementById('minionWrapper'); const availableWidth = window.innerWidth - 40; const minionTrueWidth = 260; const minionHeight = 400; let scaleFactor = availableWidth / minionTrueWidth; if (scaleFactor > 1.5) scaleFactor = 1.5; wrapper.style.transform = `scale(${scaleFactor})`; wrapper.style.height = `${minionHeight * scaleFactor}px`; } window.addEventListener('resize', resizeMinion); resizeMinion(); connectWebSocket(); const pupils = document.querySelectorAll('.pupil'); function moveEyesAutomatically() { const angle = Math.random() * Math.PI * 2; const distance = Math.random() * 15; const pupilX = Math.cos(angle) * distance; const pupilY = Math.sin(angle) * distance; pupils.forEach(pupil => { pupil.style.transform = `translate(calc(-50% + ${pupilX}px), calc(-50% + ${pupilY}px))`; }); } setInterval(moveEyesAutomatically, 600); </script> </body> </html> )HTML_WRAPPER"; #endif

Passos Rápidos

Siga estas instruções passo a passo:

  • Se esta é a sua primeira vez usando o Arduino Uno R4 WiFi, consulte o tutorial sobre como configurar o ambiente para o Arduino Uno R4 WiFi na Arduino IDE.
  • Calibre primeiro o seu sensor de cor seguindo o guia de calibração do TCS3200D/TCS230. Anote os seus valores de calibração (redMin, redMax, greenMin, greenMax, blueMin, blueMax).
  • Ligue os componentes conforme o diagrama de ligação acima.
  • Conecte a placa Arduino Uno R4 WiFi ao seu computador usando um cabo USB.
  • Abra a Arduino IDE no seu computador.
  • Selecione a placa Arduino Uno R4 apropriada (por exemplo, Arduino Uno R4 WiFi) e a porta COM.
  • Vá até o ícone Libraries na barra à esquerda da Arduino IDE.
  • Pesquise "DIYables WebApps" e encontre a biblioteca DIYables WebApps da DIYables.
  • Clique no botão Install para instalar a biblioteca.
  • Será pedido que você instale algumas outras dependências da biblioteca.
  • Clique no botão Install All para instalar todas as dependências da biblioteca.
Arduino UNO R4 biblioteca DIYables WebApps
Arduino UNO R4 dependência do DIYables WebApps
  • Crie um novo sketch na Arduino IDE e dê a ele o nome ColorSensor.
  • Copie e cole os 4 arquivos acima no projeto da Arduino IDE. O projeto da Arduino IDE deve ter 4 arquivos, como mostrado abaixo:
Arduino UNO R4 arquivos do projeto do aplicativo web do sensor de cor na Arduino IDE
  • No arquivo ColorSensor.ino, atualize os dados de Wi-Fi (SSID e senha) com os seus:
const char WIFI_SSID[] = "YOUR_WIFI_NAME"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
  • Atualize os valores de calibração nas chamadas map() dentro de loop() com os seus próprios valores de calibração do passo de calibração. Por exemplo, se a sua calibração deu redMin = 42, redMax = 210, greenMin = 55, greenMax = 185, blueMin = 60, blueMax = 172, mude as linhas para:
int r = map(pulseIn(sensorOut, LOW), 42, 210, 255, 0); int g = map(pulseIn(sensorOut, LOW), 55, 185, 255, 0); int b = map(pulseIn(sensorOut, LOW), 60, 172, 255, 0);
  • Clique no botão Upload na Arduino IDE para fazer o upload do código para o Arduino UNO R4.
  • Abra o Serial Monitor. Você verá uma saída como esta:
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Uno R4 WiFi
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Uno R4 WiFi' on 'COM15')
New Line
9600 baud
Color Web Server Ready! INFO: Added app / INFO: Added app /custom DIYables WebApp Library Platform: Arduino Uno R4 WiFi Network connected! IP address: 192.168.0.2 HTTP server started on port 80 WebSocket server started on port 81 ========================================== DIYables WebApp Ready! ========================================== 📱 Web Interface: http://192.168.0.2 🔗 WebSocket: ws://192.168.0.2:81 📋 Available Applications: 🏠 Home Page: http://192.168.0.2/ 🔧 Color Sensor WebApp: http://192.168.0.2/custom ========================================== Sent to Minion: #FFD200 Sent to Minion: #00C832 Sent to Minion: #0028FF
Ln 11, Col 1
Arduino Uno R4 WiFi on COM15
2
  • Se você não vir nada, reinicie a placa Arduino.
  • Anote o endereço IP exibido e digite esse endereço na barra de endereços de um navegador web no seu celular ou PC.
  • Exemplo: http://192.168.0.2
  • Você verá a página inicial. Clique no link Color Sensor WebApp.
  • Ou você pode acessar a página do Minion diretamente pelo endereço IP seguido de /custom. Por exemplo: http://192.168.0.2/custom
  • Você verá o personagem Minion animado na página web.
  • Coloque um objeto colorido na frente do sensor TCS3200 — a cor da pele do Minion vai mudar em tempo real para combinar com a cor detectada!

Você pode ver as instruções passo a passo no vídeo abaixo.

Como o Código Funciona

Lado do Arduino (ColorSensor.ino)

O sketch principal faz o seguinte:

  • Inicializa os pinos do sensor TCS3200: S0 e S1 são configurados para a escala de frequência de 20%. S2 e S3 são usados para selecionar os filtros de cor.
  • Lê a cor a cada 1 segundo: No loop(), o Arduino seleciona os filtros vermelho, verde e azul um por um, lê a largura de pulso usando pulseIn() e mapeia os valores brutos para valores RGB de 0-255 usando os seus números de calibração.
  • Converte para HEX: Os valores RGB são formatados em uma string de cor HEX como #FF8000 usando sprintf().
  • Envia ao navegador web: A string HEX é enviada a todos os clientes web conectados por meio de customPage.sendToWeb().

Lado da Página Web (custom_page_html.h)

A página HTML contém:

  • Um personagem Minion animado construído inteiramente com CSS — incluindo olhos que piscam, uma boca que ri e pupilas que se movem aleatoriamente.
  • Conexão WebSocket: O JavaScript se conecta ao servidor WebSocket do Arduino (porta 81) e escuta as mensagens de cor recebidas.
  • Atualização da cor: Quando uma mensagem como #FF8000 é recebida, o corpo, os braços e as pálpebras do Minion fazem uma transição suave para a nova cor usando transition do CSS.
  • Reconexão automática: Se a conexão WebSocket cair, a página tenta se reconectar automaticamente a cada 2 segundos.
  • Design responsivo: O Minion se ajusta automaticamente para caber em diferentes tamanhos de tela (celulares, tablets, desktops).

Protocolo de Comunicação

Este projeto usa o framework de aplicativo web personalizado do DIYables WebApps com o identificador "Color Sensor:":

  • O Arduino envia: Color Sensor:#FF8000 (identificador + cor HEX)
  • A página web recebe: Remove o identificador e aplica o restante da cor HEX #FF8000 ao Minion

Para mais detalhes sobre o protocolo de comunicação e como personalizar o aplicativo web, veja o tutorial DIYables WebApps Custom WebApp.

※ NOSSAS MENSAGENS

  • Fique à vontade para compartilhar o link deste tutorial. Porém, por favor, não use nosso conteúdo em outros sites. Investimos muito esforço e tempo para criar este conteúdo, por favor respeite nosso trabalho!