Start a new topic

Arduino events from Nextion

I am building a smoker controller and am using  a Mega 2560 with a Nextion 3.5".  After some issues with the setup, everything is going quite nicely.  I have 6 pages and there are two buttons that trigger callback events to the Arduino.  The callbacks are working perfectly when there is no code running in the loop().  All my field sets and gets are working beautifully.


I put a while loop in my code so the loop() only runs when the controller is turned on however I did not put my listener inside the while loop so all is well. 


The setup runs fine and I get the following.

recvRetCommandFinished ok

recvRetCommandFinished ok

setup done


The loop() code starts out like this.

void loop()

{ nexLoop(nex_listen_list);

while (ControllerStarted) {


I know my events are coming through because of my serialprint statements.

My Controller Stop button works fine.  I pressed it twice.

[2056:0,7,b6] Controller Stopped

[2056:0,7,b6] Controller Stopped


My Save button fires fine also

[2092:1,6,b1] Save Button Event Fired


I hit my controller button which sets the boolean ControllerStarted

[2068:0,6,b5] Controller Started


The while loop has normal logic (not a lot).  As soon as I put a load in the loop() because I turn on the controller bool, none of my button events from the Nextion fire in the Arduino.  I know the Nextion is working fine before I turn the logic on in the loop().    The two buttons I tested before I turned on the controller do not fire or at least my callback functions do not execute. 


Attached is my loop()


I read about using the delay() and some people at it is a life saver.  Others believe it is a deamon to use.  Could it be related to this?  When do you want to use the delay().


I am totally stuck here and any help would be appreciated.


txt
(2.93 KB)

Sorry all, I stepped away from this for a few hours and it hit me without even looking at the code.  The listen event needs to be both inside and outside the while loop.

ok, I changed the code to put the listener both inside the while loop and after the loop(0).  

void loop()

  {

    nexLoop(nex_listen_list);

    while (ControllerStarted) {

          nexLoop(nex_listen_list);


Still does not fire any events after the controller is started.

Hmmm.  Still not firing events. So why would you feel an event should fire.

Wouldn't there need to be a trigger that fires it?


Loop() is a while statement in itself

  A while inside ...hmm

  delays inside ....hmmm

  checking serial nexLoop twice per loop()


A snippet of the code doesn't show if all the necessaries are present.

But you are tripping over your code band-aids rather than implementing your plan.


Perhaps there are several styles of programming, but ...

Loop should be a clean run through only doing something when it is time to do it


Pseudo ...

Loop {

  if need to update time on Nextion ...

     call function to update time

  if need to get temperature on Nextion ...

     call function to fetch temperature  

}


Then loop should look clean and clear and easy to understand

 - and if no triggers, loop should iterate in a few useconds


Perhaps let me peak at HMI and INO

@bigredsmokehouse


There's nothing wrong with running a 'while' loop inside the loop() per se, but the stuff you have going on there, especially all those Serial.prints, will be getting executed at potentially 1000's of time a second.

I would hazard a guess that you are overloading the serial buffer effectively crashing your device.


Have a look on the web for 'blink without delay' and use the timer functions described, to do those tasks, say every five seconds. Freed up from all that printing, your device then might have half a chance of doing 'other stuff'.


So rather than using a bool to get into that almost endless while loop, you use that same bool to do an 'if true, do this list of stuff once every five seconds, exit'. All without the additional 'while' loop, even better would be to put all that in a separate function that you call from loop(), much like   nexLoop(nex_listen_list);

Hi Patrick,


When this project is completed it will be on GitHub.  I have a lot more code to write now that I have my awesome Nextion working properly.  I am also looking for a solenoid that I can put on a propane feed (on and off) only. 


Attached is my ino and HMI.  I really appreciate you being so kind to look at this.

ino
HMI
(1.11 MB)

Thank you indev2.  Points well taken.  I am much more comfortable with the process and will take out all my serial prints out.  I actually don't need many of them anymore other than checking things when I initially write a chunk of code.  I have a feeling this is going to help dramatically.  Many thanks !!!!

I have to agree with indev2 on lots of prints, but also

 - your setup trigger callbacks - I expect are an issue or just forward declaration?

 - and two unbridled .getTemp_F() call in every loop.

 - mixture of hardware serial and software serial ??


A NexComponent (page, id, "objname") does two things

 - it has the page,id coordinates needed for listen list inbound

 - it has objname for parsing assignments outbound


The Touch is setup by

 - Send Component ID checked in Touch Events in HMI

 - including &our_object into the nex_listen_list

 - and attaching the appropriate push/pop (usually done in setup)

 - Serial already defined in nexInit(); - see NexHardware.cpp


Each iteration of loop,

  nexLoop is called and checks if a 0x65 event occurs

  At this point it iterates through your nex_listen_list

   if matching coordinates, then checks for push/pop function and delegates


Attached ino is base needed for your Nextion button triggers

 - default dbSerial and nexSerial as defined in NexConfig.h

try the sketch without all the extras see that Nextion is working


Temperature probes usually take about 750ms,

   you have called twice every iteration of loop()

   this can be an issue, usually set to check every so often no 1000s per second.


If the base sketch is outputting and responding to your buttons

 then issue is mostly in overloading what to be done every loop() iteration

ino
(773 Bytes)

@bigredsmokehouse


Sorry we seem to have a misunderstanding on the Serial.print() issue.


I was making reference to the code in LoopCode.txt


With the delays commented out as you have it, once you enter the 'while' loop, it will try to execute as fast as it can over and over. Possibly many thousands of times a second.

Each call to .setText() is an instruction to Serial.print to Nextion. In no time at all the Serial buffers on at least one of your devices - your Ardiuno or the Nextion - will be in overload condition assuming the other code can be executed relatively quickly. 

The occasional prints done elsewhere are probably quite within what I consider normal workload. 

It's that 'while' loop that needs your immediate attention.

I cleaned everything up based on both of your wonderful comments.  It makes so much more sense.  Just hearing that there are approximately 1000 iterations of the loop() in a second really solidified in my brain.  You must excuse me but I am so used to database and transactional programming design.  I simply love this stuff and the fact that there are experts like all of you, it makes it much better to learn it. 


I truly cannot thank you enough for taking the time to answer some questions.  My code now runs so much better.

Glad to hear you are up and running.  Just for some clarifications.

loop() can be 2/3 iterations per second to a million iterations per second.


Arduino has three primary functions

  setup() only run once at program beginning

  loop() which does as its name states - top to bottom

  serialEvent() - runs at the end of each loop iteration

 

Now whether hidden (default) or user (exposed) serialEvent() function is to catch your incoming bytes.  hardware USART on a standard MCU might be 14-16 bytes (an STM32 has 3 - 32bit word hardware buffer or 12 bytes, but only 8 bits is used per word so max 3 bytes - this is two in buffer and one in the chamber) and Arduino I think has a default ~64 byte software buffer.


So the Arduino philosophy is to have its loop be quick enough to not loose data.  At 115200 baud, this is 11520 bytes/s using a 64 byte buffer means the buffer needs to be minimally cleared every 5.5ms (180 /s) or risk data loss. At 9600 baud, 960 bytes/s with 64 byte buffer needs to be cleared minimally every 66.6ms (15/s). 


But there still has to be a few idle cycles in that loop() time to clear the hardware buffer to put the incoming byte into the software buffer.  Sometimes this is interrupt driven with a Hardware serial or polled by a Software serial.


So to give an clearer idea of loop(), all instructions are sequential (a few interrupts will add extra to this). An empty loop should be expected iterate much closer to MCU_clock_MHz / a_few_cycles.  But a full loop is the time for each item, plus any conditional branch executions (and be back in time at the end of the loop to pick up the incoming serial from the buffer).


Also looking at the code: the Iteadlib, any available() bytes are also caught within nexLoop() and in a few other events like .sendCommand() which receives bytes before sending.


Using a temperature sensor can chew up 750ms if the code is to wait until the read request is processed and values are received.  One approach to get around this is a read-request-and-run (read the value, then send the request). This approach allows you to get back to your code without a 750ms delay, but it means that the value you are reading is an old value.  So if temperature is requested every 5 seconds, the value is from 5 seconds ago - and this approach may be useful in several scenarios.  You'd need to decide if it is useful for yours.  Should add, if the temperature sensor code includes the option.

Login or Signup to post a comment