Program crashes after X hours. Likely stuck in a loop I cant find.

Hey guys...

As a little background I just got through trouble-shooting a hardware issue. The thread particular to that issue can be found here: https://forum.arduino.cc/index.php?action=profile;area=showposts;u=505335

I mention this in-case my current issue is driven by that hardware issue I had yesterday. Diagram also included there.

Today I ran the device for a full cycle. This is the device idle for about 20 minutes and about 8 minutes of solenoid open time. After checking on the device- the LCD was hung up. I am thinking I'm either stuck in an endless loop or I have a variable that was not declared correctly and errors out the device.

Posting program code below. It should be noted the hang-up occurs during "draining" state. In this state the progress bar is ticking down slowly. It draws 4 rectangles, then 3, then 2 etc...

All ideas welcomed!

// Import required libraries
#include <ArducamSSD1306.h>    // Modification of Adafruit_SSD1306 for ESP8266 compatibility
#include <Adafruit_GFX.h>   // Needs a little change in original Adafruit library (See README.txt file)
#include <Wire.h>           // For I2C comm, but needed for not getting compile error
//#include <OneWire.h>
//#include <DallasTemperature.h>

#define OLED_RESET  16  // Pin 15 -RESET digital signal
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16

ArducamSSD1306 display(OLED_RESET); // FOR I2C

//global vars
unsigned long sensor1Time, sensor2Time = millis(); //set time of sensor change
unsigned long currMillis = millis();
bool sensor1 = true; //state of sensor 1
bool sensor2 = true; //state of sensor 2
int prevMode = 0;
bool solenoidState = false; //state of water valve
int currMode = 4; //logic mode   1=empty 2=draining 3=filling 4=full
int barState = 4; //progress bar var
unsigned long barUpdate = millis(); //progress bar update


void setup(void)
{
// Start Serial
Serial.begin(115000);
  // SSD1306 Init
  display.begin();  // Switch OLED
  display.setTextColor(WHITE);
  // Clear the buffer.
  display.clearDisplay();
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(10, OUTPUT);
  analogWrite(10, 0);
}

void loop() {
  int s1 = digitalRead(11);  //check-sensors
  int s2 = digitalRead(12);
  currMillis = millis(); //set time for eval
  if((currMillis-sensor1Time) >= 5000){  //evaluate if reading is consistant for 5 seconds
    sensor1 = evaluate(1, s1);
  }
  if((currMillis-sensor2Time) >= 5000){
    sensor2 = evaluate(2, s2);
  }
  currMode = process(sensor1, sensor2);  //set mode based on sensors
  changeState(currMode);  //change solenoid state based on mode
  barCount();  //set progress bar count
  //print info to screen
  display.clearDisplay();
  printMenu();
  printSystems();
  printBar();
  display.display();
}

bool evaluate(int sensor, int sVal){
 
  if(sVal == 0){
   if(sensor == 1){
     sensor1Time = millis();
   }
   else{ //if(sensor == 2)
    sensor2Time = millis();
   }
   return false;
  }
  else{ //if(sVal == 1)
   if(sensor == 1){
   sensor1Time = millis();
   }
   else{ //if(sensor == 2)
    sensor2Time = millis();
   }
   return true;
 }
}

void printMenu(){
  display.setCursor(10,0);
  display.setTextSize(2);
  display.println("AUTO-FILL");
  display.setTextSize(1);
  display.setCursor(8,16);
  display.println("SYSTEM");
  display.setCursor(86,16);
  display.println("STATUS");
  display.drawRect(0, 15, 51, 10, WHITE);
  display.drawRect(79, 15, 49, 10, WHITE);
  display.drawLine(0, 15, 128, 15, WHITE);
  display.drawPixel(0, 31, WHITE);
  display.setCursor(3,28);
  display.println("LVL SENSOR 1");
  display.drawPixel(0, 41, WHITE);
  display.setCursor(3,38);
  display.println("LVL SENSOR 2");
  display.drawPixel(0, 51, WHITE);
  display.setCursor(3,48);
  display.println("FEED VALVE 1");
}

int process(bool upperSens, bool lowerSens){
  if((upperSens == false) && (lowerSens == false)){
    return 1;
  }
  else if((upperSens == true) && (lowerSens == true)){
    return 4;
  }
  else{   //((lowerSens == true) && (upperSens == false))
    if(solenoidState == false){
      return 2;
    }
    else{ //(solenoidState == true)
      return 3;
    }
  }
}

void changeState(int state){
  if(state == 1){
    analogWrite(10, 255);
    solenoidState = true;
    currMode = 3;
  }
  if(state == 4){
    analogWrite(10, 0);
    solenoidState = false;
    //currMode = 2;
  }
}

