One section of code constantly causes Blynk to disconnect

  1. I am at work so no access to my Arduino and so I copied old code to put it in; I have taken the temp sensor out of the loop

  2. First three lines of code are (once again my mistake of copying old code)

    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <LiquidCrystal_I2C.h>

  3. V2: Mashtime Slider
    V3: Boil Time Slider
    V13: Chill Time Slider

The scale is interger minutes as in my code I divide millis() to convert it into minutes when looking at elapsed time

  1. Yes to add HOPINFO: “I,Stuff,Stuff2,Stuff3”
    HOPTIME: “T,TIME1,TIME2”

  2. I will be moving the serial print codes into my code tonight.

I worked out that I and T are not terminated with a comma but for me if I put in Cascade it returns only Cascad. Same with any variable for I,so somewhere you have lost a character.

So you have to add a comma after the last character of both info and time to stop it from looping like that?

potentially your losing a character because the for loop when inputting goes from i=0 ; i< from Terminal.length(), i++)

Maybe it should be i=0 ; i=fromTerminal.length(),i++

I’m not home unless I would try myself.

No it doesn’t need to end with a comma, I just thought that was how you had terminated it.

Still looking for the fix.

In V14 you have:

    if (i == fromTerminal.length() - 1) {  // If we're at the end of the string (no more commas to stop us)
      HOPINFO[counter] = fromTerminal.substring(lastIndex, i); 
    }

If you remove the , i from the last line it will show the full Cascade but the sketch is still crashing the ESP.

In case 9 you have:

