The problem with this approach is that we cannot check for compatibility of the Nextion component and function (for example sending text to a Nextion component that has no text).
The other approach is to use classes:
void terminate_packet() {
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}
class Base {
protected:
char const* name;
Base(char const* n) : name{n} {}
};
class Color : virtual public Base {
using Base::Base;
public:
void setColor(unsigned color) {
Serial.print(name);
Serial.print(".color=");
Serial.print(color);
terminate_packet();
}
};
class Text : public virtual Base {
using Base::Base;
public:
void setText(char const* text) {
Serial.print(name);
Serial.print(".txt=\"");
Serial.print(text);
Serial.print("\"");
terminate_packet();
}
};
class NexButton : public Color , public Text, public Font {
public:
NexButton(char const* n) : Base(n), Color(n), Text(n), Font{n} {}
};
I prefer the object approach as it is more intuitive and type safe; however my issue with it is that the objects are created and destroyed in each loop cycle; which I presume would have significant overhead. How could I only create the objects once when needed and destroy them once we no longer need them (like switching pages on the Nextion, create and destroy component objects once per page switch). How could I achieve this without using static or global variables?
ningaman151:
The problem with this approach is that we cannot check for compatibility of the Nextion component and function (for example sending text to a Nextion component that has no text).
Is someone going to power the device off, swap displays, then power the device on?
gcjr:
i'm curious why you think the object approach is more intuitive or what makes it more
Because it makes the link between an Object on the Arduino and the Nextion components; as if the Nextion component is in the Arduino.
gcjr:
and what makes it "type safe"? why would that be important
Let me give you an example:
Say we have a class NexButton that inherits from Color and Text. We make an instance of that class, and we call the methods we gained from inheriting Color and Text. All good for now. Now if we try to call methods from the Font class we get an error; as NexButton doesn't inherit from Font. This way we can make sure we're not sending illegal data to the display. It also makes it easier to debug as with the function approach you could send illegal data and not be aware of it.
appreciate the explanation, but they don't make sense to me. i believe well written object oriented code could be implemented more understandably. i don't believe the abstraction is necessary on a project that fits on an arduino.
NexButton button_1{"b0"}; //object is created at the beginning of the loop
button_1.setText("button text");
} //button_1 object is destroyed
Just because you're doing it wrong does not mean it HAS to be done wrong. Make the Nextion objects global. and they will exist for the life of the program. loop() then only needs to change whatever needs to change on each pass of loop().
Look at how it's done in ANY of the Nextion example applications.
RayLivingston:
Just because you're doing it wrong does not mean it HAS to be done wrong. Make the Nextion objects global. and they will exist for the life of the program. loop() then only needs to change whatever needs to change on each pass of loop().
Look at how it's done in ANY of the Nextion example applications.
I specifically said I don't want to use global or static variables. But I guess there's no other way. Functions method it is then.
You're not accomplishing that. In fact, just the opposite, especially if you create and destroy all the Nextion objects on every pass of loop(). Dynamic allocation consumes MORE RAM than static allocation, because in addition to the RAM occupied by the object itself, EVERY dynamically-allocated object created will have a memory block descriptor, typically 4-8 bytes of RAM (depending on the platform), attached to it, to track the size and location of that memory descriptor. So that restriction will use MORE RAM, not LESS, in addition to making the entire program slower, and just less usable.
RayLivingston:
You're not accomplishing that. In fact, just the opposite, especially if you create and destroy all the Nextion objects on every pass of loop(). Dynamic allocation consumes MORE RAM than static allocation, because in addition to the RAM occupied by the object itself, EVERY dynamically-allocated object created will have a memory block descriptor, typically 4-8 bytes of RAM (depending on the platform), attached to it, to track the size and location of that memory descriptor. So that restriction will use MORE RAM, not LESS, in addition to making the entire program slower, and just less usable.
I was talking about the use of global and static variables in general. Especially when compared to the function method. I know that the loop method is bad.
I tried writing a program once where I couldn't use the = sign. That didn't turn out very well either.
Look, the important part is typically to solve the problem at hand, not "borrow trouble" by solving problems that don't yet, and may never exist. Even if you run out of RAM, its a LOT easier to grab something with more RAM than trying to use weird half understood constraints and black magic beforehand.
#if ! DISPLAY_SUPPORTS_COLOR
class DisplayHelper
{
public:
void setColor(unsigned color)
{
// Ignored because the display is monochrome.
// Suppress the warning.
(void)(color);
}
};
#endif
#if DISPLAY_SUPPORTS_COLOR
class DisplayHelper
{
public:
void setColor(unsigned color)
{
// Do something useful here.
// Suppress the warning until color is actually used.
(void)(color);
}
};
#endif
class NexButton
{
public:
NexButton(DisplayHelper& helper)
: helper(helper)
{
// other constructor stuff
}
private:
// Use helper to adjust the display. It's responsible for doing the display specific things.
DisplayHelper& helper;
};
void setup(void)
{
}
void loop(void)
{
}
Given the source code adjustments made by the IDE it's less painful to put things like DisplayHelper in separate header + source files.