@alcal not sure why you repeated my pseudo code twice in your last post.

Obviously the full code will have all the required widget code, specifically the input widgets for the calibration etc. As it is a one off requirement for each “brew” then users can be given as long as they like to enter the details and you wouldn’t need timeout’s or millis() etc. Using in loop(), with the input widgets, allows you to do this easily, no?

Sorry I was editing my reply and by mistake I clicked the SEND button before finishing. Now I’ll complete it

Yes and as you have found Blynk has lots of easy ways to enter the calibration data.
It was your insistence that you don’t have a loop() because you are using deepSleep that I disagreed with, plus the use of while statements to collect the calibration data.

Sorry for the deleted posts above. Again, it seems there is a keyboard key (that I am unintentionally clicking on) that would fire the post when I’m in the middle of the editing…

Costas, If you accept that my alternative formulation of your pseudo code is equivalent to yours, I’d say that 99% of the action takes place on the setup() routine, while the loop() would only be used for calibration.
So now the focus to me is: is the + cycle the best way to implement a user interaction like in my calibration routines?
I made some thinking about it, I’m still not convinced, if you have some patience left, I would add some elements to better explain why.

If you look at my previous images, you will see that I have a function menu. You can choose among a number of configuration/calibration functions. All of them are implemented by using the same user interface (1 LCD + 5 buttons). Each function has its own data acquisition logic/sequence, if you think about it, each of them is a separate “state machine”.
You can even go back to the previous input or abort (exit) the current function.
The way it is working now (I admit it is far from Blynk recommended guidelines) is that each function is implemented by a separate routine, each incorporating the logics of the associated state machine, making wide usage of while()s, while the BLYNK_WRITE() routines are kept very simple.

For example (pseudo code, I left out timeout management for simplicity):

    int tiltCalibration() {
       prompt("Enter tilt value for calib point ", i);
       confirm_selected  = back_selected = exit_selected = false;
       while( !confirm_selected and !back_selected and !exit_selected )

       if (confirm_selected) {
           //store value input by user
       } else if( back_selected) {
            //go back to previous step
       } else {
           //exit tilt calibration


         if (param.asInt() == 1) {

        if (param.asInt() == 1) {

         if (param.asInt() == 1) {

Code like this to me is quite easy to understand and manage, because depending on the line you are executing, the tiltCalibration routine is able to take the right decision about what to do when the user click on the BACK button (for example).
The way I understand the Blynk guidelines (but correct me if I’m wrong), since there wouldn’t be anything similar to the tiltCalibration() routine (the program is continuously executing - loop) you have no other way than adding ALL the logics of ALL the state machines associated to this unique interface, to the BLYNK_WRITE() routines.
So when (let’s say) BLYNK_WRITE(BACK_BUTTON) is executed, it doesn’t know whether it is there because the user wants to go back from an input given for the battery calibration OR it was a way back from the second parameter of the third tilt calibration point (for example), unless you tell it someway.
So you need to manage “context variables” to keep track of where exactly you are in the interactive procedures, and inside BLYNK_WRITE() you have to add a lot of if()s (or big CASEs) to make different things depending on the context variables values, and manage a lot of global variables (instead of local ones). While this is technically possible of course (almost anything is possible by software) it looks like unreadable and unmanageable code, to me, but maybe you can suggest a better way to do it?

@alcal we all have different coding styles and preferences and I can see your point to a degree based on the limited knowledge I have of calibrating the “Ispindel”.

That said I would probably still stick to doing everything within BLYNK_WRITE() functions and not in setup().

You can always add an extra button to clear or save data etc.

Edit: I believe Blynk’s references to calling at regular intervals relates more to functions that can’t be made to work any faster than say a few seconds rather than waiting for user input for several seconds or longer. Do also take note that on ESP’s setup() must be completed within about 1s unless you are correctly handling the WDT. Many regular ESP functions in setup() will take care of the WDT but you need to factor this in when calling your own functions / routines.

Costas, I would like to thank you for your precious help.
The discussion went a bit beyond the original question about, but I found it really interesting and stimulating, while I’ll keep my while()s at the moment, now I better see your point too.

My devices have now 4 flawless fermentations under their belt, the latest one is going on right now :slight_smile:

loop()s are empty, everything is managed starting from setup(), which takes 5-7 seconds to run, never experienced any WDT issue whatsoever.
This may be due to my (moderate) usage of delay() and yield(), which are supposed to reset the WDT. Or, maybe, it is some of the “regular ESP functions” I’m using.
Thanks for pointing this out though. I’ll make a deeper investigation.

1 Like

Let me know when it ends and i’ll pop round to “check it out” :slight_smile: