WEMOS D1 Esp-Wroom-02 and Arduino IDE
|
The “WEMOS D1 Esp-Wroom-02” that I got from VNG Systems is another microcontroller development board with an ESP8266 WiFi chip. This board also has an OLED screen, 18650 battery charging circuit and a directional button built-in. This makes the board an excellent option for mobile applications. And like all the other ESP8266 based boards, this one can be programmed with the familar Arduino IDE.


WEMOS D1 Esp-Wroom-02 features
First, let’s take a closer look at the board itself. The black circuit board comes with a 10 pin header that you can solder onto it, if needed. The back of the board has a battery holder that supports flat top 18650 batteries. Other characteristics of the board are:
- Board size: 102x30x20mm
- Voltage Input range: 5V-12V
- Micro USB connection
- Charge Current: 500 mA
- Battery overcharging and overdischarging protection circuit
I found that the information about the board published online usually is incorrect.. For instance, the name of the board implies that it is fitted with the ESP-WROOM-02 WiFi chip. Instead, it has an ESP-12E/F module. Also, most of the sites mention the wrong OLED-libraries and GPIO pinouts. So below I will write about my own findings and experiences.
Wemos D1 Esp-Wroom-02 Inputs and outputs
On the board there are the following inputs and outputs available:
- 1 Analog input AD (A0)
- 5 Digital inputs/outputs with interrupt/PWM/I2C/one-wire support D3 (GPIO0), D4 (GPIO2), D8 (GPIO15), D9 (GPIO3), D10 (GPIO1)
Built-in LEDs
The description states that the board has one programmable LED, on pin D0. But I found that the board has 2 programmable LEDs. One is the blue LED on the ESP8266 module, the other one is an additional green led on the breakout board.
- Programmable blue LED on GPIO2 (LED_BUILTIN)
- Programmable green LED on GPIO16
OLED screen
The built-in OLED screen has the following specifications:
- Controller: SSD1306
- Resolution: 128 x 64 pixels, size: 0.96 Inch, color: White
- I2C (GPIO5: SDA; GPIO4: SCL)
- Address: 0x3C
It can be used with the ThingPulse ESP8266 OLED SSD1306 library.
Directional button
The board has a built-in directional button which supports 5 functions:
- Up (GPIO13), Down (GPIO12)
- Left (RESET) , Right (GPIO0)
- Push (GPIO14)
Unfortunately, the left direction contact of the button is hardwired to the RESET pin of the ESP8266, so this can not be changed without modifying the board.
GPIO summary
Summarizing, I found the GPIOs of the ESP are wired as follows:
GPIO | Function |
0 | D3 / Button right |
1 | D10 |
2 | D4 / LED blue (LED_BUILTIN) |
3 | D9 |
4 | OLED SCL |
5 | OLED SDA |
12 | Button down |
13 | Button up |
14 | Button push |
15 | D8 |
16 | LED green |
A0 | AD (ADC) |
18650 Battery holder
The battery holder supports a single flat top 18650 cell. The charging circuit will protect your battery from overcharging and also overdischarging. Warning: the circuit does not have reversed polarity protection. So be aware to insert the battery the right way. If you insert it reversed, then your board will be damaged. The polarity is indicated by a + and – printed on the board. The charging circuit has two LED indicators: the green LED indicates charging, the red LED (“standby”) lights up when there is power but the battery is not charging. When you upload a sketch to the ESP-Wroom-02, you have to remove the battery first, and set the power switch to the “ON” position.
Using the Wemos Esp-Wroom-02 with the Arduino IDE
First, you need to have the Arduino IDE installed on your computer. For Windows 10 users, check out the blog post “Installing the Arduino IDE on Windows 10” on how to do that. Linux users should see the blog post “Install or upgrade to the latest Arduino IDE on Linux“.
Second, you need to have the “Arduino core for ESP8266 WiFi chip” installed in your Arduino IDE. See the section “Installing the ESP8266 Arduino core” in the blog post “ESP8266 NodeMcu and Arduino IDE on Linux“. This procedure is the same for both Windows and Linux.
Third, select an appropriate ESP8266-based board in de Arduino IDE. For me, the selection “WeMos D1 R1” worked fine. See the picture below for the settings that I used.


Fourth, you need to install the OLED library. You can download the ThingPulse ESP8266 OLED SSD1306 library directly from GitHub or install it using the Arduino IDE library manager. See the image below.


