In this project we’ll show you how to build an IoT shield PCB for the ESP32 and a web server dashboard to control it. The shield is equipped with a BME280 sensor (temperature, humidity and pressure), an LDR (light dependent resistor), a PIR motion sensor, a status LED, a pushbutton and a terminal socket to connect a relay module or any other output.
Alternatively, you can also follow this project by wiring the circuit on a breadboard.
Watch the Video Tutorial
This project is available in video format and in written format. You can watch the video below or you can scroll down for the written instructions.
Resources
You can find all the resources needed to build this project in the links below (or you can visit the GitHub project):
- ESP32 Web Server Code (Arduino IDE)
- Schematic diagram
- Gerber files
- EasyEDA project to edit the PCB
- Click here to download all the files
Project Overview
This project consists of two parts:
IoT Shield Features
The IoT sensor shield is designed to be stacked to the ESP32. For this reason, if you want to use our PCB, you need the same ESP32 board. We’re using the ESP32 DEVKIT DOIT V1 board (the model with 36 GPIOs).
If you have another ESP32 model, you can still follow this project by assembling the circuit on a breadboard or modifying the PCB layout and wiring to match your ESP32 board.
The shield consists of:
- BME280 temperature, humidity and pressure sensor;
- LDR (light dependent resistor);
- PIR motion sensor;
- Status on-board LED;
- Pushbutton;
- 3-pin socket that gives you access to GND, 5V and a GPIO where you can connect any output (like a relay module for example).
ESP32 IoT Shield Pin Assignment
The following table describes the pin assignment for each component of the IoT shield:
Component | ESP32 Pin Assignment |
BME280 | GPIO 21 (SDA), GPIO 22 (SCL) |
PIR Motion Sensor | GPIO 27 |
Light Dependent Resistor (LDR) | GPIO 33 |
Pushbutton | GPIO 18 |
LED | GPIO 19 |
Additional Output | GPIO 32 |
If you want to assign and use different pins, read our ESP32 Pinout Reference Guide.
Web Server (IoT Dashboard) Features
To control the shield, we’ll build a web server. However, you can program the sensor shield as you wish with any other web server or to integrate it with a home automation platform.
Here’s the web server features to control the IoT shield:
- To access the web server, you need to login with username and password (read: ESP32 Web Server HTTP Authentication: Username and Password Protected).
- After authenticating with the right credentials, you can access the web server. There’s an icon at the top of the web page that you can click to logout. Then, you’ll need to login again.
- There are two toggle switches: one to control the output socket and another for the on-board status LED.
- The status LED can also be controlled using the physical on-shield pushbutton. The state of the LED automatically updates on the web page (like in this tutorial: Control Outputs with Web Server and a Physical Button Simultaneously). The toggle switch for the status LED can be useful to activate or deactivate something on the ESP32 and the LED gives you a visual feedback of what’s going on.
- The temperature, humidity and luminosity are displayed on the web server and are automatically updated using server-sent events (SSE).
- Finally, there’s a card that indicates if motion was detected. After receiving the “Motion Detected” notification, you can click on the card to clear the warning.
These are the main features of the ESP32 IoT dashboard we’re going to build. This combines many of the subjects approached in previous tutorials.
This is just an example on how you can control your shield. The idea is to modify the code to add your own features to the project.
Testing the Circuit on a Breadboard
Before designing and building the PCB shield, it’s important to test the circuit on a breadboard. If you don’t want to make a PCB, you can still follow this project by assembling the circuit on a breadboard.
Parts Required
To assemble the circuit on a breadboard you need the following parts:
- DOIT ESP32 DEVKIT V1 Board (version with 36 GPIOs) – read Best ESP32 Development Boards
- 2x 5mm LED
- 2x 330 Ohm resistor
- 1x BME280 (4 pins)
- 1x mini PIR motion sensor
- 1x light dependent resistor
- 2x 10k Ohm resistor
- 1x pushbutton
- Breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
After gathering all the parts, assemble the circuit by following the next schematic diagram:
Designing the PCB
To design the circuit and PCB, we used EasyEDA which is a browser based software to design PCBs. If you want to customize your PCB, you just need to upload the following files:
Designing the circuit works like in any other circuit software tool, you place some components and you wire them together. Then, you assign each component to a footprint.
Having the parts assigned, place each component. When you’re happy with the layout, make all the connections and route your PCB.
Save your project and export the Gerber files.
Note: you can grab the project files and edit them to customize the shield for your own needs.
Ordering the PCBs at PCBWay
This project is sponsored by PCBWay. PCBWay is a full feature Printed Circuit Board manufacturing service.
Turn your DIY breadboard circuits into professional PCBs – get 10 boards for approximately $5 + shipping (which will vary depending on your country).
Once you have your Gerber files, you can order the PCB. Follow the next steps to download the file.
1. Download the Gerber files – click here to download the .zip file
2. Go to PCBWay website and open the PCB Instant Quote page.
3. PCBWay can grab all the PCB details and automatically fill them for you. Use the “Quick-order PCB (Autofill parameters)”.
4. Press the “+ Add Gerber file” button to upload the provided Gerber files.
And that’s it. You can also use the OnlineGerberViewer to check if your PCB is looking as it should.
If you aren’t in a hurry, you can use the China Post shipping method to lower your cost significantly. In our opinion, we think they overestimate the China Post shipping time.
You can increase your PCB order quantity and change the solder mask color. I’ve ordered the Blue color.
Once you’re ready, you can order the PCBs by clicking “Save to Cart” and complete your order.
Unboxing
After approximately one week using the DHL shipping method, I received the PCBs at my office.
Everything comes well packed, and the PCBs are really high-quality. The letters on the silkscreen are really well-printed and easy to read. Additionally, the solder sticks easily to the pads.
Besides the PCBs, I also received some stickers, a ruler and a pen. Overall, we’re really satisfied with the PCBWay service.
Soldering the Components
The next step is soldering the components to the PCB. I’ve used an SMD LED and SMD resistors. These can be a bit difficult to solder, but they save a lot of space on the PCB.
Here’s a list of all the components needed to build the PCB shield:
- 1x SMD LED (1206)
- 1x 330 Ohm SMD resistors (1206)
- 2x 10k Ohm SMD resistor (1206)
- 1x Pushbutton (0.55 mm)
- 1x BME280
- 1x Mini PIR motion sensor
- 1x Light dependent resistor
- 1x Screw terminal blocks
- Female pin header socket (2.54 mm)
Here’s the soldering tools I’ve used:
Read our review about the TS80 Soldering Iron: TS80 Soldering Iron Review – Best Portable Soldering Iron.
Start by soldering the SMD components. Then, solder the header pins. And finally, solder the other components or use header pins if you don’t want to connect the components permanently.
Here’s how the ESP32 IoT Shield looks like after assembling all the parts. It should connect perfectly to the ESP32 DEVKIT DOIT V1 board.
Programming the ESP32 IoT Shield
The code for this project runs a web server that allows you to monitor and control the IoT shield. The features of the web server were covered previously.
We’ll program the ESP32 board using Arduino IDE. So make sure you have the ESP32 board add-on installed.
Installing Libraries
Before uploading the code, make sure you have the following libraries installed:
Follow the next steps to install the libraries:
Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries. The Library Manager should open.
Search for “adafruit bme280 ” on the Search box and install the library.
To use the BME280 library, you also need to install the Adafruit_Sensor library. Follow the next steps to install the library in your Arduino IDE:
Go to Sketch > Include Library > Manage Libraries and type “Adafruit Unified Sensor” in the search box. Scroll all the way down to find the library and install it.
To install the ESPAsyncWebServer and the AsyncTCP libraries, click on the following links to download the .zip folder:
These libraries aren’t available to install through the Arduino Library Manager, so you need to copy the library files to the Arduino Installation Libraries folder. Alternatively, in your Arduino IDE, you can go to Sketch > Include Library > Add .zip Library and select the libraries you’ve just downloaded.
Code – ESP32 IoT Shied Web Server Dashboard
Copy the following code to the Arduino IDE.
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-iot-shield-pcb-dashboard/
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
// Import required libraries
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Web Server HTTP Authentication credentials
const char* http_username = "admin";
const char* http_password = "admin";
Adafruit_BME280 bme; // BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)
const int buttonPin = 18; // Pushbutton
const int ledPin = 19; // Status LED
const int output = 32; // Output socket
const int ldr = 33; // LDR (Light Dependent Resistor)
const int motionSensor = 27; // PIR Motion Sensor
int ledState = LOW; // current state of the output pin
int buttonState; // current reading from the input pin
int lastButtonState = LOW; // previous reading from the input pin
bool motionDetected = false; // flag variable to send motion alert message
bool clearMotionAlert = true; // clear last motion alert message from web page
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncEventSource events("/events");
const char* PARAM_INPUT_1 = "state";
// Checks if motion was detected
void IRAM_ATTR detectsMovement() {
//Serial.println("MOTION DETECTED!!!");
motionDetected = true;
clearMotionAlert = false;
}
// Main HTML web page in root url /
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP IOT DASHBOARD</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h3 {font-size: 1.8rem; color: white;}
h4 { font-size: 1.2rem;}
p { font-size: 1.4rem;}
body { margin: 0;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px; margin-bottom: 20px;}
.switch input {display: none;}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 68px; opacity: 0.8; cursor: pointer;}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
input:checked+.slider {background-color: #1b78e2}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
.topnav { overflow: hidden; background-color: #1b78e2;}
.content { padding: 20px;}
.card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);}
.cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));}
.slider2 { -webkit-appearance: none; margin: 14px; height: 20px; background: #ccc; outline: none; opacity: 0.8; -webkit-transition: .2s; transition: opacity .2s; margin-bottom: 40px; }
.slider:hover, .slider2:hover { opacity: 1; }
.slider2::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 40px; height: 40px; background: #008B74; cursor: pointer; }
.slider2::-moz-range-thumb { width: 40px; height: 40px; background: #008B74; cursor: pointer;}
.reading { font-size: 2.6rem;}
.card-switch {color: #50a2ff; }
.card-light{ color: #008B74;}
.card-bme{ color: #572dfb;}
.card-motion{ color: #3b3b3b; cursor: pointer;}
.icon-pointer{ cursor: pointer;}
</style>
</head>
<body>
<div class="topnav">
<h3>ESP IOT DASHBOARD <span style="text-align:right;"> <i class="fas fa-user-slash icon-pointer" onclick="logoutButton()"></i></span></h3>
</div>
<div class="content">
<div class="cards">
%BUTTONPLACEHOLDER%
<div class="card card-bme">
<h4><i class="fas fa-chart-bar"></i> TEMPERATURE</h4><div><p class="reading"><span id="temp"></span>°C</p></div>
</div>
<div class="card card-bme">
<h4><i class="fas fa-chart-bar"></i> HUMIDITY</h4><div><p class="reading"><span id="humi"></span>%</p></div>
</div>
<div class="card card-light">
<h4><i class="fas fa-sun"></i> LIGHT</h4><div><p class="reading"><span id="light"></span></p></div>
</div>
<div class="card card-motion" onClick="clearMotionAlert()">
<h4><i class="fas fa-running"></i> MOTION SENSOR</h4><div><p class="reading"><span id="motion">%MOTIONMESSAGE%</span></p></div>
</div>
</div>
<script>
function logoutButton() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/logout", true);
xhr.send();
setTimeout(function(){ window.open("/logged-out","_self"); }, 1000);
}
function controlOutput(element) {
var xhr = new XMLHttpRequest();
if(element.checked){ xhr.open("GET", "/output?state=1", true); }
else { xhr.open("GET", "/output?state=0", true); }
xhr.send();
}
function toggleLed(element) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/toggle", true);
xhr.send();
}
function clearMotionAlert() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/clear-motion", true);
xhr.send();
setTimeout(function(){
document.getElementById("motion").innerHTML = "No motion";
document.getElementById("motion").style.color = "#3b3b3b";
}, 1000);
}
if (!!window.EventSource) {
var source = new EventSource('/events');
source.addEventListener('open', function(e) {
console.log("Events Connected");
}, false);
source.addEventListener('error', function(e) {
if (e.target.readyState != EventSource.OPEN) {
console.log("Events Disconnected");
}
}, false);
source.addEventListener('message', function(e) {
console.log("message", e.data);
}, false);
source.addEventListener('led_state', function(e) {
console.log("led_state", e.data);
var inputChecked;
if( e.data == 1){ inputChecked = true; }
else { inputChecked = false; }
document.getElementById("led").checked = inputChecked;
}, false);
source.addEventListener('motion', function(e) {
console.log("motion", e.data);
document.getElementById("motion").innerHTML = e.data;
document.getElementById("motion").style.color = "#b30000";
}, false);
source.addEventListener('temperature', function(e) {
console.log("temperature", e.data);
document.getElementById("temp").innerHTML = e.data;
}, false);
source.addEventListener('humidity', function(e) {
console.log("humidity", e.data);
document.getElementById("humi").innerHTML = e.data;
}, false);
source.addEventListener('light', function(e) {
console.log("light", e.data);
document.getElementById("light").innerHTML = e.data;
}, false);
}</script>
</body>
</html>)rawliteral";
String outputState(int gpio){
if(digitalRead(gpio)){
return "checked";
}
else {
return "";
}
}
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons;
String outputStateValue = outputState(32);
buttons+="<div class=\"card card-switch\"><h4><i class=\"fas fa-lightbulb\"></i> OUTPUT</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"controlOutput(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label></div>";
outputStateValue = outputState(19);
buttons+="<div class=\"card card-switch\"><h4><i class=\"fas fa-lightbulb\"></i> STATUS LED</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleLed(this)\" id=\"led\" " + outputStateValue + "><span class=\"slider\"></span></label></div>";
return buttons;
}
else if(var == "MOTIONMESSAGE"){
if(!clearMotionAlert) {
return String("<span style=\"color:#b30000;\">MOTION DETECTED!</span>");
}
else {
return String("No motion");
}
}
return String();
}
// Logged out web page
const char logout_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>Logged out or <a href="/">return to homepage</a>.</p>
<p><strong>Note:</strong> close all web browser tabs to complete the logout process.</p>
</body>
</html>
)rawliteral";
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
// initialize the pushbutton pin as an input
pinMode(buttonPin, INPUT);
// initialize the LED pin as an output
pinMode(ledPin, OUTPUT);
// initialize the LED pin as an output
pinMode(output, OUTPUT);
// PIR Motion Sensor mode INPUT_PULLUP
pinMode(motionSensor, INPUT_PULLUP);
// Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
request->send_P(200, "text/html", index_html, processor);
});
server.on("/logged-out", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", logout_html, processor);
});
server.on("/logout", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(401);
});
// Send a GET request to control output socket <ESP_IP>/output?state=<inputMessage>
server.on("/output", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
String inputMessage;
// GET gpio and state value
if (request->hasParam(PARAM_INPUT_1)) {
inputMessage = request->getParam(PARAM_INPUT_1)->value();
digitalWrite(output, inputMessage.toInt());
request->send(200, "text/plain", "OK");
}
request->send(200, "text/plain", "Failed");
});
// Send a GET request to control on board status LED <ESP_IP>/toggle
server.on("/toggle", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
ledState = !ledState;
digitalWrite(ledPin, ledState);
request->send(200, "text/plain", "OK");
});
// Send a GET request to clear the "Motion Detected" message <ESP_IP>/clear-motion
server.on("/clear-motion", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
clearMotionAlert = true;
request->send(200, "text/plain", "OK");
});
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
// send event with message "hello!", id current millis and set reconnect delay to 1 second
client->send("hello!",NULL,millis(),1000);
});
server.addHandler(&events);
// Start server
server.begin();
}
void loop(){
static unsigned long lastEventTime = millis();
static const unsigned long EVENT_INTERVAL_MS = 10000;
// read the state of the switch into a local variable
int reading = digitalRead(buttonPin);
// If the switch changed
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
ledState = !ledState;
digitalWrite(ledPin, ledState);
events.send(String(digitalRead(ledPin)).c_str(),"led_state",millis());
}
}
}
if ((millis() - lastEventTime) > EVENT_INTERVAL_MS) {
events.send("ping",NULL,millis());
events.send(String(bme.readTemperature()).c_str(),"temperature",millis());
events.send(String(bme.readHumidity()).c_str(),"humidity",millis());
events.send(String(analogRead(ldr)).c_str(),"light",millis());
lastEventTime = millis();
}
if(motionDetected & !clearMotionAlert){
events.send(String("MOTION DETECTED!").c_str(),"motion",millis());
motionDetected = false;
}
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}
This code is quite long to explain, so you can simply replace the following two variables with your network credentials and the code will work straight away.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
If you want to learn how this code works, continue reading. Otherwise, you can skip to the Demonstration section.
How the Code Works
Read this section if you want to learn how the code works, or skip to the next section.
The following lines import the required libraries:
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
Insert your network credentials in the following lines so that the ESP32 can connect to your network.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
The next lines define the username and password to access the web server. By default the username is admin and the password is admin. You can change them on the following lines:
// Web Server HTTP Authentication credentials
const char* http_username = "admin";
const char* http_password = "admin";
Create an Adafruit_BME280 object called bme. This creates an I2C connection to the BME280 on GPIO 21 and GPIO 22.
Adafruit_BME280 bme; // BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)
Then, define the GPIOs the components of the shield are connected to.
const int buttonPin = 18; // Pushbutton
const int ledPin = 19; // Status LED
const int output = 32; // Output socket
const int ldr = 33; // LDR (Light Dependent Resistor)
const int motionSensor = 27; // PIR Motion Sensor
Create the following variables to old states. The comments explain what each variable means.
int ledState = LOW; // current state of the output pin
int buttonState; // current reading from the input pin
int lastButtonState = LOW; // previous reading from the input pin
bool motionDetected = false; // flag variable to send motion alert message
bool clearMotionAlert = true; // clear last motion alert message from web page
The lastDebounceTime and the debounceDelay variables are used to debounce the button. This prevents false positive button presses.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
Create an AsyncWebServer object on port 80.
AsyncWebServer server(80);
To automatically display the information on the web server when new readings are available, we’ll use Server-Sent Events (SSE).
The following line creates a new event source on /events. Server-Sent Events allow a web page (client) to get updates from a server.
AsyncEventSource events("/events");
The PARAM_INPUT_1 variable will be used to check whether a certain URL request contains the parameter “state“.
const char* PARAM_INPUT_1 = "state";
Interrupt Callback Function
The detectsMovement() callback function will be called when the PIR motion sensor senses motion (an interrupt is triggered). The function changes the state of the motionDetected variable to true so that we know that motion was detected and set the clearMotionAlert variable to false because we want the “Motion Detected” message to be displayed on the web server.
void IRAM_ATTR detectsMovement() {
//Serial.println("MOTION DETECTED!!!");
motionDetected = true;
clearMotionAlert = false;
}
Building the Web Page
The index_html variable contains all the HTML, CSS and JavaScript to build the web page. We won’t go into details on how the HTML and CSS works. We’ll just take a look at how to handle the events sent by the server.
Handle Events
Create a new EventSource object and specify the URL of the page sending the updates. In our case, it’s /events.
if (!!window.EventSource) {
var source = new EventSource('/events');
Once you’ve instantiated an event source, you can start listening for messages from the server with addEventListener().
These are the default event listeners, as shown here in the AsyncWebServer documentation.
source.addEventListener('open', function(e) {
console.log("Events Connected");
}, false);
source.addEventListener('error', function(e) {
if (e.target.readyState != EventSource.OPEN) {
console.log("Events Disconnected");
}
}, false);
source.addEventListener('message', function(e) {
console.log("message", e.data);
}, false);
Then, add the other event listeners.
When you change the status LED state, the ESP32 sends an event (led_state) with that information so that the dashboard updates automatically.
source.addEventListener('led_state', function(e) {
console.log("led_state", e.data);
var inputChecked;
if( e.data == 1){ inputChecked = true; }
else { inputChecked = false; }
document.getElementById("led").checked = inputChecked;
}, false);
When the browser receives this event, it changes the state of the toggle switch element.
The motion event is sent when motion is detected. When this happens, it changes the content of the message and changes its color.
source.addEventListener('motion', function(e) {
console.log("motion", e.data);
document.getElementById("motion").innerHTML = e.data;
document.getElementById("motion").style.color = "#b30000";
}, false);
The temperature, humidity and light events are sent to the browser when new readings are available.
source.addEventListener('temperature', function(e) {
console.log("temperature", e.data);
document.getElementById("temp").innerHTML = e.data;
}, false);
source.addEventListener('humidity', function(e) {
console.log("humidity", e.data);
document.getElementById("humi").innerHTML = e.data;
}, false);
source.addEventListener('light', function(e) {
console.log("light", e.data);
document.getElementById("light").innerHTML = e.data;
}, false);
When that happens, we put the received data into the elements with the corresponding id.
outputState() function
The outputState() function is used to check the current output state of a GPIO. It returns “checked” if the GPIO is on or an empty string if it isn’t. The returned string will be used to build the web page with the current outputs states. This way, every time you access the web server you see the current states.
String outputState(int gpio){
if(digitalRead(gpio)){
return "checked";
}
else {
return "";
}
}
processor()
The processor() function replaces the placeholders on the HTML text with whatever string we want. We use the processor() function so that when you access the web server page for the first time in a new browser tab, it shows the current GPIO states, and motion sensor state.
The BUTTONPLACEHODER is replaced with the HTML text to build the button with the right states.
if(var == "BUTTONPLACEHOLDER"){
String buttons;
String outputStateValue = outputState(32);
buttons+="<div class=\"card card-switch\"><h4><i class=\"fas fa-lightbulb\"></i> OUTPUT</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"controlOutput(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label></div>";
outputStateValue = outputState(19);
buttons+="<div class=\"card card-switch\"><h4><i class=\"fas fa-lightbulb\"></i> STATUS LED</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleLed(this)\" id=\"led\" " + outputStateValue + "><span class=\"slider\"></span></label></div>";
return buttons;
}
The MOTIONMESSAGE placeholder is replaced with the MOTION DETECTED message or No motion message, depending on the current motion state.
else if(var == "MOTIONMESSAGE"){
if(!clearMotionAlert) {
return String("<span style=\"color:#b30000;\">MOTION DETECTED!</span>");
}
else {
return String("No motion");
}
}
return String();
Logout Page
The logout_html variable contains the HTML text to build the logout page. You are redirected to the logout page when you click on the web page logout button.
const char logout_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>Logged out or <a href="/">return to homepage</a>.</p>
<p><strong>Note:</strong> close all web browser tabs to complete the logout process.</p>
</body>
</html>
)rawliteral";
In the logout page, there’s a link that allows you to go back to the login page (root / URL).
<p>Logged out or <a href="/">return to homepage</a>.</p>
setup()
In the setup(), initialize the serial monitor.
Serial.begin(115200);
Initialize the BME280 sensor.
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
Set the button as an input, the status led and the additional output as outputs and the PIR motion sensor as an interrupt.
// initialize the pushbutton pin as an input
pinMode(buttonPin, INPUT);
// initialize the LED pin as an output
pinMode(ledPin, OUTPUT);
// initialize the LED pin as an output
pinMode(output, OUTPUT);
// PIR Motion Sensor mode INPUT_PULLUP
pinMode(motionSensor, INPUT_PULLUP);
// Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);
Connect to wi-fi and print the ESP32 IP address.
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
Handle Requests
We need to handle what happens when the ESP32 receives a request on a certain URL.
Handle Requests with Authentication
Every time you make a request to the ESP32 to access the web server, it will check whether you’ve already entered the correct username and password to authenticate.
Basically, to add authentication to your web server, you just need to add the following lines after each request:
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
These lines continuously pop up the authentication window until you insert the right credentials.
You need to do this for all requests. This way, you ensure that you’ll only get responses if you are logged in.
For example, when you try to access the root URL (ESP IP address), you add the previous two lines before sending the page. If you enter the wrong credentials, the browser will keep asking for them.
Recommended reading: ESP32/ESP8266 Web Server HTTP Authentication (Username and Password Protected)
If you access the root / URL and insert the right credentials, send the main web page (saved on the index_html) variable.
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
request->send_P(200, "text/html", index_html, processor);
});
Handle Logout
When you click the logout button, the ESP receives a request on the /logout URL. When that happens send the response code 401.
server.on("/logout", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(401);
});
The response code 401 is an unauthorized error HTTP response status code indicating that the request sent by the client could not be authenticated. So, it will have the same effect as a logout – it will ask for the username and password and won’t let you access the web server again until you login.
When you click the web server logout button, after one second, the ESP receives another request on the /logged-out URL. When that happens, send the HTML text to build the logout page (logout_html variable).
server.on("/logged-out", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", logout_html, processor);
});
Handle Output
When you click the button to control the output, the ESP receives a request like this /output?state=<inputMessage>. The inputMessage can be either 0 or 1 (off or on).
The following lines checker whether the request on the /output URL contains the parameter state. If it does, save the value of the state into the inputMessage variable. Then, control the output GPIO with the value of that message digitalWrite(output, inputMessage.toInt());
// Send a GET request to control output socket <ESP_IP>/output?state=<inputMessage>
server.on("/output", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
String inputMessage;
// GET gpio and state value
if (request->hasParam(PARAM_INPUT_1)) {
inputMessage = request->getParam(PARAM_INPUT_1)->value();
digitalWrite(output, inputMessage.toInt());
request->send(200, "text/plain", "OK");
}
request->send(200, "text/plain", "Failed");
});
Handle Status LED
When you control the status LED, invert the button state.
// Send a GET request to control on board status LED <ESP_IP>/toggle
server.on("/toggle", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
ledState = !ledState;
digitalWrite(ledPin, ledState);
request->send(200, "text/plain", "OK");
});
Handle Motion
When you click the motion sensor card after motion being detected, you make a request on the /clear-motion URL. When that happens, set the clearMotion variable to true.
server.on("/clear-motion", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
clearMotionAlert = true;
request->send(200, "text/plain", "OK");
});
Server Event Source
Set up the event source on the server.
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
// send event with message "hello!", id current millis and set reconnect delay to 1 second
client->send("hello!",NULL,millis(),1000);
});
server.addHandler(&events);
Finally, start the web server.
server.begin();
loop()
In the loop(), check the pushbutton state. If the button state has changed its state, change the output LED state accordingly, and send an event to the browser to change the output state on the web page.
int reading = digitalRead(buttonPin);
// If the switch changed
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
ledState = !ledState;
digitalWrite(ledPin, ledState);
events.send(String(digitalRead(ledPin)).c_str(),"led_state",millis());
}
}
}
Send sensor readings to the browser using server-sent events, every 10 seconds. You can change that period of time in the EVENT_INTERVAL_MS variable.
if ((millis() - lastEventTime) > EVENT_INTERVAL_MS) {
events.send("ping",NULL,millis());
events.send(String(bme.readTemperature()).c_str(),"temperature",millis());
events.send(String(bme.readHumidity()).c_str(),"humidity",millis());
events.send(String(analogRead(ldr)).c_str(),"light",millis());
lastEventTime = millis();
}
When motion is detected and if we haven’t cleared the notification, send the MOTION DETECTED message in the event.
if(motionDetected & !clearMotionAlert){
events.send(String("MOTION DETECTED!").c_str(),"motion",millis());
motionDetected = false;
}
Upload the Code
To upload code, go to Tools> Board and select DOIT ESP32 DEVKIT V1. Go to Tools > Port and select the COM port the ESP32 is connected to. Then, click the upload button:
Testing the Multisensor Shield
Open the Serial Monitor at a baud rate of 112500. Press the ESP32 RST button to print the ESP IP address.
Open your browser and type the ESP32 IP address. The following page should load. Insert the username and password to access the web server. By default the username is admin and the password is admin. You can change that on the code.
After inserting the right credentials, you have access to the dashboard functionalities. There are two toggle switches: one to control the status LED and another to control the additional output.
You can control the status LED using the toggle switch and also the shield physical button. The state is automatically updated on the web page. There’s another toggle button to control an additional output like a relay module.
Recommended reading: ESP32 Relay Module – Control AC Appliances (Web Server)
The web server shows the latest sensor readings. The readings are updated every 10 seconds automatically using server-sent events. This means that when the ESP32 grabs new readings, it sends an event to the client (your browser). When this event happens, it updates the fields with new readings.
Finally, there’s a card indicating if motion was detected or not. When motion is detected, it shows the “Motion Detected” message. This message is also updated automatically using server-sent events.
Once, you’ve seen this notification, you can click the motion card. It will clear the warning message and show “No motion” instead”.
Wrapping Up
We hope you’ve found this project useful and you’re able to build it yourself. You can program the IoT Shield with other code suitable for your needs. For example, you can control the output based on the current temperature value or add a threshold field. You can also edit the gerber files and add other features to the ESP32 IoT Shield.
We have other similar projects that include building and designing PCBs that you may like:
- Build an All-in-One ESP32 Weather Station Shield
- Build a Multisensor Shield for ESP8266
- EXTREME POWER SAVING with Microcontroller External Wake Up: Latching Power PCB
Learn more about the ESP32 with our resources:
Thanks
Thank you Rui and Sara Santos ,
Brilliant example – I am struggling ( and have been since Christmas ) finding an example of a variable ( say a Slider ) sending information from the Front end to the Back end via ESPASyncWebServer.
I think you are the most likely to know the solution – Please help me and everybody else who will hunting for this solution.
cheers
Greg
Hi.
You can take a look at this example: https://randomnerdtutorials.com/esp32-web-server-slider-pwm/
Or this one for multiple sliders: https://randomnerdtutorials.com/esp32-web-server-websocket-sliders/
I hope this helps.
Regards,
Sara
Thanks Sara – This is wonderful – I find your code really excellent and punchy ( direct ) – It is easy to follow and learn from – thank you so much.
That’s great.
Thank you.
EXCELLENT PROJECT CONGRATULATIONS
I WILL USE PART OF IT IN MY NEXT ONE
KEEP ON THE GOOD WORK
Thanks 😀
Hi, great project ! Is there a direct link to order the PCBs from PCBWAY ? Please keep up your excellent work !
Hi.
Just download the gerber files here: https://github.com/RuiSantosdotme/ESP32-IoT-Shield-PCB/raw/master/Gerber_PCB_ESP32_IoT_Shield_2020-06-10_10-55-31.zip
Then, go to https://randomnerdtutorials.com/pcbway and follow the instructions on the tutorial. You just need to upload that gerber file and order the PCBs.
It’s easy.
Regards,
Sara
Thanks Sara, just ordered the PCBs. Have a great one !
Thanks 🙂
How is it powered? Thank you and awesome project.
Hi
It is powered using the USB socket of the ESP32.
Regards,
Sara
All I’ve got to say is, WOW!!!
You’ve taken this to the next level, documenting the process for designing a shield, getting it manufactured, and at an exceptional price point.
Unbelievably through and integrated treatment of this project!
Thank you 😀
Nice little project. I’d like to build it myself. Can you or someone of your community deliver one of his pcb for small money?
I’d prefer normal throuhole resistors. The others I don’t have on stock. But that is no mayor problem. I’ll try to solder normal resistors on the pcb.
Many thanks for your good work and your help in understanding electronics.
Tom
Hello Tom, unfortunately we don’t sell any hardware at the moment, but you can quickly order the bare PCB using this link:
https://www.pcbway.com/QuickOrderOnline.aspx?from=randomnerdtutorials&fileurl=https://pcbwayfile.s3-us-west-2.amazonaws.com/gerber/20/06/17/0512017290142.zip&projectid=6220&filename=Gerber_PCB_ESP32_IoT_Shield_2020-06-10_10-55-31.zip
Then, you just need to order the components to assemble it.
Thanks again!
Rui
Hi,
I don’t seem to be able to view the pcb on the EasyEDA online editor – I have of course downloaded your files and unzipped them and when I open the pcb_pcb json file (82k) in EasyEDA I just see a blank workspace … any thoughts?
Ah It’s ok – I thought I was seeing the whole workspace but turns out I wasn’t.
Weird that it displays the board off screen but hey, I got there in the end. Now to edit and put in more sensors and IO’s.
Nice
Nice project…..how can I make it work on my ESP8266
Hi.
We have something similar (but different) for the ESP8266: https://randomnerdtutorials.com/esp8266-multisensor-shield/
Regards,
Sara
Thanks for the reply…your projects help me to continue my hobby during this lockdown
Thanks great!
Regards,
Sara
Hi, I am keen to build this project but can only seem to find 30 or 38 pin ESP32. Anybody know where I can get a 36 pin one from? even the link in the article goes to a 30 pin one?
Hi Mike.
If you get your board from banggood, you get the board with 36 GPIOs.
https://makeradvisor.com/tools/esp32-dev-board-wi-fi-bluetooth/
Regards,
Sara
Thank you for making such great projects. All of your tutorials and projects that you give to us for free is very generous and helpful to us that aren’t good at programming and have very limited funds. I hope you make a lot of money from your advertisers. Again thanks and please keep it you.
Thank you so much for your kind words 😀
Regards,
Sara
Hello,
I have a little question.
On schematic/PCB why there is a track on the terminal 2 of the P1 Header-Female which is going nowhere ?
Thanks to you and have a nice day
Hi.
It is going to GPIO27.
Regards,
Sara
Thanks for the reponse
But : On one side the track goes to GPIO 27 but on the other side where does the track go ?
Adrien 🙂
Hi Adrien.
You are right.
It’s a small error on the PCB design. There’s that extra line that goes nowhere. Nonetheless, the PCB still works fine.
Thanks for noticing.
Regards,
Sara
Hi. Hope you are fine, already have holidays? Hope you have, its not working all the time.
I`m here again with another dificulty again. Programing the same board you have i get a error, dont know what can be, this is the error i get:
Foram encontradas múltiplas bibliotecas para «Adafruit_Sensor.h»
Utilizado: C:\Users\paulo\Documents\Arduino\libraries\Adafruit_Sensor-master
Não utilizado: C:\Users\paulo\Documents\Arduino\libraries\Adafruit_Unified_Sensor
Não utilizado: C:\Users\paulo\Documents\Arduino\libraries\AllThingsTalk_LTE-M_SDK
Foram encontradas múltiplas bibliotecas para «Adafruit_BME280.h»
In file included from C:\Users\paulo\Documents\Arduino\ESP32DASHBOARD_RANDOMNERDS\ESP32DASHBOARD_RANDOMNERDS.ino:5:0:
Utilizado: C:\Users\paulo\Documents\Arduino\libraries\Adafruit_BME280_Library
C:\Users\paulo\Documents\Arduino\libraries\ESPAsyncWebServer-master\src/AsyncEventSource.h:25:22: fatal error: AsyncTCP.h: No such file or directory
Não utilizado: C:\Users\paulo\Documents\Arduino\libraries\AllThingsTalk_LTE-M_SDK
compilation terminated.
exit status 1
Erro ao compilar para a placa DOIT ESP32 DEVKIT V1.
I tried esp dev kit, esp wrover and i get the error, dont upload, hope you can help me, thanks a lot.
Sorry again, it now upload after new try, but i get nothing on monitor its blank, any idea? Thanks again.
Hi.
After uploading the code, open the serial monitor, and make sure you have the right baud rate selected “115200”.
Then, press the ESP32 on-board RESET button, and it should print something on the Serial Monitor.
Regards,
Sara
Ok Sara it worked and then i get the message couldnt fund a valid BME280, i have an BMP280 not BME280, but i am waiting for 3 new onws at some time, hope soon to test forword to see if there is any more problems and make it work.
One more time but not enough thank you very much.
Hi Sara mean while i wait for the BME280 I changed the scketch to a BMP280 without pressure everything works fine only light that dont change its always at 4095 with no changes, do you have any idea how to fix, thanks, best regards.
Sorry again i remove humidity because BMP280 doesnt have but is missing pressure board, sshould be there i think but it isnt, so i have no readings on light, but board is there with the value of 4095 all the time, and no pressure board, hope you can help, thanks again.
hi.
I thought this dashboard had pressure readings but no, isnt it possible to add this feature? I say this because the BME280 has this capability and the dashboard gets more complete than it is (great as all the others you made). Hope you think on this, the shield is working fine with the exception i cant have no readings on GPIO33 for the light sensor, may be its my problem because i have no readings in the weather shield also, i have checked everything on both and cant imegine why i have no readings,
Thanks one more time for the help and borough you with so many quetions.
Hi Sara i dont have readings on light sensor, cheked everything because i ha dad a error on weather shield that reads ok now but here i have no reads and everything its ok i recheked everything, if you have any idea maybe its missing something i cant see.
Abought the pressure do you think its possible add the feature even we have to add wires.
Thanks hope you can help me.
Regards.
Hi Sara.
Now i receive the BME280 the shield works complete only the light sensor reads but oposit way, if i increase light i get the lower value, if i have low light i have higher values. I already turn the pins of the light sensor like if they have polarity and its the same. Do you wonder what can be?
Thanks a lot, and if possible help me to read the pressure on this shield.
Thanks again.
Hi Paulo.
That’s how the LDR works.
More light –> lower values.
Less light –> higher values
Thanks for following our projects.
Regards,
Sara
Hi Sara, thanks a lot so everything is working ok reading well.
Sorry to ask again, but is possível the scketch read pressure also?
Thanks a lot, great job you do, congrats
Hi.
Yes, you can add the lines to add the pressure.
To learn how to get pressure, you can read our BME280 guide: https://randomnerdtutorials.com/esp32-bme280-arduino-ide-pressure-temperature-humidity/
Regards,
Sara
Very good. I’m studying about Esp32, and this project help me too much.
That’s great!
Thanks 🙂
Hi,
I purchased ebay) a couple of the 36 pin boards but i can’t flash them. I tried the en button. but no luck. I tried it on two 36 pin boards and got the same result.
This is the error I get-
Serial port COM15
Connecting…….._____….._____….._____….._____….._____….._____….._____
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
*** [upload] Error 2
=================== [FAILED] Took 45.31 seconds ===================
I have no problem flashing my other es32 boards. The 36 pin boards are identified on the silkscreen as “esp32 devkit v1”. Thank you for your excellent tutorials, I hope
you can help me with this problem
Larry
Hi Larry.
Take a look at this: https://randomnerdtutorials.com/solved-failed-to-connect-to-esp32-timed-out-waiting-for-packet-header/
Regards,
Sara
Thank you Sara, your suggestion worked without problems.
Best Regards,
Larry
Hi,
I hope someone can help with the following problem
I am building the esp32 iot shield. I followed the instructions
And acquired the parts, including the PCB. The assembly and
Soldering were completed okay. I then loaded (platformio) the code which
Also loaded okay. When I attempted to test it, the following
Error showed up:
“ [fum•ÍÁÍ2-hal-cpu.c:159] setCpuFrequencyMhz(): Can not switch to 240 MHz! Chip CPU frequency rated for 160MHz.
ÿ[E][esp32-hal-i2c.c:1426] i2cCheckLineState(): Bus Invalid State, TwoWire() Can’t init sda=1, scl=0 “
Could not find a valid BME280 sensor, check wiring!
I searched for solutions and found many of them, but none worked.
Thank you>
Regards
Larry
Hi Larry.
That’s a very weird issue.
What is the board that you are using?
Did you try compiling the code using Arduino IDE instead?
Additionally, the error with the BME280, usually means that something is wrong with the wiring or pin definition.
Regards,
Sara
Hi Sara,
Thank you for responding.
I was able to load the sketch using the Arduino IDE, After loading it, I tested it and got
The same message as I did on Platformio.
I was able to eliminate the cpu speed message when using Platformio by adding this line to the
Ini file: “board_build.f_cpu = 160000000L”
I am using is the 36 pin version, “ESP32 DEVKIT V1” from DOIT, purchased on EBAY.
I have two DOIT boards and neither works at 240mhz. I have several other boards which
Are not from DOIT, and all test okay at 240mhz. The reduced speed of the DOIT boards
Has no apparent effect on the functionality of my sketches.
The problem I have with the BME280 sensor not being found appears to be
A defective BME280 sensor..
I have ordered a few more, they should arrive early
Next week. I will test them and let you know the result.
Thank you again for your prompt response, I am really enjoying the RNT tutorials and forums (no Trolls).
Larry
Hi Sara,
I received the new BME280 sensors today. Everything worked perfectly after plugging
in the new one.
Thanks
Larry
That’s great 😀
hello sir,
i was trying to do that project with PHP and MYSQL
can u make toturial about this ?
thank you
Hi.
We have these tutorials that cover those topics:
https://randomnerdtutorials.com/cloud-weather-station-esp32-esp8266/
https://randomnerdtutorials.com/raspberry-pi-apache-mysql-php-lamp-server/
https://randomnerdtutorials.com/visualize-esp32-esp8266-sensor-readings-from-anywhere/
https://randomnerdtutorials.com/esp32-esp8266-mysql-database-php/
Regards,
Sara
hello i meant combined ones … one that combines the switches and the weather station ,,, like complete one in 1 arduino and sends to mysql
Hi.
At the moment, we only have those tutorials.
Regards,
Sara
appreciate your response
A great tutorial! So much useful hints! I think, creating this tutorial was a lot of work for us and I want to say ‘Thank You’ for this project.
Serial.printf(“Client reconnected! Last message ID that it got is:””” %u\n””””, client->lastId());
Hi, What does that part “””xxxx””” of this line mean?
Thanks .
Ross
hi, i´m a huge fan of your site. learned a lot about the esp32 here !! thanks for all of you affort. normally i try to get further on my own, but i´m totally stucked on the usage of smd leds and the related resistors. in the past i used the common led which where delivered beside the learn package, the colored ones with the both thin legs. now i´m trying to do my own fist pcb, but i´m not sure which led and resistor to choose. therefor i was reading this article but there is only a link to a banggood smd package. could you please point me to a equal led smd and equal resistor on https://lcsc.com?
that would be great !!!!
Thx in advance & all the best, Thorsten
Hi.
We’re using SMD 330Ohm resistor 1206 package. Usually, when you get a package (like the one in Maker Advisor), it comes with this value. You also get other values and multiple resistors of the same value.
On the LCSC website, go to All Products > Resistors > Chip Resistor Surface Mount and select the package (1206) and the resistance (330), the tolerance can be a value between 1 and 5%. Then, click Apply, and choose any of the shown results.
I hope this helps.
Regards,
Sara
Hi Sara, thanks for your help regarding the resistors.
Can you help me out also regarding the LED you are using in this case?
maybe on the lcsc site, too?
Would be awesome !!
Best, Thorsten
Hi.
For the LED, Go to All Products > Optocouplers & LEDs & Infrared > Light Emitting Diodes
And select the options:
– Package: 1206
– Color: Blue
Then, click apply.
Any of the results will do.
Regards,
Sara
Hi,
Really a fantastic project, because as a newbe i learn a lot.
I made the project and loaded the program with arduino ide.
The interface worked wel but the esp is resetting en restarting every 10 sec.
Is there a solution fore this ?
Hi.
Please double-check all your connections.
Regards,
Sara
Hello Sara,
Thanks for the reply.
Alle connection are checked and conform your example.
Reading again your tutorial i saw your using another esp.
I’m using the esp82666 12-e NodeMCU Kit….
Is it possible to get your project working on this esp ?
Best
Wouter
Hi.
This project doesn’t work with the ESP8266 out of the box.
You need to make some modifications to make it compatible like the pin assignment and the WiFi library.
Regards,
Sara
Hi Sara,
Making several modifications the project works fine on my esp8266.
Only the BME 280 doesn’t work.
Testing several BME 280 in several sketches i didn’t manage to get
the device working but i’ll get on trying and reading to get it done.
For now i want to thank you for your help, i really appriciate your
professional effort to support a newbee like me.
Regards,
Wouter
Hi.
Please double-check that you have a BME280 sensor.
Some people get a BMP280 instead of a BME280.
Try to run an I2C scanner sketch to see if the ESP32 can communicate with the sensor: https://raw.githubusercontent.com/RuiSantosdotme/Random-Nerd-Tutorials/master/Projects/LCD_I2C/I2C_Scanner.ino
I hope this helps.
Regards,
Sara
Just replace
#include “Wifi.h” with
#include “ESP8266Wifi.h”
and works on ESP8266.
HI, I have done this project and it is working fine. However, what I miss when using the ESP32 is an external boot button. Putting it all into a box it is cumbersome to operate the boot button. Any ideas?
Hi,
Really a fantastic project, because as a newbe i learn a lot.
String processor(const String& var){
//Serial.println(var);
if(var == “BUTTONPLACEHOLDER”){
String buttons;
String outputStateValue = outputState(32);
buttons+=”
OUTPUT
“;
outputStateValue = outputState(19);
buttons+=”
STATUS LED
“;
return buttons;
this code, have a part of ” const char index_html[] PROGMEM = R”rawliteral(…. ” . Can you help me move it in “const char index_html[] PROGMEM = R”rawliteral(…. ” ? Thank you very much!!
Hallo,
I have a question: On the PCB there is no connection to ground and to 3.3V for the BME280.
On the Fritzing picture there are this connections. How does it work?
Thanks
Ulrich
Hi.
There are connections to 3.3V and GND.
3.3 –> square on the PCB
GND –> dashed circles
Regards,
Sara
hi, i´m a huge fan of your site. learned a lot about the esp32 here !! thanks for all of you affort. normally i try to get further on my own, but i´m totally stucked on the usage of smd leds and the related resistors. in the past i used the common led which where delivered beside the learn package, the colored ones with the both thin legs. now i´m trying to do my own fist pcb, but i´m not sure which led and resistor to choose. therefor i was reading this article but there is only a link to a banggood smd package. could you please point me to a equal led smd and equal resistor on https://www.chimicron.com?
that would be great !!!!
Thx in advance & all the best, Thorsten
Hi,
Which software do you use the schematics diagram?
Thanks
EasyEDA
Can I turn on relay after I detected motion