Wemos: 16x2 display doens't show anything

Hello.

I connected a 16x2 LCD display to a Arduino Uno. Then I tested a “Hello, Word” code and it works perfect. Now I want to do the same with a Wemos D1 Mini but it doesn’t work.

Here is the project:

This os the “Hello, World” code. I needed to change the name of the pins (maybe this is the problem):

#include <LiquidCrystal.h>

const int rs = 8, en = 7, d4 = D5, d5 = D4, d6 = D3, d7 = D2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  lcd.begin(16, 2);
  lcd.print("hello, world!");
}

void loop() {
  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);
}

This is the result (potentiometer works perfect):

I have many sensors and components that I use for Arduino and I am testin everyone with Wemos but now I got stack
.
Thank you,

Roberto

How is it getting power if you are not using USB?

The picture number 3 shows the Wemos is connected.

robysottini:
The picture number 3 shows the Wemos is connected.

The original post - which was edited - said that the Wemos was not connected.

I'm assuming the use of raw pin #s for rs and en are a oops/mistake:

const int rs = 8, en = 7, d4 = D5, d5 = D4, d6 = D3, d7 = D2;

If you want Arduino digital pin 8 and digital pin7 (vs bit 8 and bit 7 of the output port register, then you need to use the esp8266 pin defines:

const int rs = D8, en = D7, d4 = D5, d5 = D4, d6 = D3, d7 = D2;

If that doesn't fix it, then it is possible that the library is causing a watchdog timeout.
Bring up the serial monitor in the IDE.
If a watchdog is happing, the wemos will spit out characters on the serial port usually at 115200 baud.

If you have a watchdog issue you will either have to fix the library to not do long delays.
Or use another library that works with esp8266 like the hd44780 library.

--- bill

If the 1602 display is a 5volt version, you may have a problem on a basically 3volt device (such as Wemos) with the contrast setting, making the characters invisible, depending on how you have wired it.

I corrected to this but the problem is still there:

const int rs = D8, en = D7, d4 = D5, d5 = D4, d6 = D3, d7 = D2;

Also I connected to 3.3v (before was connected to 5v): I can change the contrast with the potentiometer. So the LCD (and contrast) and the potentiometer work.

I search in Google for a schematic or picture for this simple circuit, but there is nothing: I just need to connect a 16x2 LCD to a Wemos. Do you have a example?

Thanks.

If the contrast "works" when you connect LCD_VCC to 3.3V you must have a 3.3V display. The pcb will have some "extra" components mounted. Regular 16x2 have some empty footprints.
If it only "works" with 5V, you have a regular 16x2.

Your wiring "looks" ok. You still need to test all your jumper wires for continuity.

Since you say the LCD display is ok with a Uno, just swap all the wires over to the Uno to confirm.

David.

From the photos you posted, the wiring you have looks correct as long as you are using:

const int rs = D8, en = D7, d4 = D5, d5 = D4, d6 = D3, d7 = D2;

Did you check the serial port to see if a watchdog is happening?
This is an important test if you using the LiquidCrystal library.
You need to do this test to verify that you are not having a watch dog issue.
If you have a watchdog issue, it will mimick the symptoms you are seeing as the watchdog will happen in the init() code which is called by begin() and the LCD will not get initalized and the processor will hang.
The hd44780 library will not have this watch dog issue but it does have another potential issue that the LiquidCrytal library may have as well in this environment.

In terms of 5v vs 3v.

There can be two issues:

  1. using 3v
    While using a 5V LCD at 3v will usually work, it may not provide a proper contrast signal.
    If used for the backlight it may not work or be a bit too dim and it might overload the 3v output on the wemos.
    Since most LCDs have separate power for the backlight and the rest of the LCD,
    I would wire the backlight up to 5v as that should be brighter and it will reduce the load on the 3v pin on the wemos.

  2. using 5v for the LCD logic (lcd module pin 2 & contrast pot)
    is using 5v inputs with 3v wemos outputs which can have issues since it is out of spec for the LCD inputs.
    It won’t cause damage to the wemos but the LCD may have issues seeing HIGH signals.

I tested a Linknode D1, which is an UNO form factor esp board with both LiquidCrystal and my hd44780 library and a LCD keypad shield.
With this setup the LCD and backlight are using 5v.

It appeared to work with the LiquidCrystal library but initially had issues with my hd44780 library.
Using 3v outputs with a 5v device is using signals that are out of spec.
However, this can and usually does work for LCDs. I have done this many times with many different processors.
I did run into an issue with the hd4478 library.
The issue I saw is slew rate of signals. i.e. it takes a while for the 3v signals to reach their full 3v level which is needed to be seen as HIGH by the LCD and it can be longer than the time before the E signal is dropped by the library. It was an issue with my hd44780 library which is a bit faster than the LiquidCrystal library.
This is not a timing issue with the LCD chip set but rather is an artifact of using signals that are out of spec.
This slew rate timing can also be affected by the length and type of wires.

After this test I put in an extra microsecond delay to allow signals to settle for esp8266 modules.
This update will be in the next release of the hd44780 library.
Without this update, the LCD would kind of work but the display would experience data corruption.

Give us an update on whether the board is experiencing a watchdog timeout.
That will provide more information on where the problem may be.

You could try the hd44780 library using the hd44780_pinIO class, but you will need to put in a small patch to get reliable data on the LCD.

— bill

@bperrybap, I am having a watch dog issue as you described. I can’t find any tutorials online for hooking up the Wemos D1 mini to an LCD without a backpack. I have successfully used my LCD with the same code on an Arduino Uno, but I’m having an issue now with my D1 mini.

#include <LiquidCrystal.h>
const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup()
{
  Serial.begin(115200);
  Serial.printf("starting...");
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print("hello");
}

void loop()
{   
  Serial.printf("hello");
  delay(1000);
}

I have narrowed down my issue to the 3rd line. If I block out the LiquidCrystal lcd line, then I can print to Serial just fine. But if I include the 3rd line, then I get the following error in my Serial output:

ets Jan  8 2013,rst cause:4, boot mode:(1,6)

wdt reset

Does this mean I’m unable to use the LiquidCrystal library with my D1 mini? How do I fix this issue without an LCD backpack? I’m using the BL1602P LCD and I’m powering the LCD with an external 5v supply. Thanks for the help.

On a related note, my goal to display temperatures from a DS18B20 temperature probe on the LCD screen with the D1 mini. This requires the OneWire and DallasTemperature libraries. It looks like the OneWire instantiation causes the same issue as above:

#include <OneWire.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);

This gives the same error as above except with boot mode:(1,7). How are these issues related and can I fix this one as well?

The latest code in post # 9 doesn't fill in the constructor parameters properly so who knows what is happening since you are not initializing the library with the proper pin information.
I explained about the pin numbers vs pin symbols in post #4.
In post #6 you seemed to be using the Dn pin symbols, but the
latest code in post #9 ignores the pin number requirements by not using the Dn symbols.

Summarizing again from post #4:
Naked Arduino pin #s on the D1 mini are GPIO bit numbers.
The labels on that are on the board are the Dn symbols not GPIO bit numbers.
The Dn symbols are used to map to GPIO bit numbers.
pin Dn is not the same physical pin as pin n
If you want to use the physical pin as labeled on the PCB, you must use the Dn symbols as those are needed to match the labels printed labels on the PCB.

Not sure if there will still be watchdog timeout with the LiquidCrystal library if you use the proper pins but for sure you need to use the Dn symbols to make sure you are using the proper physical pins.

If it still has watchdog issues, you could switch to using my hd44780 library and the hd44780_pinIO class.
It has been tested with the esp8266 core.
But if you do switch to hd44780 and hd44780_pinIO, you will also have to make sure to use the Dn numbers in the constructor.

Basically, when using that board, you should be using Dn pin symbols.

--- bill

Thanks for the quick reply. I think I understand - I need to replace the variables that I feed to the lcd constructor with proper D# formatted inputs? Is this correct? The variable names in the constructor correspond to where they connect on the LCD and their declarations (D#) correspond to where they connect on the D1 mini. So I don't need to declare pin numbers at all, just their labels (D#)? If I implement this code, I get my serial prints perfectly fine, but still nothing is printed out to the LCD screen.

const int rs = D7, en = D6, d4 = D5, d5 = D4, d6 = D3, d7 = D2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

I have also tried these variations:

const int rs = 7, en = 6, d4 = 5, d5 = 17, d6 = 18, d7 = 19;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

using the pin numbers from here, and this variation:

#define D2 19
#define D3 18
#define D4 17
#define D5 5
#define D6 6
#define D7 7
const int rs = D7, en = D6, d4 = D5, d5 = D4, d6 = D3, d7 = D2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

Both of these variations gave me watch dog errors.

Also, I know it's unrelated to LCDs, but could you read what I added to the end of post #9? I got a similar watch dog issue in my serial output by using the OneWire library. Thanks for your help!

What esp8266 board type are you using?

sgpk242:
Thanks for the quick reply. I think I understand - I need to replace the variables that I feed to the lcd constructor with proper D# formatted inputs? Is this correct?

Not really.
You need to assign values to the variables using the Dn symbols
which is what this is doing:

const int rs = D7, en = D6, d4 = D5, d5 = D4, d6 = D3, d7 = D2;

The variable names in the constructor correspond to where they connect on the LCD and their declarations (D#) correspond to where they connect on the D1 mini. So I don't need to declare pin numbers at all, just their labels (D#)? If I implement this code, I get my serial prints perfectly fine, but still nothing is printed out to the LCD screen.

I'm not following what you are saying.
The parameters in the constructor tell the library how the pins are wired to the LCD.
What matters is the order.
The 1st parameter says what Arduino pin is used for controlling RS
The 2nd parameter says what Arduino pin is used for controlling E
etc....
In order to use the pin as labeled on the PCB you must use the predefined Dn symbols.

const int rs = D7, en = D6, d4 = D5, d5 = D4, d6 = D3, d7 = D2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

That set of pins does not match what you showed in photos in the first post.
Have you changed how you have the LCD wired up?

I have also tried these variations:

Why? You already know they won't work as they will be using the wrong pins since they are using GPIO bit numbers instead of the pin as labeled on the PCB.

I just tested the IDE bundled LiquidCrystal library HelloWorld sketch on a LinkNode board which uses the "Wemos D1 R1" board type and it works ok.
So there does not appear to be a LiquidCrystal library issue in its initialization code.

--- bill

Looking at picture #1 it appears that you have a purple wire going from:

LCD pin d6 -> Wemos Mini pin labeled D6.

Wemos Mini D6 is GPIO12 which, for the Arduino Core, is pin 12 (ie not 6 )

In the various code snippets, I do not see 12 anywhere and this table from an earlier post would therefore appear to be incorrect :

#define D2 19
#define D3 18
#define D4 17
#define D5 5
#define D6 6
#define D7 7
const int rs = D7, en = D6, d4 = D5, d5 = D4, d6 = D3, d7 = D2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

Have a look here for Wemos mini D1/ Arduino pin mapping:

Instead of supplying photos of your layout, draw a diagram which showing all the interconnections and labeling the pins and post that.

6v6gt:
Looking at picture #1 it appears that you have a purple wire going from:

LCD pin d6 -> Wemos Mini pin labeled D6.

Wemos Mini D6 is GPIO12 which, for the Arduino Core, is pin 12 (ie not 6 )

But when building for the WeMos d1 mini board, the Arduino Core is not used.
For that board, the esp8266 core is used with the d1_mini variant.

In the various code snippets, I do not see 12 anywhere and this table from an earlier post would therefore appear to be incorrect :

Not only is it incorrect but creating those Dn defines should not be done.
A sketch should not be attempting to alter the pin mapping Dn defines supplied in the variant file.

Instead of supplying photos of your layout, draw a diagram which showing all the interconnections and labeling the pins and post that.

A photo is actually much better as it will be the actual wiring vs a drawing of the intended wiring.
For cases where the LCD is not working, a supplied drawing is often incorrect as it represents what was intended vs what was actually done.
And there are many many threads on the forum where the op fully believes that he has wired it up according to his diagram, but when finally looking at actual photos it turns out not to be the case.
Incorrect wiring, or wiring that does not match the pins specified in the constructor is the most common cause of the LCD not working.

In post #8 I provided the variable assignments for the variables used in the constructor that matched the photo.
None of what has been shown in any the posts so far have used the pins as shown in the original photos.
So if it is wired up as shown in the photos then it is guaranteed not to work given the code samples shown so far are passing pins to the library in the constructor that have not matched the actual wiring.

IMO, the problem here is that the wrong pins keep being specified in the constructor.
When using the WeMos D1 mini, Dn symbols supplied in the variant file should be used.
To use anything else, like naked Arduino pin #s, is messy and very subject to error as you have to look at the variant file to determine what naked pin # corresponds to each Dn pin symbol define.
And for sure the Dn defines should not be messed with in the sketch.
For that board (WeMos D1 mini) the Dn symbols are supplied by the d1_mini variant file and should be used to ensure that the physical pin used matches the label printed on the PCB.
i.e. if you see Dn on the PCB use Dn for your pin. D1 means use D1, D2 use D2 etc...

It isn't that complicated. Wire up the LCD using any of the Dn pins, and then fill in the constructor accordingly using the Dn symbols or use variables that are assigned values using the Dn symbols.
The key is that for that board, the Dn symbols should be used and will make wiring and configuring the library quick and easy.

-- bill

I appreciate both of your replies. However, I am not the original poster. I think I have different wiring than the original poster. I entered this conversation with Post #9. Bill, what you said about the Dn notation finally makes sense - I understand now that when working with the D1 mini, I have to use the Dn notation and not the supposed pin numbers like with Arduino. I have attached a diagram of my wiring, the actual wiring is messy and I don’t think you’d be able to read it from a picture. This is the setup that I’m working with that has worked with the Arduino Uno. Code below. I still don’t understand what I’m doing wrong with the lcd constructor.

#include <LiquidCrystal.h>

const int rs = D7, en = D6, d4 = D5, d5 = D4, d6 = D3, d7 = D2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

long start;

void setup(void)
{
  Serial.begin(115200);
  Serial.println("starting...");
  lcd.begin(16, 2);
  start = millis();
}

void loop(void)
{   
  lcd.setCursor(0, 0);
  lcd.print(start);
}

If nothing is wrong with my diagram and my code, then I will go back and double check my wiring.

Your Fritzing matches the constructor. However I would expect the Wemos to be connected to VCC and GND.

A photo of real life would let other eyes compare with the Fritzing.
Wires and breadboards can have broken connections.

David.

sgpk242:
Bill, what you said about the Dn notation finally makes sense - I understand now that when working with the D1 mini, I have to use the Dn notation and not the supposed pin numbers like with Arduino.

You can use naked pin numbers. The issue is that the naked pin numbers will not match the Dn number printed on PCB.
For example to use the pin labeled D1 you would use 5, to use the pin labeled D5 you would use 14, to use D2 you would use 4.

IMO, it isn’t worth doing the work of looking in the variant file for the naked pin number.
It is much easier to just use the Dn symbol which matches the label on the PCB.
This is similar to the Analog symbols on an UNO or Mega boards
You can use 14 instead of A0 on an UNO or 54 on a mega board,
but it is easier to use A0 as that is how the board is labeled.

In terms of what can cause a watchdog, it could be the actual pins you are using.
You have be careful if you are using GPIO0, GPIO2, and GPIO15 as those control the power up boot sequence in the ESP8266.
Those are D3, D4, and D8 on that board.

See this unrelated post for a bit more about how these pins affect the powerup reset sequence:

— bill

OK. I didn't notice that the thread concerned two different installations, hence the confusion.

I have also learned something from this that it is possible to use directly the "Node MCU" type board labeling (D2 etc.) directly in the sketch. I normally use the Adafruit Huzzah breakouts or the raw ESP8266 modules which use a different marking system. On the odd occasion where I have used a NodeMCU clone, I have referred to a pinout mapping diagram for the Arduino pin numbers.

I did a quick check looking at the image search results from the search string "Wemos mini lcd 1602" and "NodeMCU lcd 1602". Not surprisingly, I saw only circuits using the I2C backpack in combination with the LCD 1602. I guess that is due to the limited number of pins available on these ESP8266 breakouts and the low cost and ease of use of the I2C backpacks. That is the route I'd also recommend here so that the OP (#2) has at least a few pins left for other devices.

https://www.ebay.com/itm/IIC-I2C-TWI-SP-I-Serial-Interface-Board-Module-Arduino-1602-2004-LCD-Display/310565362720

Hello Roberto,

its a bit late but :

i just try a few minutes ago with a Wemos D1 mini and it works like a charm.

Just replace the pin by Dx :

#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = D4, en = D3, d4 = D8, d5 = D7, d6 = D6, d7 = D5;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
}

void loop() {
  // set the cursor to (0,0):
  lcd.setCursor(0, 0);
  // print from 0 to 9:
  for (int thisChar = 0; thisChar < 10; thisChar++) {
    lcd.print(thisChar);
    delay(500);
  }

  // set the cursor to (16,1):
  lcd.setCursor(16, 1);
  // set the display to automatically scroll:
  lcd.autoscroll();
  // print from 0 to 9:
  for (int thisChar = 0; thisChar < 10; thisChar++) {
    lcd.print(thisChar);
    delay(500);
  }
  // turn off automatic scrolling
  lcd.noAutoscroll();

  // clear screen for the next loop:
  lcd.clear();
}