void printSystems(){
  display.setCursor(92,28);
  if(sensor1 == false){
    display.println("OFF");
  }
  else{
    display.println("ON");
  }
  display.setCursor(92,38);
  if(sensor2 == false){
    display.println("OFF");
  }
  else{
    display.println("ON");
  }
  display.setCursor(92,48);
  if(solenoidState == true){
    display.println("OPEN");
  }
  else{
    display.println("CLOSED");
  }
}

void barCount(){
  switch(currMode){
     case 1 :
      barState = 0;
      break;  
     case 2 :  
       if(barUpdate < millis()-1000){
        if(barState == 0){
          barState = 4;
        }
        else{
          barState = barState - 1;
        }
        barUpdate = millis();
       }
       break;  
     case 3 :    
       if(barUpdate < millis()-1000){
        if(barState == 4){
          barState = 0;
        }
        else{
          barState = barState + 1;
        }
        barUpdate = millis();
       }
       break;
    case 4 :
      barState = 4;
      break;
  }
}

void printBar(){
  switch(barState){
    case 0 :
      break;
    case 1 :
      display.fillRect(2, 60, 29, 6, WHITE);
      break;
    case 2 :
      display.fillRect(2, 60, 29, 6, WHITE);
      display.fillRect(34, 60, 29, 6, WHITE);
      break;
    case 3 :
      display.fillRect(2, 60, 29, 6, WHITE);
      display.fillRect(34, 60, 29, 6, WHITE);
      display.fillRect(66, 60, 29, 6, WHITE);
      break;
    case 4 :
      display.fillRect(2, 60, 29, 6, WHITE);
      display.fillRect(34, 60, 29, 6, WHITE);
      display.fillRect(66, 60, 29, 6, WHITE);
      display.fillRect(98, 60, 28, 6, WHITE);
      break;
  }
}

