I know it is a no - no to call functions from the constructor that rely on init() having already run. So things like pinMode and digitalWrite should be in a begin method somewhere.
So I always thought that is exactly what happened with something like the stock LiquidCrystal library. But no. Upon closer inspection, the constructor calls the LiquidCrystal::init() function which calls pinMode all over the place and then calls begin(16,1). SO if you have a 16 x 1 display, you wouldn't even have to call begin because the constructor calls it!
How does that work? Is just moving it out of the constructor proper and into a function called by the constructor enough to pass?
Not at all, however glancing through init seems to indicate that it doesn't affect pin modes one way or the other. It would probably be correct to say that timer functions (eg. millis or delay) and ADC functions won't work before init() is called because it sets things up for them.
The stock library shouldn't really do that, its likely to come a cropper when ported to
some new hardware because of the assumption. Luck not judgement is the reason it
works I suspect!
The LCD library is badly written. It should not be calling pinMode in the constructor, and in particular it should not be trying to initialize the LCD in the constructor, because the power may not yet have stabilised and the LCD may not be ready. I use a modified version of the LCD library in which the constructor does not call the begin method (and I have made a few other changes too).
dc42:
and in particular it should not be trying to initialize the LCD in the constructor, because the power may not yet have stabilised and the LCD may not be ready.
There is a 50ms delay hanging out in there and a comment that goes with it that claims that it is for just that reason.
I'm modifying that library right now to use a shift register to drive all the pins so I can use SPI with it. I need my pins back. I thought I would just have to modify the virtual parts. But when I got to that part I started thinking I might be making much bigger modifications. The project it is going in has to call an init() function for about 12 different classes in setup(). I can't imagine one more would be an issue.
dc42:
and in particular it should not be trying to initialize the LCD in the constructor, because the power may not yet have stabilised and the LCD may not be ready.
There is a 50ms delay hanging out in there and a comment that goes with it that claims that it is for just that reason.
50ms is an arbitrary value. If the begin() call is removed from the constructor, then the user can choose how much delay (if any) to use before calling begin().
F Malpartida's Liquid Crystal library?.. It does handle several different serial implementations.. I use the one for the I2C implementation using a PCF8574. It is more than fast enough for my purposes..
dc42:
and in particular it should not be trying to initialize the LCD in the constructor, because the power may not yet have stabilised and the LCD may not be ready.
There is a 50ms delay hanging out in there and a comment that goes with it that claims that it is for just that reason.
50ms is an arbitrary value. If the begin() call is removed from the constructor, then the user can choose how much delay (if any) to use before calling begin().
I agree 100%. That's why I think the library I'm writing I will change so that begin calls init at the very beginning and init doesn't call begin. Then nothing happens with that class other than variable assignments until I call the begin method. Then it will run init and begin. Once I am good and ready.