for (int h=0 ; h=hopCounter; h++) {

If you change the h=hopCounter to h < hopCounter it will stop the crashing but I’m not sure if that still processes all the required hops etc (perhaps you can look at this).

Also I would comment out the Blynk.notify(HOPINFO[h]) in this section until it is running smoothly because of the one Push message per minute limit. Even with the change above it is still looping round saying Add: Cascade every few seconds so it will exceed the one push per minute (but at least it isn’t dropping the connection).

You will have to review the change from h=hopCounter" part to see where and when the second and subsequent hops should appear.

I am looking at the code, I have the if statement true if the elapsed time is +/- 1 minute from the hop time. That would make it be true for two minutes so perhaps that’s why it still is repeating.

I made it that way because I’m not sure how timing works if I say elapsed time = hop time would it have to be exactly that time and if the loop doesn’t happen to run that time it wouldn’t trigger. I could make a counter type to make the hop trigger only once. Thoughts?

In V14 you have:

terminalHops.print(HOPTIME[1]);

and

terminalHops.print(HOPINFO[1]);

Should these 1’s be i’s and should they be included within the For loop()?

If I have 2 Hops (Cascade and Stuff) the modified (< from =) For loop in case 9 shows:

Add:
Add: Cascade

So one of the hops is missing.
I’m not sure I follow how the hops are added. If I set T,1,1 and I,Cascade,Stuff does this mean show a message for 1 minute to add Cascade and then a minute later add Stuff or are both hops added at the same time, if so what is the T format for this?

I will take a look at the +/- 1 minute but to be honest I think all of the stages would have been handled better with SimpleTimer and the code split up into much smaller sections. So pre mash, mash, boil and chill.

SimpleTimer is dynamic and can take user input from the sliders etc. So you enable pre mash timer based on user input, then move on to mash etc.

1 Like

The remarks on the SimpleTimer are very good I think. I’ve been reading up on brewing because I wanted to take it up too, but it’s too costly in time and I’m not really patient, LOL.

But you can enable/disable timers based on inputs, as Costas says. It’ll save a lot of hassle and possible programming space, but it’ll be some job to get things done.

How I would start, is by making a flowchart to document the process. It’s not to be taken lightly because there are a lot of factors involved in beer brewing (I’m hoping Phil can make his fall beer in time :wink: ).

1 Like

@Lichtsignaal if you study the code you will see how messy it currently is (bit like most of my code).

The brewing process seems quite involved but it is really just one stage following the previous one. @philmurp has some fall back positions included in his code so it is not always A -> B -> C -> D but again SimpleTimer can handle all this.

Flowchart essential.

1 Like

@philmurp regarding the + / - 1 minute for the hop time:

To be able to test your sketch I didn’t want to have to wait a week for a “brew” to finish and I didn’t want to hook up temperature sensors and heaters. So I did some “simulation” and also skipped lots of conditions in the sketch.

So where you had the attempt to read the temperature a thousand times a second in loop() I removed this and with a 3 second timer called Fahrenheit() did this:

void Fahrenheit(){
  tanktemp = tanktemp + 0.1;  // Starting from 200F,   also tried +1
  Serial.println(tanktemp);
  Blynk.virtualWrite(V9,tanktemp);
  if (premash == true){
    Blynk.virtualWrite(V11, ElapsedPreMashTime);
    Blynk.virtualWrite(V10, "preM");
  }
  else if (mashrun == true){
    Blynk.virtualWrite(V11, ElapsedMashTime);
    Blynk.virtualWrite(V10, "MASH");
  }
  else if (boilrun == true){
    Blynk.virtualWrite(V11, ElapsedBoilTime);
    Blynk.virtualWrite(V10, "BOIL");
  }
  else if (chillrun == true){
    Blynk.virtualWrite(V11, ElapsedChillTime);
    Blynk.virtualWrite(V10, "CHILL");
  }
  else {
    Blynk.virtualWrite(V11, 0);
    Blynk.virtualWrite(V10, "N/A");
  }      

  if (mashend == true){
    Blynk.virtualWrite(V10, "preB");
  } 
}

To be honest I wasn’t very successful and vary rarely did I see entries for V10 and V11 in the app (temperature in Fahrenheit for V9 was fine). I saw them a few times but I couldn’t easily replicate the correct process of pushing buttons, moving sliders and adding hops to get V10 and V11 data.

Nonetheless I was able to hack the sketch to move through various processes and you already knew where the problem area was.

One of the hacks was to comment out your + / - 1 minute hop time and change your 1 second timer to 3 seconds. In a live system I am guessing this timer could be a minute and would need to be if you are going to have Blynk.notify commands within the timed process.

I generally use counters to ensure things are only done once (or X times) rather than using time +/- a minute. However I notice that your sketch doesn’t include the text “sync” at any point. You have the brew stage and elapsed time on V10 and V11 Display widgets which is fine but I would be syncing these (and other) values if the ESP does any form of reset or loses the connection to the server etc.

for the:
terminalHops.print(HOPTIME[1]);

I used this as a way to display if the variables were being implemented properly; so it was my version of a serial output; which I now know via several discussions I should have just used serial output. I only have it showing the first of the array because I wanted to show it was working and figured if one worked the others would as well.

The theory is that when the elapsed time == Hoptime that the terminal & blynk.notify will send an alert that I need to add hops. So there should be only one notification of each hop addition. So if Cascade needs to be added during the first minute of the boil; it would be T,1 & I,Cascade which should display once.

I think what I currently have is that once it hits the elapsed time==Hoptime since I have no counter it is repeatedly displaying to add it for the +/-1 minutes from that time. Still trying to think how that counter should be done since I need it to be triggered for each hopadd separatley (i.e. each hopaddition can only be displayed once)

So here is my to do list:

  1. Add in serial reads to debug

  2. change to stop the crashing
    for (int h=0 ; h=hopCounter; h++) {
    to
    for (int h=0 ; h<=hopCounter; h++) {

  3. Change timer to run only once a minute so that Blynk.notify will work

  4. Create counter on hopadd for loop so that hopadditions are only displayed once. Here is where I could use any best practices you guys have seen to create counters in a for loop that would achieve this goal.

In response to the SimpleTimer and breaking down the code; my purpose was to ideally be able to have the brewing automated so that I hit go and don’t touch it (for hop additions I would have to do physical work for now, but in the future state I would have motors running hardware to dump hops but that’s a different story)

With the simpletimers, wouldnt I have to trigger each stage manually then?

As far as workflow, I have drawn out some basic sketches previously to get to this point. I can whip something more formal up in visio or something like that, @Costas your right it is sequential with a few re-work off shoots in case temperatures fall below a certain limit (you need your mash temp to stay consistent as possible). Adding in complexity is also the coding I created to manually run the setup. So I have the auto brewing code; but then separate I have buttons to be able to manually turn on and off heaters & pump which would be for the purpose of other random chores like cleaning or if I wanted to experiment with complex mash phases that I just didnt think were time efficient for me to build into the autobrewing code (some complex brews have step mashes where the mash temperature is held a several different temperatures for some length of time during the mash ie. 150 for 10minutes, 165 for 10 minutes etc)

I think you should give us a real world example of a brew, just a simple one with the H & I data and times and temperatures for each of the stages.

But for sure SimpleTimer doesn’t need any manual intervention unless to you want to provide any.

Using your current if statements based on time and temperature each of the 4 stages are triggered through SimpleTimer.

See extract of how I would lay it out (it compiles but doesn’t do anything).

// extract for Brewery - breweryextract.ino Costas 25/8/16
// see http://playground.arduino.cc/Code/SimpleTimer
// normal libraries here


#include <SimpleTimer.h>

SimpleTimer timer;

int premashtimer = 1;   // timers just numered 1 to 5, required for enable / disable feature
long premashinterval = 10; // general but can be changed during execution
int mashtimer = 2;
long mashinterval = 20;    // general but can be changed during execution
int boiltimer = 3;
long boilinterval = 80;    // general but can be changed during execution
int chilltimer = 4;
long chillinterval = 6;    // general but can be changed during execution

int oneminutetimer = 5;

void setup() {
  // normal Blynk setup here
  
  // these first 4 timers are defind but disabled on bootup
  premashtimer = timer.setInterval(premashinterval, premashstuff); 
  timer.disable(premashtimer);
  mashtimer = timer.setInterval(mashinterval, mashstuff); 
  timer.disable(mashtimer);
  boiltimer = timer.setInterval(boilinterval, boilstuff); 
  timer.disable(boiltimer);
  chilltimer = timer.setInterval(chillinterval, chillstuff); 
  timer.disable(chilltimer);

  // this timer is automatically enabled on bootup
  oneminutetimer = timer.setInterval(60000L, oneminutestuff); // check things every minute
      
  
  // if all is ok enable premashtimer, maybe check is done in oneminutetimer
  timer.enable(premashtimer);
}

void premashstuff(){
  timer.disable(premashtimer);
  // do premashstuff
  timer.enable(mashtimer);  
}

void mashstuff(){
  timer.disable(mashtimer);
  // do mashstuff
  timer.enable(boiltimer);   
}

void boilstuff(){
  timer.disable(boiltimer);
  // do boilstuff
  timer.enable(chilltimer);   
}

void chillstuff(){
  timer.disable(chilltimer);
  // do chillstuff
  // send push message, beer is ready    
}

void oneminutestuff(){
  // check temperature and time etc
  // maybe change timer intervals from sliders
  // add hopinfo and hoptime
}

void loop() {
  //Blynk.run();  // include this line when Blynk libraries are inserted above
  timer.run();
}

Ok now I am getting it a bit more. The benefit of these timers is that during each phase, the only code running would be within that phase; which is run at an interval I have chosen; instead of where I have it now where it runs through the entire autobrewing code via switch case? (regular blynk code, and then the overall oneminute timer code would also run the whole time)

Second, it would make debugging and looking at the code easier?

Here is an example of brewing parameters I would insert:
Mash Temp: 158
Mash Time: 60
Boil Time: 60
Chill Time: 20
T,1,30,45
I,Cascade2OZ,Colombus2OZ,Mosaic2OZ

Here is the theory of what would run now:
Heaters on to heat water until 158
Heaters off, pump on for 60 minutes
Heaters on until boil temp reached (200F in my case)
Boil Temp reached, boil elapsed time tracked; HERE IS WHERE THE HOP ADDITIONS CODES TRIPS ME UP
Heaters on for 60 minutes during boil
Heaters off, pumps on for 20 minutes for chill time

Currently it all works ok, except for as soon as we hit a hop addition code it disconnects; and when I dont put anything in for hop additions; then boil runs fine; so it really seems like isolated hop additions issue.

1 Like

For sure it would. I have eye strain today from looking at your code yesterday :slight_smile:

You can have up to 10 timers running simultaneously (for each SimpleTimer object) if needed but generally a handful running at the same time is normally enough.

Wouldnt having timer.disable in the void loop cause that section code to only run once? Are you saying I should have my if statements based on time/temp around that.

void premashstuff(){
  timer.disable(premashtimer);
  // do premashstuff
  timer.enable(mashtimer);  
}

For example I should have that when mash conditions are met, then you disable premash timer and enable mashtimer, but until then the premashtimer continues to be enabled. Sorry if I am missing a component of how this library works.

Also, coming back to the hop addition code; with those updates you mentioned you were able to not have the board crash and the hop addition notification worked? So if I can figure out some sort of counter then the hop notify once should work?

You are right about the functions only running once based on the disable timer. I was expecting you to be using the 1 minute timer to check when each function should end and that each function does only need to run once.

Maybe they need to run more than once but I’m not a brewer so I don’t know.

You don’t want an enormous piece of code in the 1 minute timer though so again if you want to put some code in the functions to run over and over then by all means ensure you don’t disable the timer until that phase is complete.

Yes with the hacks I did I was able to get the push message and the ESP didn’t crash but as per my earlier comments I wasn’t running through from start to finish. I was forcing entry to case 9 simply by making the condition true (whatever it was). If I added Cascade the push message stated add: Cascade or something to that effect, but I was concerned it wasn’t notifying me when to add the second or third hop. I’ll leave that part for you to fix.

I was able to work on the code today finally; and I think I have it working although it still needs a full brewing test run.

  1. Added counters so that the hop reminder would only happen once for each hop input by creating a hop counter array that mirrored the HOPINFO and HOPADD arrays
  2. By having the terminal input finish with the delimiter (in my case “,”) it will include all inputs
  3. No crashing

Thanks for all the feedback and I will get to brewing a full batch asap.

1 Like

Awesome, @Costas and I will send you our addresses for delivery, lol :wink:

3 Likes

Yes @Lichtsignaal I’m looking forward to sampling Phil’s next batch.

1 Like