[color=#222222][/color]

This:

      if (barUpdate < millis() - 1000) {

should be changed to:

      if (millis() - barUpdate >= 1000) {

Your evaluate function could be eliminated. Replace:

  if ((currMillis - sensor1Time) >= 5000) { //evaluate if reading is consistant for 5 seconds
    sensor1 = evaluate(1, s1);
  }
  if ((currMillis - sensor2Time) >= 5000) {
    sensor2 = evaluate(2, s2);
  }

with:

  if ((currMillis - sensor1Time) >= 5000) { //evaluate if reading is consistant for 5 seconds
    sensor1 = s1 == HIGH ? true : false;
    sensor1Time = millis();
  }
  if ((currMillis - sensor2Time) >= 5000) {
    sensor2 = s2 == HIGH ? true : false;
    sensor2Time = millis();
  }

ToddL1962:
This:

      if (barUpdate < millis() - 1000) {

should be changed to:

      if (millis() - barUpdate >= 1000) {

Your evaluate function could be eliminated. Replace:

  if ((currMillis - sensor1Time) >= 5000) { //evaluate if reading is consistant for 5 seconds

sensor1 = evaluate(1, s1);
 }
 if ((currMillis - sensor2Time) >= 5000) {
   sensor2 = evaluate(2, s2);
 }




with:



if ((currMillis - sensor1Time) >= 5000) { //evaluate if reading is consistant for 5 seconds
   sensor1 = s1 == HIGH ? true : false;
   sensor1Time = millis();
 }
 if ((currMillis - sensor2Time) >= 5000) {
   sensor2 = s2 == HIGH ? true : false;
   sensor2Time = millis();
 }

Thanks for taking a look! Going to give this a try right away. Looks like I was violating some basic BODMAS rules with that first example there.
Thank you for the help with the evaluate function. I was getting frustrated figuring that one out. I'm pretty novice.

Do you think either of these were contributing to a freeze or possible endless loop?

Do you have a kickback suppression diode across the solenoid coil? Please post a wiring diagram.

JCA34F:
Do you have a kickback suppression diode across the solenoid coil? Please post a wiring diagram.

I do now. I mentioned in the OP I had some circuit issues I had rectified. The issue fried a FET and I had to replace it. A fly-back was added to the coil and the fan. Diode not present in the diagram but currently have one across both with polarity pointing towards +V.

Here's the thread

https://forum.arduino.cc/index.php?topic=717309.msg4818831#msg4818831

Looks like I was violating some basic BODMAS rules with that first example there.

No, it has nothing to do with BODMAS. The issue is that you can only calculate intervals correctly by subtracting current from stored time stamps, considering the problem of millis() "rolling over" from its nearly maximum value, back to zero. If you look at the IDE example sketches using millis(), you will see that it is always done this way. It's the only safe way.

aarg:
No, it has nothing to do with BODMAS. The issue is that you can only calculate intervals correctly by subtracting current from stored time stamps, considering the problem of millis() "rolling over" from its nearly maximum value, back to zero. If you look at the IDE example sketches using millis(), you will see that it is always done this way. It's the only safe way.

Roger that! Thank you for the clarification. My thought was the below segment might achieve the same thing but I do see the difference now.

     if (barUpdate < (millis() - 1000)) {

Could you elaborate of what type of issue this creates? Is it that when millis resets to zero there is nothing to subtract from and there's the hang?

I can't comment fairly because 'barUpdate' seems to be a current time stamp, not a previous or future time stamp. Here is one explanation (of many...):

https://www.norwegiancreations.com/2018/10/arduino-tutorial-avoiding-the-overflow-issue-when-using-millis-and-micros/

it also links to this one, so here you go:

aarg:
I can't comment fairly because 'barUpdate' seems to be a current time stamp, not a previous or future time stamp. Here is one explanation (of many...):

Arduino Tutorial: Avoiding the Overflow Issue When Using millis() and micros() – Norwegian Creations

it also links to this one, so here you go:

programming - How can I handle the millis() rollover? - Arduino Stack Exchange

Fair enough! I'll make the change just to be more aligned with standard practice (my larger goal anyways) and eliminate evaluate. I wasn't even aware you could do the syntax you posted (I have lots to learn).

I have one cycle to run on the device tonight. I'll give it a go. Last night it ran for about 10 hours before freezing (twice now). Would have been draining state. I'll report back tomorrow.

Unfortunately no dice. This is the first time it didn't make it through even one fill.

-First odd thing was the solenoid energized during start-up. I don't recall it doing this in the past but perhaps it was and I was not seeing it because there was no water pressure. This isn't a big deal if its normal. I just cant imagine why pin 10 would kick a high output signal during boot.

-Second is; this time it froze during filling and within about 5 minutes. It could be a wiring issue... but the solenoid stayed open (kept filling) while it was frozen. So it was still outputting a signal to the FET. The screen continues to display but a frozen task bar and the sensors don't respond because the screen is not updating.

-Third: the BEC is 5V-5A that supplies the arduino. The screen runs from the arduinos 3v (bad idea?) The solenoid and fan are powered 12v via FET. Only the arduino (and oled screen) are powered off that 5v so I figured 5A was plenty adequate.

-Fourth: Both the fan AND the coil are switched from the same common FET gate. Is this a problem?

Reattaching my wiring diagram should anything stick out- remember i've since added diodes across both fan and solenoid.

Hi,
Can you please use normal component symbols in your diagram?
A hand drawn diagram will be easier and faster to make, especially when drawing component symbols.

Why are you switching the power from the 12V what ever it is in the gnd lead and not the positive lead?
What is the N-CH MOSFET and can you label your pins please.
Please label the pins on your components including the BEC, what is its part number?

As asked previously do you have a back EMF diode on the solenoid windings?

Tom... :slight_smile:

TomGeorge:
Hi,
Can you please use normal component symbols in your diagram?
A hand drawn diagram will be easier and faster to make, especially when drawing component symbols.

Why are you switching the power from the 12V what ever it is in the gnd lead and not the positive lead?
What is the N-CH MOSFET and can you label your pins please.
Please label the pins on your components including the BEC, what is its part number?

As asked previously do you have a back EMF diode on the solenoid windings?

Tom... :slight_smile:

  • I assumed switching ground was a better practice here as it was a common sink where there are multiple voltage sources. Am I backwards? Easy fix if that's your recommendation.

  • FET is IRLB8721PbF. Acquired from adafruit. Data sheet here

  • Diode is a 1N4001 for the coil and fan. Data sheet here

  • BEC is a result of my drone racing days. We use these to power 5v anything on a drone from 6S (22v) lipo batteries. Can't find a data sheet but here's the link. Generally these are quite simple. Vin Vout GndIn GndOut. I tied the grounds together. All sources are sharing a common ground. Link here: iFlight BEC

  • I'll get working on the diagram. I don't know much about standard symbols so it will take longer but ill get something out here. Back in the school days I took a few classes using multisim but its been quite some time.

That BEC link doesn’t work and the few things I could tell wrong about it didn’t fix it up.

But.

I have xperience with iFlight BECs and I ask you to check and be sure it is delivering what you need volt- and amp-wise.

I have found their stated specifications to be somewhat, um, aspirational.

HTH

a7

alto777:
That BEC link doesn’t work and the few things I could tell wrong about it didn’t fix it up.

But.

I have xperience with iFlight BECs and I ask you to check and be sure it is delivering what you need volt- and amp-wise.

I have found their stated specifications to be somewhat, um, aspirational.

HTH

a7

Sorry raw link to BEC and OLED below. I was also wrong. Its a 3A supply not a 5A. I'll check it out. Also noticed this dialog when looking into power draw of feather M0 (11mah + 15mah OLED)

The Feather is not designed for external power supplies - this is a design decision to make the board compact and low cost. It is not recommended, but technically possible:

  • Connect an external 3.3V power supply to the 3V and GND pins. Not recommended, this may cause unexpected behavior and the **EN **pin will no longer. Also this doesn't provide power on BAT or USB and some Feathers/Wings use those pins for high current usages. You may end up damaging your Feather.
  • Connect an external 5V power supply to the USB and GND pins. Not recommended, this may cause unexpected behavior when plugging in the USB port because you will be back-powering the USB port, which could confuse or damage your computer.

BEC

https://www.amazon.com/UCTRONICS-SSD1306-Self-Luminous-Display-Raspberry/dp/B072Q2X2LL/ref=sr_1_2?dchild=1&keywords=ADAFRUIT+OLED&qid=1603820882&sr=8-2

OLED

https://www.amazon.com/iFlight-Adjustable-Step-Down-Voltage-Regulator/dp/B0823QLMWC/ref=sr_1_1_sspa?dchild=1&keywords=5v+bec&qid=1604205910&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzNEY5NlFBS1RIRDZZJmVuY3J5cHRlZElkPUEwMjk4OTI4MzRDOVY2UU43WUFDOCZlbmNyeXB0ZWRBZElkPUEwMzczOTI0MUlWVE5ZVkxLV1BBJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==

THX. I think that is exactly the one I have tried.

It came nowhere near delivering 3 Amps at 5 volts. And got very hot whilst not doing.

Several are now in my random parts bin, I will verify when I ever need them that they were fine for 1 amp according to my label.

Neither the vendor nor iFlight stayed engaged with me, and iFlight never sent the promised samples from a “new production run”. Last time I’ll ever go to the trouble of proving to a manufacturer with a video showing their crap failure product. Grrrr.

Now I always set up a static test before deploying any BEC, many are super optimistic about current capacity.

a7

Hi,

I assumed switching ground was a better practice here as it was a common sink where there are multiple voltage sources. Am I backwards? Easy fix if that's your recommendation.

As all your hardware is powered by the 12V supply, ie a common source, switching the positive is better.
If you switch gnd then if when turned off you have an inadvertent connection between any of your hardware and gnd, you will have current flow.
When switching positive at the supply an inadvertent connection to gnd by your hardware when turned off will result in no current flow.

Tom.... :slight_smile:

alto777:
THX. I think that is exactly the one I have tried.

It came nowhere near delivering 3 Amps at 5 volts. And got very hot whilst not doing.

Several are now in my random parts bin, I will verify when I ever need them that they were fine for 1 amp according to my label.

Neither the vendor nor iFlight stayed engaged with me, and iFlight never sent the promised samples from a “new production run”. Last time I’ll ever go to the trouble of proving to a manufacturer with a video showing their crap failure product. Grrrr.

Now I always set up a static test before deploying any BEC, many are super optimistic about current capacity.

a7

Nice. I will test the V and throw a load on it. Do we agree even 500mah is sufficient for operation? I think my power requirement for 5v doesn't go above 100mah.

I might consider just using an arduino uno or metro or something. Any of them have 12v, 5v, and 3.3 and I don't need a BEC, the power jack is built on (where I soldered one). I think you can switch power on those things by pulling a pin low via a rocker just the same.

Does anyone think this is a code issue? I don't know whether to be flattered or worried :slight_smile:

TomGeorge:
Hi,
As all your hardware is powered by the 12V supply, ie a common source, switching the positive is better.
If you switch gnd then if when turned off you have an inadvertent connection between any of your hardware and gnd, you will have current flow.
When switching positive at the supply an inadvertent connection to gnd by your hardware when turned off will result in no current flow.

Tom.... :slight_smile:

Got it. I'll switch that over to the other side. Perhaps this explains the coil energizing during boot.

Hi,
This may help, I have added the switch and some bypass capacitors that will help with noise filtering.

I see your solenoid valve is 12V and 4.8W, current is 400mA, but have seen nothing of the fan current or if your 12V supply can produce the minimum current required for your project. What is the 12V supply's rated output current?