Most likely cause
You are hitting an insidious problem that even experienced C++ programmers frequently miss: order of initialization of global variables. In your case, Display lcd is initialized (i.e., its constructor is called) before main() and subsequently setup() are executed. However, you almost certainly are #includeing whatever library is declaring the LiquidCrystal_I2C class, probably Wire.h, and so on. In many of these classes, a global variable of that type is also defined to make it easier to access stuff. For example, Serial (as in Serial.println("foo")) is really a global variable of the appropriate type of whatever serial implementation your particular core is using.
The problem you are hitting is that the C++ standard does not guarantee the execution order of the constructors of global variables. The order is an artifact of the compiler, the order in which object files were linked, and probably the phase of the moon :)
What is (almost certainly) happening is that the constructor for your class Display is being called, which initializes the LCD and the i2c bus, and then something else calls either the LCD constructor or the i2c constructor and messes things up.
OK, "how do I fix this?" I hear you ask. Simple: make the global lcd variable a pointer, and allocate the instance in begin(), like so:
#include "Display.h"
Display *lcd;
void setup() {
Serial.begin(9600);
lcd = new Display();
// stuff
}
void loop() {
// more stuff
lcd->some_method(some_argument);
// even more stuff
}
Now you are guaranteed that your code will be the last to touch any initialization code that might affect the display or the bus. Just keep accessing the class Display methods through the pointer.
A less likely cause
It is still possible that your constructors are getting executed in the right order, but your hardware does not like being initialized twice (but test that anyway!), so you may have to figure out how to reset the hardware so you can initialize it again. If I understand your posting correctly, the loop never runs, which means that a second initialization probably either causes a exception (which you would not see unless you had some kind of additional debugging channel; in the case of the ESP8266, for example, that would be the output-only Serial1 port, and even then, you'd have to explicitly turn on debugging. Each core has its own debugging stuff, I forget what the real Arduino does.)
Hope this helps.
/ji
_lcd = new LiquidCrystal_I2C(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);_lcd->begin(20, 4);– Natalia Kelim Thiel Apr 15 '16 at 20:05