Finally, you should install the Brzo I2C Library (https://github.com/pasko-zh/brzo_i2c) in the same way: go to Sketch > Use Library > Manage Libraries > Search for “Brzo I2C” and choose “install”.
Now, you can test your Esp-Wroom-02 board with the demo sketch below. When the button is pressed, the OLED screen will show the direction of the button. It also displays the value of the analog input, It will change when you touch it with your finger.
/** GPIO 0 - Button right / D3 GPIO 1 - D10 GPIO 2 - LED blue (LED_BUILTIN) / D4 GPIO 3 - D9 GPIO 4 - OLED SCL GPIO 5 - OLED SDA GPIO 12 - Button down GPIO 13 - Button up GPIO 14 - Button push GPIO 15 - D8 GPIO 16 - LED green GPIO A0 - ADC **/ #include "SSD1306Brzo.h" // Include OLED Library SSD1306Brzo display(0x3c, 5, 4); // Initialize OLED display int blueLed = LED_BUILTIN; // Blue LED is on GPIO 2 (LED_BUILTIN) int greenLed = 16; // Green LED is on GPIO 16 int analogPin = A0; // Analog input is A0 int analogValue = 0; volatile byte state = LOW; String button = "Waiting..."; void setup() { display.init(); // Initialise the display pinMode(blueLed, OUTPUT); // Initialize digital pin LED_BUILTIN as an output. pinMode(greenLed, OUTPUT); // initialize digital pin 16 as an output. pinMode(0, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(0), interrupt0, HIGH); // Right pinMode(12, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(12), interrupt12, HIGH); // Down pinMode(13, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(13), interrupt13, HIGH); // Up pinMode(14, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(14), interrupt14, HIGH); // Push } void drawText() { // Fuction to draw the text display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_16); display.drawString(0, 0, "Button:"); display.setFont(ArialMT_Plain_24); display.drawString(0, 16, button); // Print button press display.setFont(ArialMT_Plain_16); analogValue = analogRead(analogPin); display.drawString(0, 48, "ADC: " + String(analogValue)); // Print value of analog input } void interrupt0() // Right { button = "Right"; blink(); } void interrupt12() // Down { button = "Down"; blink(); } void interrupt13() // Up { button = "Up"; blink(); } void interrupt14() // Push { button = "Push"; blink(); } void blink() { state = !state; // Reverse LED state } void loop() { display.clear(); // Clear OLED display drawText(); // Draw the text display.display(); // Write the buffer to the display digitalWrite(blueLed, state); // Turn the blue LED on/off digitalWrite(greenLed, !state); // Turn the green LED on/off }
I think you forgot to mention the use of https://github.com/pasko-zh/brzo_i2c
You are right Sebastian, I have updated the blog post. Thanks for pointing it out!
There was an interrupt issue that continually reset the ESP8266. I have added in the fixes below:
/**
GPIO 0 – Button right / D3
GPIO 1 – D10
GPIO 2 – LED blue (LED_BUILTIN) / D4
GPIO 3 – D9
GPIO 4 – OLED SCL
GPIO 5 – OLED SDA
GPIO 12 – Button down
GPIO 13 – Button up
GPIO 14 – Button push
GPIO 15 – D8
GPIO 16 – LED green
GPIO A0 – ADC
**/
#include “SSD1306Brzo.h” // Include OLED Library
SSD1306Brzo display(0x3c, 5, 4); // Initialize OLED display
int blueLed = LED_BUILTIN; // Blue LED is on GPIO 2 (LED_BUILTIN)
int greenLed = 16; // Green LED is on GPIO 16
int analogPin = A0; // Analog input is A0
int analogValue = 0;
volatile byte state = LOW;
String button = “Waiting…”;
void drawText() { // Fuction to draw the text
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, “Button:”);
display.setFont(ArialMT_Plain_24);
display.drawString(0, 16, button); // Print button press
display.setFont(ArialMT_Plain_16);
analogValue = analogRead(analogPin);
display.drawString(0, 48, “ADC: ” + String(analogValue)); // Print value of analog input
}
void ICACHE_RAM_ATTR interrupt0() // Right
{
button = “Right”;
blink();
}
void ICACHE_RAM_ATTR interrupt12() // Down
{
button = “Down”;
blink();
}
void ICACHE_RAM_ATTR interrupt13() // Up
{
button = “Up”;
blink();
}
void ICACHE_RAM_ATTR interrupt14() // Push
{
button = “Push”;
blink();
}
void blink() {
state = !state; // Reverse LED state
}
void setup() {
display.init(); // Initialise the display
pinMode(blueLed, OUTPUT); // Initialize digital pin LED_BUILTIN as an output.
pinMode(greenLed, OUTPUT); // initialize digital pin 16 as an output.
pinMode(0, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(0), interrupt0, FALLING); // Right
pinMode(12, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(12), interrupt12, FALLING); // Down
pinMode(13, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(13), interrupt13, FALLING); // Up
pinMode(14, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(14), interrupt14, FALLING); // Push
//interrupts();
}
void loop() {
display.clear(); // Clear OLED display
drawText(); // Draw the text
display.display(); // Write the buffer to the display
digitalWrite(blueLed, state); // Turn the blue LED on/off
digitalWrite(greenLed, !state); // Turn the green LED on/off
}
Thank you and the author.
I spent an embarrassing amount of time trying to figure out what was going on with my board and trying to find a solution online. Everything seemed to be fine but I now see I did a couple small things wrong.
I’m glad you solved your problem!
Can you tell us what the problem was and how you solved it? Maybe it can help someone else in the future 🙂
Thank you James. You code works perfectly. The author of this post should change his code to yours.
The only pin I can make OneWire to work is the D8 (GPIO 15). When trying D9 and D10 (GPIO3 and GPIO1) it’s not working.
how can I connect to GPIO 4 – SCL GPIO 5 – SDA with BME280? The pins are not visible.
Hi Mauro,
Those two pins are used internally for the OLED screen.
The only GPIOs that are broken it to the pin header are:
-1 Analog input AD (A0)
-5 Digital inputs/outputs D3 (GPIO0), D4 (GPIO2), D8 (GPIO15), D9 (GPIO3), D10 (GPIO1)
is there no way to intercept them? for example directly on wemos? it is wasteful if the i2c bus cannot be used
I guess you could do that, but wouldn’t it be easier to just choose some other type of development board?
The board is very useful because it already has the OLED and the battery, this is why people want to use it specifically and not buy different ones in order to achieve the result.
So people want to use it for other projects not just deauther this is why people ask questions about how to add extra I2C devices to it
Unless you are running out of pins. Using wire.begin(D3, D4) is easier. Of course, one can solder two wires to D1 and D2 on the 8266 directly.
Question: What is the meaning of the Red and Green LED? According to this article, the Red LED indicates Charging is in Process; the Green LED indicates Charging is completed. As soon as I plugged the USB cable to the module with the Switch in OFF position, the Green LED turns ON. I know the battery is not fully charged!
Thanks for pointing out the error! The green LED is connected to the “CHRG” pin of the TP5410 chip, and the red LED to the “STDBY”.
So, the green one will light up when the battery is charging, and the red one when there is power but no charging going on.
I suggested earlier to use D3, D4 for the 2nd I2C port. Here is how I made it works. You need to call Wire.begin() prior to accessing the device. Hope this helps.
——————————————————————–
void readRTC()
{
Wire.begin(0, 2); //D3, D4
DateTime now = rtc.now();
ye = now.year(); mo = now.month(); da = now.day();
dow = now.dayOfTheWeek();
ho = now.hour(); mi = now.minute(); se = now.second();
}
——————————————————————–
void send2OLED()
{
Wire.begin(5, 4); //D1, D2
display.clear();
hms = String(ho)+ “:” + String(mi) + “:” + String(se);
display.drawString(10, 10, hms);display.display();
}
Do you have a schematic of this board? After I ran the “test all” sketch, I found the “joystick” of one of my boards does not work. Please share if you have it.
I flashed Tasmota on my board for a swimming pool temperature meter application to be used with DS18B20 sensor.
I haven’t been able to get the Deep Sleep feature to work though. Has anybody here had any luck?
I bridged D0 and RESET, and soldered a 10k resistor from RESET to 3.3V as described here:
https://tasmota.github.io/docs/DeepSleep/
I am looking into something similar right now, but for use in a grow house. Only had a DHT11 sensor at home, but that will do for now. I think I have gotten deep sleep to work now, not sure how much power it is using though. It took a lot of testing and these are the important parts:
Soldering – Just left of the USB connector there were two solder points without a resistor. These needs to be soldered together. I suspect these are connecting GPIO16 (which have the green led) with RST.
GPIO16 – The example on this page is not working properly, but the one James wrote does. But very important for deep sleep to work, do not set GPIO16 as an output. Don’t set it at all. If you do, you will reset the device when you don’t expect to.
Code – In the end of loop put his to sleep for 10 minutes:
ESP.deepSleep(10 * 60e6);
The green led blinks about every 1-2 seconds.
When the device wakes up it will be done through a reset so all initialization will happen like you just turned it on, connecting to WiFi and so on.
Choice of GPIO – First of all, the defined pin names in Arduino IDE does not align with the pins in this unit. Better use the GPIO number when defining pins.
When I connected the DHT11 signal to D8 (15) or D9 (3) I could not flash the device without disconnecting the cable. If I instead choose D10 (1) it was possible to keep the cable connected.
Hope this information helps.