{"id":100518,"date":"2020-12-10T15:01:27","date_gmt":"2020-12-10T15:01:27","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=100518"},"modified":"2021-04-27T10:05:52","modified_gmt":"2021-04-27T10:05:52","slug":"esp32-weather-station-pcb","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-weather-station-pcb\/","title":{"rendered":"ESP32 Weather Station Interface PCB Shield (Temperature, Humidity, Pressure, Date and Time)"},"content":{"rendered":"\n<p>In this project, you&#8217;ll learn how to build a Weather Station Interface PCB Shield for the ESP32 development board. The PCB features a BME280 temperature, humidity and pressure sensor, a light dependent resistor, a pushbutton, an OLED display and multiple WS2812B addressable RGB LEDs. The OLED displays the sensor readings and the LEDs produce different lighting effects to what is shown in the OLED. It also displays date and time.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-PCB-Shield-Temperature-Humidity-Date-Time.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Weather Station Interface PCB Shield Temperature Humidity Pressure Date Time\" class=\"wp-image-100764\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-PCB-Shield-Temperature-Humidity-Date-Time.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-PCB-Shield-Temperature-Humidity-Date-Time.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-PCB-Shield-Temperature-Humidity-Date-Time.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-PCB-Shield-Temperature-Humidity-Date-Time.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Watch the Video Tutorial<\/h2>\n\n\n\n<p>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.<\/p>\n\n\n<p style=\"text-align:center\"><iframe width=\"720\" height=\"405\" src=\"https:\/\/www.youtube.com\/embed\/_680VPayXWI?rel=0\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Resources<\/h3>\n\n\n\n<p>You can find all the resources needed to build this project in the links below (or you can visit the&nbsp;<a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub project<\/a> page):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/raw.githubusercontent.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/main\/ESP32_Weather_Station_PCB\/ESP32_Weather_Station_PCB.ino\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32 Code (Arduino IDE)<\/a><\/li><li><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/Gerber_PCB_ESP32%20Weather%20Station%20Interface_2020-12-06_17-30-24.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Gerber files<\/a><\/li><li><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/Project_ESP32%20Weather%20Station%20Interface_2020-12-06_17-29-59.zip\" target=\"_blank\" rel=\"noreferrer noopener\">EasyEDA project to edit the PCB<\/a><\/li><li><strong><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/archive\/main.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Click here to download all the files<\/a><\/strong><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-OLED-Screen.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Weather Station Interface Project OVerview\" class=\"wp-image-100737\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-OLED-Screen.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-OLED-Screen.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Weather Station PCB Hardware Features<\/h3>\n\n\n\n<p>The shield is designed with some headers pins to stack the ESP32 board. For this reason, if you want to build and use our PCB, you need to get the same ESP32 development board. We\u2019re using the&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\">ESP32 DEVKIT DOIT V1<\/a>&nbsp;board (the model with&nbsp;<strong>36 GPIOs<\/strong>).<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Stacked-board-PCB-Weather-Station-Interface-Shield-.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Stacked board PCB Weather Station Interface Shield\" class=\"wp-image-100738\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Stacked-board-PCB-Weather-Station-Interface-Shield-.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Stacked-board-PCB-Weather-Station-Interface-Shield-.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>If you want to follow this project and you have a different ESP32 model, you can assemble the circuit on a breadboard or you can modify the PCB layout and wiring to match the pinout of your ESP32 board. Throughout this project, we provide all the necessary files, if you need to modify the PCB.<\/p>\n\n\n\n<p>The shield consists of:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>BME280 temperature, humidity and pressure sensor;<\/li><li>LDR (light dependent resistor &#8211; luminosity sensor);<\/li><li>0.96 inch I2C OLED Display;<\/li><li>Pushbutton;<\/li><li>12 WS2812B addressable RGB LEDs;<\/li><\/ul>\n\n\n\n<p>If you&#8217;re going to replicate this project on a breadboard, instead of individual WS2812B addressable RGB LEDs, you can use an <a href=\"https:\/\/makeradvisor.com\/tools\/ws2812b-addressable-rgb-led-strip\/\" target=\"_blank\" rel=\"noreferrer noopener\">addressable RGB LED strip<\/a> or an addressable RGB LED ring with the same number of LEDs (12).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Weather Station PCB Pin Assignment<\/h3>\n\n\n\n<p>The following table shows the pin assignment for each component on the shield:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Component<\/strong><\/td><td><strong>ESP32 Pin Assignment<\/strong><\/td><\/tr><tr><td>BME280<\/td><td>GPIO 21 (SDA), GPIO 22 (SCL)<\/td><\/tr><tr><td>OLED Display<\/td><td>GPIO 21 (SDA), GPIO 22 (SCL)<\/td><\/tr><tr><td>Light Dependent Resistor (LDR)<\/td><td>GPIO 33<\/td><\/tr><tr><td>Pushbutton<\/td><td>GPIO 18<\/td><\/tr><tr><td>Addressable RGB LEDs<\/td><td>GPIO 27<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Weather Station PCB Software Features<\/h2>\n\n\n\n<p>There are endless ways to program the same circuit to get different outcomes with different functionalities and features. In this particular project we&#8217;ll program the PCB as follows:<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"801\" height=\"476\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-OLED-Screens.png?resize=801%2C476&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-100719\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-OLED-Screens.png?w=801&amp;quality=100&amp;strip=all&amp;ssl=1 801w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-OLED-Screens.png?resize=300%2C178&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-OLED-Screens.png?resize=768%2C456&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 801px) 100vw, 801px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>The OLED displays five different screens: <ol><li>Current date and time;<\/li><li>Temperature<\/li><li>Humidity<\/li><li>Pressure<\/li><li>Luminosity<\/li><\/ol><\/li><li>Each screen is shown for 15 seconds before going to the next one.<\/li><li>Alternatively, you can press the pushbutton to change screens.<\/li><li>In each screen the WS2812B addressable RGB LEDs show a different pattern:<ul><li>On the date and time screen, the RGB LEDs display a rainbow effect;<\/li><li>On the other screens, the RGB LEDs work like a gauge. For example, 100% humidity lights up all LEDs, 50% humidify lights up half of the number of LEDs.<\/li><li>The color of the LEDs is different for each screen: green for the temperature, blue for the humidity, purple for pressure and yellow for luminosity.<\/li><\/ul><\/li><\/ul>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"423\" height=\"423\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-Design.png?resize=423%2C423&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-100720\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-Design.png?w=423&amp;quality=100&amp;strip=all&amp;ssl=1 423w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-Design.png?resize=300%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/Weather-Station-PCB-ESP32-Design.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w\" sizes=\"(max-width: 423px) 100vw, 423px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"designPCB\">Testing the Circuit on a Breadboard<\/h2>\n\n\n\n<p>Before designing and building the PCB, it\u2019s important to test the circuit on a breadboard. If you don\u2019t want to make a PCB, you can still follow this project by assembling the circuit on a breadboard.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Breadboard-Weather-Station-Interface-Shield-Components-Parts-Required.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Breadboard Weather Station Interface Shield Components Parts Required\" class=\"wp-image-100739\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Breadboard-Weather-Station-Interface-Shield-Components-Parts-Required.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Breadboard-Weather-Station-Interface-Shield-Components-Parts-Required.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Parts Required<\/h3>\n\n\n\n<p>To assemble the circuit on a breadboard you need the following parts (the parts for the actual PCB are shown in a later section):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">DOIT ESP32 DEVKIT V1 Board<\/a>\u00a0\u2013 read\u00a0<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP32 Development Boards<\/a><\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">BME280<\/a>\u00a0(4 pins)<\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/oled-display-128x64-0-96-inch\/\" target=\"_blank\" rel=\"noreferrer noopener\">I2C OLED Display<\/a> (4 pins)<\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/photoresistor-light-dependent-resistor-ldr\/\" target=\"_blank\">Light dependent resistor<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/pushbuttons-kit\/\" target=\"_blank\">Pushbutton<\/a><\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noreferrer noopener\">2x 10k Ohm resistor<\/a><\/li><li><a style=\"font-size: inherit; background-color: initial;\" href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li><\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<p>After gathering all the parts, assemble the circuit by following the next schematic diagram:<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-Schematic-Diagram-Fritzing.jpg?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1176\" height=\"1418\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-Schematic-Diagram-Fritzing.jpg?resize=1176%2C1418&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Weather Station Interface Schematic Diagram Fritzing\" class=\"wp-image-100742\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-Schematic-Diagram-Fritzing.jpg?w=1176&amp;quality=100&amp;strip=all&amp;ssl=1 1176w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-Schematic-Diagram-Fritzing.jpg?resize=249%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 249w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-Schematic-Diagram-Fritzing.jpg?resize=849%2C1024&amp;quality=100&amp;strip=all&amp;ssl=1 849w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-Schematic-Diagram-Fritzing.jpg?resize=768%2C926&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1176px) 100vw, 1176px\" \/><\/a><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Designing the PCB<\/h2>\n\n\n\n<p>To design the circuit and PCB, we used&nbsp;<a rel=\"noreferrer noopener nofollow\" href=\"https:\/\/easyeda.com\/\" target=\"_blank\">EasyEDA<\/a>&nbsp;which is a browser based software to design PCBs. If you want to customize your PCB, you just need to upload the following files:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/Project_ESP32%20Weather%20Station%20Interface_2020-12-06_17-29-59.zip\" target=\"_blank\" rel=\"noreferrer noopener\">EasyEDA project files to edit the PCB<\/a><\/li><\/ul>\n\n\n\n<p>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.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1122\" height=\"930\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Circuit-Diagram-Circuit.png?resize=1122%2C930&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Weather Station Interface PCB Schematic Diagram Wiring Circuit\" class=\"wp-image-100740\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Circuit-Diagram-Circuit.png?w=1122&amp;quality=100&amp;strip=all&amp;ssl=1 1122w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Circuit-Diagram-Circuit.png?resize=300%2C249&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Circuit-Diagram-Circuit.png?resize=1024%2C849&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Circuit-Diagram-Circuit.png?resize=768%2C637&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1122px) 100vw, 1122px\" \/><\/figure><\/div>\n\n\n\n<p>Having the parts assigned, place each component. When you\u2019re happy with the layout, make all the connections and route your PCB.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"739\" height=\"741\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Gerbers.png?resize=739%2C741&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 PCB Weather Station Interface PCB Layout\" class=\"wp-image-100744\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Gerbers.png?w=739&amp;quality=100&amp;strip=all&amp;ssl=1 739w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Gerbers.png?resize=300%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Gerbers.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w\" sizes=\"(max-width: 739px) 100vw, 739px\" \/><\/figure><\/div>\n\n\n\n<p>Save your project and export the Gerber files.<\/p>\n\n\n\n<p><strong>Note: <\/strong> you can grab the project files and edit them to customize the shield for your own needs.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/Gerber_PCB_ESP32%20Weather%20Station%20Interface_2020-12-06_17-30-24.zip\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Download Gerber .zip file<\/strong><\/a><\/li><li><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/Project_ESP32%20Weather%20Station%20Interface_2020-12-06_17-29-59.zip\" target=\"_blank\" rel=\"noreferrer noopener\">EasyEDA project to edit the PCB<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Ordering the PCBs at PCBWay<\/h2>\n\n\n\n<p>This project is sponsored by PCBWay. <a href=\"https:\/\/randomnerdtutorials.com\/pcbway\" target=\"_blank\" rel=\"noreferrer noopener\">PCBWay<\/a>&nbsp;is a full feature Printed Circuit Board manufacturing service. <\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/makeradvisor.com\/pcbway\" target=\"_blank\" rel=\"noopener noreferrer\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"291\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/PCBWay-banner.jpg?resize=750%2C291&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Ordering the PCBs at PCBWay\" class=\"wp-image-97545\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/PCBWay-banner.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/PCBWay-banner.jpg?resize=300%2C116&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>Turn your DIY breadboard circuits into <a href=\"https:\/\/randomnerdtutorials.com\/pcbway\" target=\"_blank\" rel=\"noreferrer noopener\">professional PCBs<\/a> &#8211; get 10 boards for approximately $5 + shipping (which will vary depending on your country).<\/p>\n\n\n\n<p>Once you have your Gerber files, you can order the PCB. Follow the next steps.<\/p>\n\n\n\n<p>1. Download the Gerber files \u2013&nbsp;<strong><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/Gerber_PCB_ESP32%20Weather%20Station%20Interface_2020-12-06_17-30-24.zip\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/Gerber_PCB_ESP32%20Weather%20Station%20Interface_2020-12-06_17-30-24.zip\">click here to download the .zip file<\/a><\/strong><\/p>\n\n\n\n<p>2. Go to <a href=\"https:\/\/randomnerdtutorials.com\/pcbway\" target=\"_blank\" rel=\"noreferrer noopener\">PCBWay website<\/a> and open the PCB Instant Quote page.&nbsp;<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"504\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/1-PCBWay-Order-PCB.png?resize=900%2C504&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"PCBWay Order PCB open instant quote page\" class=\"wp-image-97554\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/1-PCBWay-Order-PCB.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/1-PCBWay-Order-PCB.png?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/1-PCBWay-Order-PCB.png?resize=768%2C430&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n\n<p>3. PCBWay can grab all the PCB details and automatically fills them for you. Use the \u201cQuick-order PCB (Autofill parameters)\u201d.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"469\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/2-PCBWay-Order-PCB-autofill-parameters.png?resize=900%2C469&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"PCBWay Order PCB autofill parameters\" class=\"wp-image-97555\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/2-PCBWay-Order-PCB-autofill-parameters.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/2-PCBWay-Order-PCB-autofill-parameters.png?resize=300%2C156&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/2-PCBWay-Order-PCB-autofill-parameters.png?resize=768%2C400&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n\n<p>4. Press the \u201c+ Add Gerber file\u201d button to upload the provided Gerber files.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"939\" height=\"521\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/3-PCBWay-Order-PCB-gerbers-files.png?resize=939%2C521&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"PCBWay Order PCB add gerber file button\" class=\"wp-image-97556\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/3-PCBWay-Order-PCB-gerbers-files.png?w=939&amp;quality=100&amp;strip=all&amp;ssl=1 939w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/3-PCBWay-Order-PCB-gerbers-files.png?resize=300%2C166&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/3-PCBWay-Order-PCB-gerbers-files.png?resize=768%2C426&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 939px) 100vw, 939px\" \/><\/figure><\/div>\n\n\n\n<p>And that\u2019s it. You can also use the OnlineGerberViewer to check if your PCB is looking as it should.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"579\" height=\"600\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Gerber-Viewer-Online.png?resize=579%2C600&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 PCB Weather Station Interface Gerber Viewer Online\" class=\"wp-image-100745\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Gerber-Viewer-Online.png?w=579&amp;quality=100&amp;strip=all&amp;ssl=1 579w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Gerber-Viewer-Online.png?resize=290%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 290w\" sizes=\"(max-width: 579px) 100vw, 579px\" \/><\/figure><\/div>\n\n\n\n<p>If you aren\u2019t 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.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"365\" height=\"630\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/6-PCBWay-Order-PCB-china-post.png?resize=365%2C630&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"PCBWay Order PCB China post shipping method\" class=\"wp-image-97559\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/6-PCBWay-Order-PCB-china-post.png?w=365&amp;quality=100&amp;strip=all&amp;ssl=1 365w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/6-PCBWay-Order-PCB-china-post.png?resize=174%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 174w\" sizes=\"(max-width: 365px) 100vw, 365px\" \/><\/figure><\/div>\n\n\n\n<p>You can increase your PCB order quantity and change the solder mask color. I\u2019ve ordered the Blue color.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1152\" height=\"548\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB-PCBWay-Order-PCB.png?resize=1152%2C548&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 PCB Weather Station Interface Final PCB PCBWay Order PCB\" class=\"wp-image-100743\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB-PCBWay-Order-PCB.png?w=1152&amp;quality=100&amp;strip=all&amp;ssl=1 1152w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB-PCBWay-Order-PCB.png?resize=300%2C143&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB-PCBWay-Order-PCB.png?resize=1024%2C487&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB-PCBWay-Order-PCB.png?resize=768%2C365&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1152px) 100vw, 1152px\" \/><\/figure><\/div>\n\n\n\n<p>Once you\u2019re ready, you can order the PCBs by clicking &#8220;Save to Cart&#8221; and complete your order.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Unboxing<\/h2>\n\n\n\n<p>After approximately one week using the DHL shipping method, I received the PCBs at my office. <\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 PCB Weather Station Interface Shield\" class=\"wp-image-100735\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>As usual, 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.<\/p>\n\n\n\n<p>We\u2019re really satisfied with the PCBWay service. Here&#8217;s some other projects we&#8217;ve built using the PCBWay service:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-cam-shield-pcb-telegram\/\">ESP32-CAM with Telegram: Take Photos, Control Outputs, Request Sensor Readings and Motion Notifications<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-iot-shield-pcb-dashboard\/\">ESP32 IoT Shield PCB with Dashboard for Outputs and Sensors<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Soldering the Components<\/h2>\n\n\n\n<p>The next step is soldering the components to the PCB. I\u2019ve used SMD LEDs, SMD resistors and SMD capacitors. These can be a bit difficult to solder, but the PCB looks much better.<\/p>\n\n\n\n<p>If you&#8217;ve never soldered SMD before, we recommend watching a few videos to learn how it&#8217;s done. You can also get an SMD DIY soldering Kit to practice a bit.<\/p>\n\n\n\n<p>Here\u2019s a list of all the components needed to assemble the PCB:<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-Components-Parts-Required.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESPCB Weather Station Interface Shield Components Parts Required\" class=\"wp-image-100736\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-Components-Parts-Required.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-Components-Parts-Required.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">DOIT ESP32 DEVKIT V1 Board<\/a> (<strong>36 GPIOs<\/strong>)<\/li><li>12x SMD WS2812B addressable RGB LEDs<\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/smd-resistors\" target=\"_blank\">2x 10k Ohm SMD resistor<\/a>\u00a0(1206)<\/li><li>12x 10nF capacitors (0805)<\/li><li>Pushbutton (0.55 mm)<\/li><li><a href=\"https:\/\/makeradvisor.com\/female-pin-header-socket\" target=\"_blank\" rel=\"noreferrer noopener\">Female pin header socket<\/a>\u00a0(2.54 mm)<\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">BME280<\/a> (4 pins)<\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/photoresistor-light-dependent-resistor-ldr\/\" target=\"_blank\" rel=\"noreferrer noopener\">Light dependent resistor<\/a><\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/oled-display-128x64-0-96-inch\/\" target=\"_blank\" rel=\"noreferrer noopener\">I2C SSD1306 0.96inch OLED display<\/a> (4 pins)<\/li><\/ul>\n\n\n\n<p>Here\u2019s the soldering tools I\u2019ve used:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/makeradvisor.com\/ts80-soldering-iron-review\/\" target=\"_blank\" rel=\"noreferrer noopener\">TS80 mini portable soldering iron<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/www.banggood.com\/0_5mm-500g-Soldering-Wires-Welding-Iron-Rosin-Core-6040-Lead-Tin-Flux-2_0-Percent-p-1023387.html?p=MA240439985285201910\" target=\"_blank\">Solder 60\/40 0.5mm diameter<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/soldering-mats-review\/\" target=\"_blank\">Soldering mat<\/a><\/li><\/ul>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/TS80-Soldering-Iron-Review-Best-Portable-Soldering-Iron.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"TS80 Soldering Iron Review Best Portable Soldering Iron\" class=\"wp-image-97549\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/TS80-Soldering-Iron-Review-Best-Portable-Soldering-Iron.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/06\/TS80-Soldering-Iron-Review-Best-Portable-Soldering-Iron.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>Read our review about the TS80 Soldering Iron:&nbsp;<a href=\"https:\/\/makeradvisor.com\/ts80-soldering-iron-review\/\" target=\"_blank\" rel=\"noreferrer noopener\">TS80 Soldering Iron Review \u2013 Best Portable Soldering Iron<\/a>.<\/p>\n\n\n\n<p>Start by soldering the SMD components. Then, solder the header pins. And finally, solder the other components or use header pins if you don\u2019t want to connect the components permanently.<\/p>\n\n\n\n<p>Here\u2019s how the ESP32 Shield looks like after assembling all the parts.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 PCB Weather Station Interface Final PCB\" class=\"wp-image-100741\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Final-PCB.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>The ESP32 board should stack perfectly on the header pins on the other side of the PCB.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Stacked-board-PCB-Weather-Station-Interface-Shield-.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Stacked board PCB Weather Station Interface Shield\" class=\"wp-image-100738\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Stacked-board-PCB-Weather-Station-Interface-Shield-.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Stacked-board-PCB-Weather-Station-Interface-Shield-.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<hr class=\"wp-block-separator is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Programming the Weather Station Interface PCB<\/h2>\n\n\n\n<p>The code for this project displays sensors readings on different screens on the OLED display as well as date and time. The addressable RGB LEDs show different colors and animations accordingly to what is displayed on the screen.<\/p>\n\n\n\n<p>You can program the PCB in any way that is more suitable for you. <\/p>\n\n\n\n<p>We&#8217;ll program the ESP32 board using Arduino IDE. So make sure you have the ESP32 board add-on installed.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/installing-the-esp32-board-in-arduino-ide-windows-instructions\/\">Installing ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux)<\/a><\/li><\/ul>\n\n\n\n<p>If you want to program the ESP32\/ESP8266 using VS Code + PlatformIO, follow the next tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266 (Windows, Mac OS X, Linux Ubuntu)<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Installing Libraries (Arduino IDE)<\/h3>\n\n\n\n<p>For this project, you need to install all these libraries in your Arduino IDE.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/adafruit\/Adafruit_NeoPixel\" target=\"_blank\" rel=\"noreferrer noopener\">Adafruit Neopixel<\/a><\/li><li><a href=\"https:\/\/github.com\/adafruit\/Adafruit-GFX-Library\" target=\"_blank\" rel=\"noreferrer noopener\">Adafruit GFX<\/a><\/li><li><a href=\"https:\/\/github.com\/adafruit\/Adafruit_SSD1306\" target=\"_blank\" rel=\"noreferrer noopener\">Adafruit SSD1306<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/adafruit\/Adafruit_BME280_Library\" target=\"_blank\">Adafruit_BME280 library<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/adafruit\/Adafruit_Sensor\" target=\"_blank\">Adafruit_Sensor library<\/a><\/li><\/ul>\n\n\n\n<p>All these libraries can be installed using the Arduino IDE library manager. Just go to <strong>Sketch <\/strong>&gt; <strong>Include Library<\/strong> &gt; <strong>Manage Libraries<\/strong> and search for the library name.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Installing Libraries (VS Code + PlatformIO)<\/h3>\n\n\n\n<p>If you&#8217;re programming the ESP32 using PlatformIO, you should include the libraries on the <span class=\"rnthl rntliteral\">platformio.ini<\/span> file like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>&#091;env:esp32doit-devkit-v1]\nplatform = espressif32\nboard = esp32doit-devkit-v1\nframework = arduino\nmonitor_speed = 115200\nlib_deps = adafruit\/Adafruit NeoPixel @ ^1.7.0\n           adafruit\/Adafruit SSD1306 @ ^2.4.1\n           adafruit\/Adafruit Unified Sensor @ ^1.1.4\n           adafruit\/Adafruit BME280 Library @ ^2.1.2\n           adafruit\/Adafruit GFX Library @ ^1.10.3\n           adafruit\/Adafruit BusIO @ ^1.6.0\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Code<\/h3>\n\n\n\n<p>Copy the following code to your Arduino IDE or to the <span class=\"rnthl rntliteral\">main.cpp<\/span> file if your using PlatformIO.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\r\n  Rui Santos\r\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-weather-station-pcb\/\r\n  \r\n  Permission is hereby granted, free of charge, to any person obtaining a copy\r\n  of this software and associated documentation files.\r\n  \r\n  The above copyright notice and this permission notice shall be included in all\r\n  copies or substantial portions of the Software.\r\n*\/\r\n\r\n#include &lt;Arduino.h&gt;\r\n#include &lt;Adafruit_NeoPixel.h&gt;\r\n#include &lt;Wire.h&gt;\r\n#include &lt;Adafruit_GFX.h&gt;\r\n#include &lt;Adafruit_SSD1306.h&gt;\r\n#include &lt;Adafruit_Sensor.h&gt;\r\n#include &lt;Adafruit_BME280.h&gt;\r\n#include &lt;WiFi.h&gt;\r\n#include &lt;time.h&gt;\r\n\r\n\/\/ Insert your network credentials\r\nconst char* ssid     = &quot;REPLACE_WITH_YOUR_SSID&quot;;\r\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\r\n\r\n\/\/ NTP Server Details\r\nconst char* ntpServer = &quot;pool.ntp.org&quot;;\r\nconst long  gmtOffset_sec = 0;\r\nconst int   daylightOffset_sec = 3600;\r\n\r\n\/\/ OLED Display\r\n#define SCREEN_WIDTH 128  \/\/ OLED display width, in pixels\r\n#define SCREEN_HEIGHT 64  \/\/ OLED display height, in pixels\r\n\r\n#define I2Cdisplay_SDA 21\r\n#define I2Cdisplay_SCL 22\r\nTwoWire I2Cdisplay = TwoWire(1);\r\n\r\nAdafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;I2Cdisplay, -1);\r\n\r\n\/\/ WS2812B Addressable RGB LEDs\r\n#define LED_PIN    27  \/\/ GPIO the LEDs are connected to\r\n#define LED_COUNT  12  \/\/ Number of LEDs\r\nAdafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);\r\n\r\n\/\/ BME280\r\n#define I2C_SDA 21\r\n#define I2C_SCL 22\r\nTwoWire I2CBME = TwoWire(0);\r\nAdafruit_BME280 bme;\r\n\r\n\/\/ LDR (Light Dependent Resistor)\r\n#define ldr  33          \r\n\r\n\/\/ Pushbutton\r\n#define buttonPin  18    \r\n\r\nint buttonState;              \/\/ current reading from the input pin\r\nint lastButtonState = LOW;    \/\/ previous reading from the input pin\r\n\r\nunsigned long lastDebounceTime = 0;  \/\/ the last time the output pin was toggled\r\nunsigned long debounceDelay = 50;    \/\/ the debounce time; increase if the output flickers\r\n\r\n\/\/ Screens\r\nint displayScreenNum = 0;\r\nint displayScreenNumMax = 4;\r\n\r\nunsigned long lastTimer = 0;\r\nunsigned long timerDelay = 15000;\r\n\r\nunsigned char temperature_icon[] ={\r\n  0b00000001, 0b11000000, \/\/        ###      \r\n  0b00000011, 0b11100000, \/\/       #####     \r\n  0b00000111, 0b00100000, \/\/      ###  #     \r\n  0b00000111, 0b11100000, \/\/      ######     \r\n  0b00000111, 0b00100000, \/\/      ###  #     \r\n  0b00000111, 0b11100000, \/\/      ######     \r\n  0b00000111, 0b00100000, \/\/      ###  #     \r\n  0b00000111, 0b11100000, \/\/      ######     \r\n  0b00000111, 0b00100000, \/\/      ###  #     \r\n  0b00001111, 0b11110000, \/\/     ########    \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00001111, 0b11110000, \/\/     ########    \r\n  0b00000111, 0b11100000, \/\/      ######     \r\n};\r\n\r\nunsigned char humidity_icon[] ={\r\n  0b00000000, 0b00000000, \/\/                 \r\n  0b00000001, 0b10000000, \/\/        ##       \r\n  0b00000011, 0b11000000, \/\/       ####      \r\n  0b00000111, 0b11100000, \/\/      ######     \r\n  0b00001111, 0b11110000, \/\/     ########    \r\n  0b00001111, 0b11110000, \/\/     ########    \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00011111, 0b11011000, \/\/    ####### ##   \r\n  0b00111111, 0b10011100, \/\/   #######  ###  \r\n  0b00111111, 0b10011100, \/\/   #######  ###  \r\n  0b00111111, 0b00011100, \/\/   ######   ###  \r\n  0b00011110, 0b00111000, \/\/    ####   ###   \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00001111, 0b11110000, \/\/     ########    \r\n  0b00000011, 0b11000000, \/\/       ####      \r\n  0b00000000, 0b00000000, \/\/                 \r\n};\r\n\r\nunsigned char arrow_down_icon[] ={\r\n  0b00001111, 0b11110000, \/\/     ########    \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00011111, 0b11111000, \/\/    ##########   \r\n  0b00011100, 0b00111000, \/\/    ###    ###   \r\n  0b00011100, 0b00111000, \/\/    ###    ###   \r\n  0b00011100, 0b00111000, \/\/    ###    ###   \r\n  0b01111100, 0b00111110, \/\/  #####    ##### \r\n  0b11111100, 0b00111111, \/\/ ######    ######\r\n  0b11111100, 0b00111111, \/\/ ######    ######\r\n  0b01111000, 0b00011110, \/\/  ####      #### \r\n  0b00111100, 0b00111100, \/\/   ####    ####  \r\n  0b00011110, 0b01111000, \/\/    ####  ####   \r\n  0b00001111, 0b11110000, \/\/     ########    \r\n  0b00000111, 0b11100000, \/\/      ######     \r\n  0b00000011, 0b11000000, \/\/       ####      \r\n  0b00000001, 0b10000000, \/\/        ##       \r\n};\r\n\r\nunsigned char sun_icon[] ={\r\n  0b00000000, 0b00000000, \/\/                 \r\n  0b00100000, 0b10000010, \/\/   #     #     # \r\n  0b00010000, 0b10000100, \/\/    #    #    #  \r\n  0b00001000, 0b00001000, \/\/     #       #   \r\n  0b00000001, 0b11000000, \/\/        ###      \r\n  0b00000111, 0b11110000, \/\/      #######    \r\n  0b00000111, 0b11110000, \/\/      #######    \r\n  0b00001111, 0b11111000, \/\/     #########   \r\n  0b01101111, 0b11111011, \/\/  ## ######### ##\r\n  0b00001111, 0b11111000, \/\/     #########   \r\n  0b00000111, 0b11110000, \/\/      #######    \r\n  0b00000111, 0b11110000, \/\/      #######    \r\n  0b00010001, 0b11000100, \/\/    #   ###   #  \r\n  0b00100000, 0b00000010, \/\/   #           # \r\n  0b01000000, 0b10000001, \/\/  #      #      #\r\n  0b00000000, 0b10000000, \/\/         #       \r\n};\r\n\r\n\/\/ Clear the LEDs\r\nvoid colorWipe(uint32_t color, int wait, int numNeoPixels) {\r\n  for(int i=0; i&lt;numNeoPixels; i++) { \/\/ For each pixel in strip...\r\n    strip.setPixelColor(i, color);         \/\/  Set pixel's color (in RAM)\r\n    strip.show();                          \/\/  Update strip to match\r\n    delay(wait);                           \/\/  Pause for a moment\r\n  }\r\n}\r\n\r\n\/\/ Rainbow cycle along all LEDs. Pass delay time (in ms) between frames.\r\nvoid rainbow(int wait) {\r\n  long firstPixelHue = 256;\r\n    for(int i=0; i&lt;strip.numPixels(); i++) { \/\/ For each pixel in strip...\r\n      int pixelHue = firstPixelHue + (i * 65536L \/ strip.numPixels());\r\n      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));\r\n    }\r\n    strip.show(); \/\/ Update strip with new contents\r\n    delay(wait);  \/\/ Pause for a moment\r\n}\r\n\r\n\/\/ Create display marker for each screen\r\nvoid displayIndicator(int displayNumber) {\r\n  int xCoordinates[5] = {44, 54, 64, 74, 84};\r\n  for (int i =0; i&lt;5; i++) {\r\n    if (i == displayNumber) {\r\n      display.fillCircle(xCoordinates[i], 60, 2, WHITE);\r\n    }\r\n    else {\r\n      display.drawCircle(xCoordinates[i], 60, 2, WHITE);\r\n    }\r\n  }\r\n}\r\n\r\n\/\/SCREEN NUMBER 0: DATE AND TIME\r\nvoid displayLocalTime(){\r\n  struct tm timeinfo;\r\n  if(!getLocalTime(&amp;timeinfo)){\r\n    Serial.println(&quot;Failed to obtain time&quot;);\r\n  }\r\n  Serial.println(&amp;timeinfo, &quot;%A, %B %d %Y %H:%M:%S&quot;);\r\n\r\n  \/\/GET DATE\r\n  \/\/Get full weekday name\r\n  char weekDay[10];\r\n  strftime(weekDay, sizeof(weekDay), &quot;%a&quot;, &amp;timeinfo);\r\n  \/\/Get day of month\r\n  char dayMonth[4];\r\n  strftime(dayMonth, sizeof(dayMonth), &quot;%d&quot;, &amp;timeinfo);\r\n  \/\/Get abbreviated month name\r\n  char monthName[5];\r\n  strftime(monthName, sizeof(monthName), &quot;%b&quot;, &amp;timeinfo);\r\n  \/\/Get year\r\n  char year[6];\r\n  strftime(year, sizeof(year), &quot;%Y&quot;, &amp;timeinfo);\r\n\r\n  \/\/GET TIME\r\n  \/\/Get hour (12 hour format)\r\n  \/*char hour[4];\r\n  strftime(hour, sizeof(hour), &quot;%I&quot;, &amp;timeinfo);*\/\r\n  \r\n  \/\/Get hour (24 hour format)\r\n  char hour[4];\r\n  strftime(hour, sizeof(hour), &quot;%H&quot;, &amp;timeinfo);\r\n  \/\/Get minute\r\n  char minute[4];\r\n  strftime(minute, sizeof(minute), &quot;%M&quot;, &amp;timeinfo);\r\n\r\n  \/\/Display Date and Time on OLED display\r\n  display.clearDisplay();\r\n  display.setTextColor(WHITE);\r\n  display.setTextSize(3);\r\n  display.setCursor(19,5);\r\n  display.print(hour);\r\n  display.print(&quot;:&quot;);\r\n  display.print(minute);\r\n  display.setTextSize(1);\r\n  display.setCursor(16,40);\r\n  display.print(weekDay);\r\n  display.print(&quot;, &quot;);\r\n  display.print(dayMonth);\r\n  display.print(&quot; &quot;);\r\n  display.print(monthName);\r\n  display.print(&quot; &quot;);\r\n  display.print(year);\r\n  displayIndicator(displayScreenNum);\r\n  display.display();\r\n  rainbow(10);\r\n}\r\n\r\n\/\/ SCREEN NUMBER 1: TEMPERATURE\r\nvoid displayTemperature(){\r\n  display.clearDisplay();\r\n  display.setTextSize(2);\r\n  display.drawBitmap(15, 5, temperature_icon, 16, 16 ,1);\r\n  display.setCursor(35, 5);\r\n  float temperature = bme.readTemperature();\r\n  display.print(temperature);\r\n  display.cp437(true);\r\n  display.setTextSize(1);\r\n  display.print(&quot; &quot;);\r\n  display.write(167);\r\n  display.print(&quot;C&quot;);\r\n  display.setCursor(0, 34);\r\n  display.setTextSize(1);\r\n  display.print(&quot;Humidity: &quot;);\r\n  display.print(bme.readHumidity());\r\n  display.print(&quot; %&quot;);\r\n  display.setCursor(0, 44);\r\n  display.setTextSize(1);\r\n  display.print(&quot;Pressure: &quot;);\r\n  display.print(bme.readPressure()\/100.0F);\r\n  display.print(&quot; hpa&quot;);\r\n  displayIndicator(displayScreenNum);\r\n  display.display();\r\n  int temperaturePer = map(temperature, -5, 36, 0, LED_COUNT-1);\r\n  colorWipe(strip.Color(0,   255,   0), 50, temperaturePer);\r\n}\r\n\r\n\/\/ SCREEN NUMBER 2: HUMIDITY\r\nvoid displayHumidity(){\r\n  display.clearDisplay();\r\n  display.setTextSize(2);\r\n  display.drawBitmap(15, 5, humidity_icon, 16, 16 ,1);\r\n  display.setCursor(35, 5);\r\n  float humidity = bme.readHumidity();\r\n  display.print(humidity);\r\n  display.print(&quot; %&quot;);\r\n  display.setCursor(0, 34);\r\n  display.setTextSize(1);\r\n  display.print(&quot;Temperature: &quot;);\r\n  display.print(bme.readTemperature());\r\n  display.cp437(true);\r\n  display.print(&quot; &quot;);\r\n  display.write(167);\r\n  display.print(&quot;C&quot;);\r\n  display.setCursor(0, 44);\r\n  display.setTextSize(1);\r\n  display.print(&quot;Pressure: &quot;);\r\n  display.print(bme.readPressure()\/100.0F);\r\n  display.print(&quot; hpa&quot;);\r\n  displayIndicator(displayScreenNum);\r\n  display.display();\r\n  int humidityPer = map(humidity, 0, 100, 0, LED_COUNT-1);\r\n  colorWipe(strip.Color(0,   0,   255), 50, humidityPer);\r\n}\r\n\r\n\/\/ SCREEN NUMBER 3: PRESSURE\r\nvoid displayPressure(){\r\n  display.clearDisplay();\r\n  display.setTextSize(2);\r\n  display.drawBitmap(0, 5, arrow_down_icon, 16, 16 ,1);\r\n  display.setCursor(20, 5);\r\n  display.print(bme.readPressure()\/100.0F);\r\n  display.setTextSize(1);\r\n  display.print(&quot; hpa&quot;);\r\n  display.setCursor(0, 34);\r\n  display.setTextSize(1);\r\n  display.print(&quot;Temperature: &quot;);\r\n  display.print(bme.readTemperature());\r\n  display.cp437(true);\r\n  display.print(&quot; &quot;);\r\n  display.write(167);\r\n  display.print(&quot;C&quot;);\r\n  display.setCursor(0, 44);\r\n  display.setTextSize(1);\r\n  display.print(&quot;Humidity: &quot;);\r\n  display.print(bme.readHumidity());\r\n  display.print(&quot; hpa&quot;);\r\n  displayIndicator(displayScreenNum);\r\n  display.display();\r\n  colorWipe(strip.Color(255,   0,   255), 50, 12);\r\n}\r\n\r\n\/\/ SCREEN NUMBER 4: LUMINOSITY\r\nvoid displayLDR(){\r\n  display.clearDisplay();\r\n  display.setTextSize(2);\r\n  display.drawBitmap(33, 5, sun_icon, 16, 16 ,1);\r\n  display.setCursor(53, 5);\r\n  int ldrReading = map(analogRead(ldr), 0, 4095, 100, 0);\r\n  display.print(ldrReading);\r\n  display.print(&quot; %&quot;);\r\n  display.setTextSize(1);\r\n  display.setCursor(0, 34);\r\n  display.print(&quot;Temperature: &quot;);\r\n  display.print(bme.readTemperature());\r\n  display.print(&quot; &quot;);\r\n  display.cp437(true);\r\n  display.write(167);\r\n  display.print(&quot;C&quot;);\r\n  display.setCursor(0, 44);\r\n  display.setTextSize(1);\r\n  display.print(&quot;Humidity: &quot;);\r\n  display.print(bme.readHumidity());\r\n  display.print(&quot; %&quot;);\r\n  display.setCursor(0, 44);\r\n  displayIndicator(displayScreenNum);\r\n  display.display();\r\n  int ldrReadingPer = map(ldrReading, 0, 100, 0, LED_COUNT-1);\r\n  colorWipe(strip.Color(255,   255,   0), 50, ldrReadingPer);\r\n}\r\n\r\n\/\/ Display the right screen accordingly to the displayScreenNum\r\nvoid updateScreen() {\r\n  colorWipe(strip.Color(0, 0, 0), 1, LED_COUNT);\r\n  if (displayScreenNum == 0){\r\n    displayLocalTime();\r\n  }\r\n  else if (displayScreenNum == 1) {\r\n    displayTemperature();\r\n  }\r\n  else if (displayScreenNum ==2){\r\n    displayHumidity();\r\n  }\r\n  else if (displayScreenNum==3){\r\n    displayPressure();\r\n  }\r\n  else {\r\n    displayLDR();\r\n  }\r\n}\r\n\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  \r\n  \/\/ Initialize the pushbutton pin as an input\r\n  pinMode(buttonPin, INPUT);\r\n  \r\n  I2CBME.begin(I2C_SDA, I2C_SCL, 100000);\r\n  I2Cdisplay.begin(I2Cdisplay_SDA, I2Cdisplay_SCL, 100000); \r\n\r\n  \/\/ Initialize OLED Display\r\n  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {\r\n    Serial.println(F(&quot;SSD1306 allocation failed&quot;));\r\n    for(;;);\r\n  }\r\n  display.clearDisplay();\r\n  display.setTextColor(WHITE);\r\n  \r\n  \/\/ Initialize BME280\r\n  bool status = bme.begin(0x76, &amp;I2CBME);  \r\n  if (!status) {\r\n    Serial.println(&quot;Could not find a valid BME280 sensor, check wiring!&quot;);\r\n    while (1);\r\n  }\r\n  \r\n  \/\/ Initialize WS2812B LEDs\r\n  strip.begin();           \/\/ INITIALIZE NeoPixel strip object (REQUIRED)\r\n  strip.show();            \/\/ Turn OFF all pixels ASAP\r\n  strip.setBrightness(50); \/\/ Set BRIGHTNESS to about 1\/5 (max = 255)\r\n\r\n  \/\/ Connect to Wi-Fi\r\n  Serial.print(&quot;Connecting to &quot;);\r\n  Serial.println(ssid);\r\n  WiFi.begin(ssid, password);\r\n  while (WiFi.status() != WL_CONNECTED) {\r\n    delay(500);\r\n    Serial.print(&quot;.&quot;);\r\n  }\r\n  Serial.println(&quot;&quot;);\r\n  Serial.println(&quot;WiFi connected.&quot;);\r\n  \r\n  \/\/ Init and get the time\r\n  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);\r\n}\r\n\r\nvoid loop() {\r\n  \/\/ read the state of the switch into a local variable\r\n  int reading = digitalRead(buttonPin);\r\n\r\n  \/\/ Change screen when the pushbutton is pressed\r\n  if (reading != lastButtonState) {\r\n    lastDebounceTime = millis();\r\n  }\r\n\r\n  if ((millis() - lastDebounceTime) &gt; debounceDelay) {\r\n    if (reading != buttonState) {\r\n      buttonState = reading;\r\n      if (buttonState == HIGH) {\r\n        updateScreen();\r\n        Serial.println(displayScreenNum);\r\n        if(displayScreenNum &lt; displayScreenNumMax) {\r\n          displayScreenNum++;\r\n        }\r\n        else {\r\n          displayScreenNum = 0;\r\n        }\r\n        lastTimer = millis();\r\n      }\r\n    }\r\n  }\r\n  lastButtonState = reading;\r\n  \r\n  \/\/ Change screen every 15 seconds (timerDelay variable)\r\n  if ((millis() - lastTimer) &gt; timerDelay) {\r\n    updateScreen();\r\n    Serial.println(displayScreenNum);\r\n    if(displayScreenNum &lt; displayScreenNumMax) {\r\n      displayScreenNum++;\r\n    }\r\n    else {\r\n      displayScreenNum = 0;\r\n    }\r\n    lastTimer = millis();\r\n  }\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Weather-Station-PCB\/raw\/main\/ESP32_Weather_Station_PCB\/ESP32_Weather_Station_PCB.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>We get date and time from an NTP server. So, the ESP32 needs to connect to the internet. Insert your network credentials on the following variables and the code will work straight away.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ssid = \"REPLACE_WITH_YOUR_SSID\";\nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>Read this section if you want to learn how the code works, or skip to the&nbsp;next section.<\/p>\n\n\n\n<p>This code is quite long, but simple. If you want to fully understand how it works, you may need to take a look at the following tutorials:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-date-time-ntp-client-server-arduino\/\">ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-ssd1306-oled-display-arduino-ide\/\">ESP32 OLED Display with Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-dht-temperature-and-humidity-oled-display\/\">ESP32\/ESP8266: DHT Temperature and Humidity Readings in OLED Display<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-bme280-arduino-ide-pressure-temperature-humidity\/\">ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/guide-for-ws2812b-addressable-rgb-led-strip-with-arduino\/\">Guide for WS2812B Addressable RGB LED Strip with Arduino<\/a><\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Including Libraries<\/h4>\n\n\n\n<p>First, you need to include the necessary libraries.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;Arduino.h&gt;\n#include &lt;Adafruit_NeoPixel.h&gt;\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_GFX.h&gt;\n#include &lt;Adafruit_SSD1306.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;\n#include &lt;WiFi.h&gt;\n#include &lt;time.h&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Network Credentials<\/h4>\n\n\n\n<p>Insert your network credentials in the following lines so that the ESP32 can connect to your network to request date and time from an NTP server.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ssid     = \"REPLACE_WITH_YOUR_SSID\";\nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">NTP Server<\/h4>\n\n\n\n<p>Then, you need to define the following variables to configure and get time from an NTP server: <span class=\"rnthl rntliteral\">ntpServer<\/span>, <span class=\"rnthl rntliteral\">gmtOffset_sec<\/span> and <span class=\"rnthl rntliteral\">daylightOffset_sec<\/span>.<\/p>\n\n\n\n<p>We\u2019ll request the time from <em>pool.ntp.org<\/em>, which is a cluster of timeservers that anyone can use to request the time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ntpServer = \"pool.ntp.org\";<\/code><\/pre>\n\n\n\n<p><strong>GMT Offset<\/strong><\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">gmtOffset_sec<\/span> variable defines the offset in seconds between your time zone and GMT. We live in Portugal, so the time offset is 0. Change the time <span class=\"rnthl rntliteral\">gmtOffset_sec<\/span> variable to match your time zone.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const long gmtOffset_sec = 0;<\/code><\/pre>\n\n\n\n<p><strong>Daylight Offset<\/strong><\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">daylightOffset_sec<\/span> variable defines the offset in seconds for daylight saving time. It is generally one hour, that corresponds to 3600 seconds<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const int daylightOffset_sec = 3600;<\/code><\/pre>\n\n\n\n<p class=\"rntbox rntclblue\">Learn more about getting time from NTP server: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-date-time-ntp-client-server-arduino\/\">ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">OLED Display<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">SCREEN_WIDTH<\/span> and <span class=\"rnthl rntliteral\">SCREEN_HEIGHT<\/span> variables define the dimensions of the OLED display in pixels. We&#8217;re using a 0.96inch OLED display: 128 x 64 pixels.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define SCREEN_WIDTH 128  \/\/ OLED display width, in pixels\n#define SCREEN_HEIGHT 64  \/\/ OLED display height, in pixels<\/code><\/pre>\n\n\n\n<p>The OLED display is connected to GPIO 22 (SCL) and GPIO 21 (SDA).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define I2Cdisplay_SDA 21\n#define I2Cdisplay_SCL 22\nTwoWire I2Cdisplay = TwoWire(1);<\/code><\/pre>\n\n\n\n<p>Initialize a <span class=\"rnthl rntliteral\">display<\/span> object with the width and height defined earlier with I2C communication protocol (<span class=\"rnthl rntliteral\">&amp;I2Cdisplay<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;I2Cdisplay, -1);\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">WS2812B Addressable RGB LEDS<\/h4>\n\n\n\n<p>You need to define the GPIO that the RGB LEDs are connected to. Addressable RGB LEDs communicate with the ESP32 using One Wire protocol. So, all LEDs can be controlled by the same GPIO. In this case, they are connected to GPIO 27.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED_PIN 27<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">LED_COUNT<\/span> variable saves the number of addressable RGB LEDs we want to control. In this case, it&#8217;s 12.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED_COUNT 12<\/code><\/pre>\n\n\n\n<p>Create an <span class=\"rnthl rntliteral\">Adafruit_NeoPixel<\/span> object called <span class=\"rnthl rntliteral\">strip<\/span> to control the addressable RGB LEDs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">BME280 Sensor<\/h4>\n\n\n\n<p>Create an <span class=\"rnthl rntliteral\">Adafruit_BME280<\/span> object called <span class=\"rnthl rntliteral\">bme<\/span> on the default ESP32 pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define I2C_SDA 21\n#define I2C_SCL 22\nTwoWire I2CBME = TwoWire(0);\nAdafruit_BME280 bme;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">LDR<\/h4>\n\n\n\n<p>Define the GPIO the LDR is connected to.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const int ldr = 33; \/\/ LDR (Light Dependent Resistor)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Pushbutton<\/h4>\n\n\n\n<p>Define the GPIO the pushbutton is connected to.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define buttonPin 18<\/code><\/pre>\n\n\n\n<p>The following variables are used to handle the pushbutton.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>int buttonState;              \/\/ current reading from the input pin\nint lastButtonState = LOW;    \/\/ previous reading from the input pin\n\nunsigned long lastDebounceTime = 0;  \/\/ the last time the output pin was toggled\nunsigned long debounceDelay = 50;    \/\/ the debounce time; increase if the output flickers<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">OLED Screens<\/h4>\n\n\n\n<p>As mentioned previously, the OLED will display five different screens. Each screen is numbered from 0 to 4.  The <span class=\"rnthl rntliteral\">displayScreenNum<\/span> variable holds the screen number that must be displayed on the OLED &#8211; it starts at zero. The <span class=\"rnthl rntliteral\">displayNumMax<\/span> holds the maximum number of screens.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>int displayScreenNum = 0;\nint displayScreenNumMax = 4;<\/code><\/pre>\n\n\n\n<p>The next variables will be used to handle the timer to display each screen for 15 seconds. You can change the display screen period on the <span class=\"rnthl rntliteral\">timerDelay<\/span> variable.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned long lastTimer = 0;\nunsigned long timerDelay = 15000;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Icons<\/h4>\n\n\n\n<p>In each screen, the OLED displays an icon related with the reading it is showing. In the temperature screen it displays a thermometer (<span class=\"rnthl rntliteral\">temperature_icon<\/span>), in the humidity screen a teardrop (<span class=\"rnthl rntliteral\">humidity_icon<\/span>), in the pressure screen a arrow (<span class=\"rnthl rntliteral\">arrow_down_icon<\/span>) and in the luminosity screen a sun (<span class=\"rnthl rntliteral\">sun_icon<\/span>). We need to include those icons in the code. These icons are 16&#215;16 pixels.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unsigned char temperature_icon&#091;] ={\n  0b00000001, 0b11000000, \/\/        ###      \n  0b00000011, 0b11100000, \/\/       #####     \n  0b00000111, 0b00100000, \/\/      ###  #     \n  0b00000111, 0b11100000, \/\/      ######     \n  0b00000111, 0b00100000, \/\/      ###  #     \n  0b00000111, 0b11100000, \/\/      ######     \n  0b00000111, 0b00100000, \/\/      ###  #     \n  0b00000111, 0b11100000, \/\/      ######     \n  0b00000111, 0b00100000, \/\/      ###  #     \n  0b00001111, 0b11110000, \/\/     ########    \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00001111, 0b11110000, \/\/     ########    \n  0b00000111, 0b11100000, \/\/      ######     \n};\n\nunsigned char humidity_icon&#091;] ={\n  0b00000000, 0b00000000, \/\/                 \n  0b00000001, 0b10000000, \/\/        ##       \n  0b00000011, 0b11000000, \/\/       ####      \n  0b00000111, 0b11100000, \/\/      ######     \n  0b00001111, 0b11110000, \/\/     ########    \n  0b00001111, 0b11110000, \/\/     ########    \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00011111, 0b11011000, \/\/    ####### ##   \n  0b00111111, 0b10011100, \/\/   #######  ###  \n  0b00111111, 0b10011100, \/\/   #######  ###  \n  0b00111111, 0b00011100, \/\/   ######   ###  \n  0b00011110, 0b00111000, \/\/    ####   ###   \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00001111, 0b11110000, \/\/     ########    \n  0b00000011, 0b11000000, \/\/       ####      \n  0b00000000, 0b00000000, \/\/                 \n};\n\n unsigned char arrow_down_icon&#091;] ={\n  0b00001111, 0b11110000, \/\/     ########    \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00011111, 0b11111000, \/\/    ##########   \n  0b00011100, 0b00111000, \/\/    ###    ###   \n  0b00011100, 0b00111000, \/\/    ###    ###   \n  0b00011100, 0b00111000, \/\/    ###    ###   \n  0b01111100, 0b00111110, \/\/  #####    ##### \n  0b11111100, 0b00111111, \/\/ ######    ######\n  0b11111100, 0b00111111, \/\/ ######    ######\n  0b01111000, 0b00011110, \/\/  ####      #### \n  0b00111100, 0b00111100, \/\/   ####    ####  \n  0b00011110, 0b01111000, \/\/    ####  ####   \n  0b00001111, 0b11110000, \/\/     ########    \n  0b00000111, 0b11100000, \/\/      ######     \n  0b00000011, 0b11000000, \/\/       ####      \n  0b00000001, 0b10000000, \/\/        ##       \n};\n\n unsigned char sun_icon&#091;] ={\n  0b00000000, 0b00000000, \/\/                 \n  0b00100000, 0b10000010, \/\/   #     #     # \n  0b00010000, 0b10000100, \/\/    #    #    #  \n  0b00001000, 0b00001000, \/\/     #       #   \n  0b00000001, 0b11000000, \/\/        ###      \n  0b00000111, 0b11110000, \/\/      #######    \n  0b00000111, 0b11110000, \/\/      #######    \n  0b00001111, 0b11111000, \/\/     #########   \n  0b01101111, 0b11111011, \/\/  ## ######### ##\n  0b00001111, 0b11111000, \/\/     #########   \n  0b00000111, 0b11110000, \/\/      #######    \n  0b00000111, 0b11110000, \/\/      #######    \n  0b00010001, 0b11000100, \/\/    #   ###   #  \n  0b00100000, 0b00000010, \/\/   #           # \n  0b01000000, 0b10000001, \/\/  #      #      #\n  0b00000000, 0b10000000, \/\/         #       \n};<\/code><\/pre>\n\n\n\n<p>To learn more about how to display icons, we recommend reading our OLED guide: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-ssd1306-oled-display-arduino-ide\/\">ESP32 OLED Display with Arduino IDE<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">colorWipe() and rainbow() functions<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">colorWipe()<\/span> and <span class=\"rnthl rntliteral\">rainbow()<\/span> functions are used to control the addresable RGB LEDs. <\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">colorWipe()<\/span> is used to light up or clear specific LEDs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void colorWipe(uint32_t color, int wait, int numNeoPixels) {\n  for(int i=0; i&lt;numNeoPixels; i++) { \/\/ For each pixel in strip...\n    strip.setPixelColor(i, color);         \/\/  Set pixel's color (in RAM)\n    strip.show();                          \/\/  Update strip to match\n    delay(wait);                           \/\/  Pause for a moment\n  }\n}<\/code><\/pre>\n\n\n\n<p> The <span class=\"rnthl rntliteral\">rainbow()<\/span> function, as the name suggests, displays a rainbow effect.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Rainbow cycle along all LEDs. Pass delay time (in ms) between frames.\nvoid rainbow(int wait) {\n  long firstPixelHue = 256;\n    for(int i=0; i&lt;strip.numPixels(); i++) { \/\/ For each pixel in strip...\n      int pixelHue = firstPixelHue + (i * 65536L \/ strip.numPixels());\n      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));\n    }\n    strip.show(); \/\/ Update strip with new contents\n    delay(wait);  \/\/ Pause for a moment\n}<\/code><\/pre>\n\n\n\n<p>You can learn more about these and other functions to control the strip by taking a look at the <a href=\"https:\/\/github.com\/adafruit\/Adafruit_NeoPixel\/tree\/master\/examples\" target=\"_blank\" rel=\"noreferrer noopener\">Neopixel Library&#8217;s examples<\/a>. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">displayIndicator() function<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">displayIndicator()<\/span> creates five little circles at the bottom of the display accordingly to the screen that is being displayed at the moment.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create display marker for each screen\nvoid displayIndicator(int displayNumber) {\n  int xCoordinates&#091;5] = {44, 54, 64, 74, 84};\n  for (int i =0; i&lt;5; i++) {\n    if (i == displayNumber) {\n      display.fillCircle(xCoordinates&#091;i], 60, 2, WHITE);\n    }\n    else {\n      display.drawCircle(xCoordinates&#091;i], 60, 2, WHITE);\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">drawCircle(x, y, radius, color)<\/span> function creates a circle. The <span class=\"rnthl rntliteral\">fillCircle(x, y, radius, color)<\/span> creates a filled circle.<\/p>\n\n\n\n<p>We&#8217;re placing the center of the circles on the following x coordinates: 44, 54, 64, 74 and 84.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>int xCoordinates&#091;5] = {44, 54, 64, 74, 84};<\/code><\/pre>\n\n\n\n<p> We draw a filled circle for the current display and a &#8220;empty&#8221; circle for the other displays:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (i == displayNumber) {\n  display.fillCircle(xCoordinates&#091;i], 60, 2, WHITE);\n}\nelse {\n  display.drawCircle(xCoordinates&#091;i], 60, 2, WHITE);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Screen Number 0: Date and Time<\/h4>\n\n\n\n<p>The first screen that shows up on the OLED displays date and time. That&#8217;s what the <span class=\"rnthl rntliteral\">displayLocalTime()<\/span> function does. It also displays a rainbow effect on the addressable RGB LEDs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/SCREEN NUMBER 0: DATE AND TIME\nvoid displayLocalTime(){\n  struct tm timeinfo;\n  if(!getLocalTime(&amp;timeinfo)){\n    Serial.println(\"Failed to obtain time\");\n  }\n  Serial.println(&amp;timeinfo, \"%A, %B %d %Y %H:%M:%S\");\n\n  \/\/GET DATE\n  \/\/Get full weekday name\n  char weekDay&#091;10];\n  strftime(weekDay, sizeof(weekDay), \"%a\", &amp;timeinfo);\n  \/\/Get day of month\n  char dayMonth&#091;4];\n  strftime(dayMonth, sizeof(dayMonth), \"%d\", &amp;timeinfo);\n  \/\/Get abbreviated month name\n  char monthName&#091;5];\n  strftime(monthName, sizeof(monthName), \"%b\", &amp;timeinfo);\n  \/\/Get year\n  char year&#091;6];\n  strftime(year, sizeof(year), \"%Y\", &amp;timeinfo);\n\n  \/\/GET TIME\n  \/\/Get hour (12 hour format)\n  \/*char hour&#091;4];\n  strftime(hour, sizeof(hour), \"%I\", &amp;timeinfo);*\/\n  \n  \/\/Get hour (24 hour format)\n  char hour&#091;4];\n  strftime(hour, sizeof(hour), \"%H\", &amp;timeinfo);\n  \/\/Get minute\n  char minute&#091;4];\n  strftime(minute, sizeof(minute), \"%M\", &amp;timeinfo);\n\n  \/\/Display Date and Time on OLED display\n  display.clearDisplay();\n  display.setTextColor(WHITE);\n  display.setTextSize(3);\n  display.setCursor(19,5);\n  display.print(hour);\n  display.print(\":\");\n  display.print(minute);\n  display.setTextSize(1);\n  display.setCursor(16,40);\n  display.print(weekDay);\n  display.print(\", \");\n  display.print(dayMonth);\n  display.print(\" \");\n  display.print(monthName);\n  display.print(\" \");\n  display.print(year);\n  displayIndicator(displayScreenNum);\n  display.display();\n  rainbow(10);\n}<\/code><\/pre>\n\n\n\n<p class=\"rntbox rntclblue\">Learn more about getting date and time from an NTP server with the ESP32: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-date-time-ntp-client-server-arduino\/\">ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Screen Number 1: Temperature<\/h4>\n\n\n\n<p>The second screen displays temperature. That&#8217;s done by calling the <span class=\"rnthl rntliteral\">displayTemperature()<\/span> function. This function also lights up the LEDs in a green color accordingly to the temperature value.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ SCREEN NUMBER 1: TEMPERATURE\nvoid displayTemperature(){\n  display.clearDisplay();\n  display.setTextSize(2);\n  display.drawBitmap(15, 5, temperature_icon, 16, 16 ,1);\n  display.setCursor(35, 5);\n  float temperature = bme.readTemperature();\n  display.print(temperature);\n  display.cp437(true);\n  display.setTextSize(1);\n  display.print(\" \");\n  display.write(167);\n  display.print(\"C\");\n  display.setCursor(0, 34);\n  display.setTextSize(1);\n  display.print(\"Humidity: \");\n  display.print(bme.readHumidity());\n  display.print(\" %\");\n  display.setCursor(0, 44);\n  display.setTextSize(1);\n  display.print(\"Pressure: \");\n  display.print(bme.readPressure()\/100.0F);\n  display.print(\" hpa\");\n  displayIndicator(displayScreenNum);\n  display.display();\n  int temperaturePer = map(temperature, -5, 36, 0, LED_COUNT-1);\n  colorWipe(strip.Color(0,   255,   0), 50, temperaturePer);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Screen Number 2: Humidity<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">displayHumidity()<\/span> function is similar to the <span class=\"rnthl rntliteral\">displayTemperature()<\/span> function but displays the humidity value.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ SCREEN NUMBER 2: HUMIDITY\nvoid displayHumidity(){\n  display.clearDisplay();\n  display.setTextSize(2);\n  display.drawBitmap(15, 5, humidity_icon, 16, 16 ,1);\n  display.setCursor(35, 5);\n  float humidity = bme.readHumidity();\n  display.print(humidity);\n  display.print(\" %\");\n  display.setCursor(0, 34);\n  display.setTextSize(1);\n  display.print(\"Temperature: \");\n  display.print(bme.readTemperature());\n  display.cp437(true);\n  display.print(\" \");\n  display.write(167);\n  display.print(\"C\");\n  display.setCursor(0, 44);\n  display.setTextSize(1);\n  display.print(\"Pressure: \");\n  display.print(bme.readPressure()\/100.0F);\n  display.print(\" hpa\");\n  displayIndicator(displayScreenNum);\n  display.display();\n  int humidityPer = map(humidity, 0, 100, 0, LED_COUNT-1);\n  colorWipe(strip.Color(0,   0,   255), 50, humidityPer);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Screen Number 3: Pressure<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">displayPressure()<\/span> function is similar to the two previous functions, but display the pressure value.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ SCREEN NUMBER 3: PRESSURE\nvoid displayPressure(){\n  display.clearDisplay();\n  display.setTextSize(2);\n  display.drawBitmap(0, 5, arrow_down_icon, 16, 16 ,1);\n  display.setCursor(20, 5);\n  display.print(bme.readPressure()\/100.0F);\n  display.setTextSize(1);\n  display.print(\" hpa\");\n  display.setCursor(0, 34);\n  display.setTextSize(1);\n  display.print(\"Temperature: \");\n  display.print(bme.readTemperature());\n  display.cp437(true);\n  display.print(\" \");\n  display.write(167);\n  display.print(\"C\");\n  display.setCursor(0, 44);\n  display.setTextSize(1);\n  display.print(\"Humidity: \");\n  display.print(bme.readHumidity());\n  display.print(\" hpa\");\n  displayIndicator(displayScreenNum);\n  display.display();\n  colorWipe(strip.Color(255,   0,   255), 50, 12);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Screen Number 4: Luminosity<\/h4>\n\n\n\n<p>Finally, the last screen displays the luminosity (<span class=\"rnthl rntliteral\">displayLDR()<\/span> function).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void displayLDR(){\n  display.clearDisplay();\n  display.setTextSize(2);\n  display.drawBitmap(33, 5, sun_icon, 16, 16 ,1);\n  display.setCursor(53, 5);\n  int ldrReading = map(analogRead(ldr), 0, 4095, 100, 0);\n  display.print(ldrReading);\n  display.print(\" %\");\n  display.setTextSize(1);\n  display.setCursor(0, 34);\n  display.print(\"Temperature: \");\n  display.print(bme.readTemperature());\n  display.print(\" \");\n  display.cp437(true);\n  display.write(167);\n  display.print(\"C\");\n  display.setCursor(0, 44);\n  display.setTextSize(1);\n  display.print(\"Humidity: \");\n  display.print(bme.readHumidity());\n  display.print(\" %\");\n  display.setCursor(0, 44);\n  displayIndicator(displayScreenNum);\n  display.display();\n  int ldrReadingPer = map(ldrReading, 0, 100, 0, LED_COUNT-1);\n  colorWipe(strip.Color(255,   255,   0), 50, ldrReadingPer);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">updateScreen() function<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">updateScreen()<\/span> function calls the right functions accordingly to the screen we want to display:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void updateScreen() {\n  colorWipe(strip.Color(0, 0, 0), 1, LED_COUNT);\n  if (displayScreenNum == 0){\n    displayLocalTime();\n  }\n  else if (displayScreenNum == 1) {\n    displayTemperature();\n  }\n  else if (displayScreenNum ==2){\n    displayHumidity();\n  }\n  else if (displayScreenNum==3){\n    displayPressure();\n  }\n  else {\n    displayLDR();\n  }\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">setup()<\/h4>\n\n\n\n<p>Set the button as an input.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(buttonPin, INPUT);<\/code><\/pre>\n\n\n\n<p>Initialize the OLED display.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {\n  Serial.println(F(\"SSD1306 allocation failed\"));\n  for(;;);\n}<\/code><\/pre>\n\n\n\n<p>Initialize the BME280 sensor:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (!bme.begin(0x76)) {\n  Serial.println(\"Could not find a valid BME280 sensor, check wiring!\");\n  while (1);\n}  <\/code><\/pre>\n\n\n\n<p>When the ESP32 first starts, we want to clear the OLED display. We also set the text color to white.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>display.clearDisplay();\ndisplay.setTextColor(WHITE);<\/code><\/pre>\n\n\n\n<p>Initialize the WS2812B LEDs and set their brightness. You can change the brightness to any other value that best suits your enviroment.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>strip.begin();           \/\/ INITIALIZE NeoPixel strip object (REQUIRED)\nstrip.show();            \/\/ Turn OFF all pixels ASAP\nstrip.setBrightness(50); \/\/ Set BRIGHTNESS to about 1\/5 (max = 255)<\/code><\/pre>\n\n\n\n<p>Initialize Wi-Fi and connect the ESP32 to your local network, so that the ESP32 can connect to the NTP server to get date and time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Connect to Wi-Fi\nSerial.print(\"Connecting to \");\nSerial.println(ssid);\nWiFi.begin(ssid, password);\nwhile (WiFi.status() != WL_CONNECTED) {\n  delay(500);\n  Serial.print(\".\");\n}\nSerial.println(\"\");\nSerial.println(\"WiFi connected.\");<\/code><\/pre>\n\n\n\n<p>Configure the NTP Server with the settings defined earlier.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);\nprintLocalTime();<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">loop()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, the following lines change the screen (<span class=\"rnthl rntliteral\">displayScreenNum<\/span>) every time the pushbutton is pressed.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ read the state of the switch into a local variable\nint reading = digitalRead(buttonPin);\n\n\/\/ Change screen when the pushbutton is pressed\nif (reading != lastButtonState) {\n  lastDebounceTime = millis();\n}\n\nif ((millis() - lastDebounceTime) &gt; debounceDelay) {\n  if (reading != buttonState) {\n    buttonState = reading;\n    if (buttonState == HIGH) {\n      updateScreen();\n      Serial.println(displayScreenNum);\n      if(displayScreenNum &lt; displayScreenNumMax) {\n        displayScreenNum++;\n      }\n      else {\n        displayScreenNum = 0;\n      }\n      lastTimer = millis();\n    }\n  }\n}\nlastButtonState = reading;<\/code><\/pre>\n\n\n\n<p>The next lines change between screens every 15 seconds (<span class=\"rnthl rntliteral\">timerDelay<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if ((millis() - lastTimer) &gt; timerDelay) {\n  updateScreen();\n  Serial.println(displayScreenNum);\n  if(displayScreenNum &lt; displayScreenNumMax) {\n    displayScreenNum++;\n  }\n  else {\n    displayScreenNum = 0;\n  }\n  lastTimer = millis();\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>After uploading the code to the board, press the on-board RESET button so that the ESP32 starts running the code.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-OLED-Screen.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Weather Station Interface Project OVerview\" class=\"wp-image-100737\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-OLED-Screen.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-PCB-Weather-Station-Interface-Shield-OLED-Screen.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure>\n\n\n\n<p>For a complete demonstration, we recommend watching the following video.<\/p>\n\n\n<p style=\"text-align:center\"><iframe width=\"720\" height=\"405\" src=\"https:\/\/www.youtube.com\/embed\/_680VPayXWI?rel=0\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>We hope you&#8217;ve found this project interesting and you&#8217;re able to build it yourself. You can use PCBWay service and you&#8217;ll get a high quality PCB for your projects.<\/p>\n\n\n\n<p>You can program the ESP32 with other code suitable for your needs. You can also edit the gerber files and add other features to the PCB or other sensors.<\/p>\n\n\n\n<p>We have other similar projects that include building and designing PCBs that you may like:<\/p>\n\n\n\n<ul class=\"wp-block-list\" id=\"block-b3c06e54-c97f-4420-9271-42065e15e540\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-cam-shield-pcb-telegram\/\">ESP32-CAM with Telegram: Take Photos, Control Outputs, Request Sensor Readings and Motion Notifications<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-iot-shield-pcb-dashboard\/\">ESP32 IoT Shield PCB with Dashboard for Outputs and Sensors<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/build-an-all-in-one-esp32-weather-station-shield\/\">Build an All-in-One ESP32 Weather Station Shield<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-multisensor-shield\/\">Build a Multisensor Shield for ESP8266<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/power-saving-latching-circuit\/\">EXTREME POWER SAVING with Microcontroller External Wake Up: Latching Power PCB<\/a><\/li><\/ul>\n\n\n\n<p>Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (eBook + video course)<\/a><\/strong><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">More ESP32 tutorials and projects\u2026<\/a><\/li><\/ul>\n\n\n\n<p class=\"has-black-color has-text-color\"><strong><strong>[Update] the bare PCB giveaway ended and the winners are:<\/strong><\/strong> Etienne Bogaert, Wal Taylor, Charles Geiser, JM GIGAN and Kristian C.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this project, you&#8217;ll learn how to build a Weather Station Interface PCB Shield for the ESP32 development board. The PCB features a BME280 temperature, humidity and pressure sensor, a &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 Weather Station Interface PCB Shield (Temperature, Humidity, Pressure, Date and Time)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-weather-station-pcb\/#more-100518\" aria-label=\"Read more about ESP32 Weather Station Interface PCB Shield (Temperature, Humidity, Pressure, Date and Time)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":100764,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-100518","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/12\/ESP32-Weather-Station-Interface-PCB-Shield-Temperature-Humidity-Date-Time.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/100518","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=100518"}],"version-history":[{"count":0,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/100518\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/100764"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=100518"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=100518"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=100518"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}