Learning to Make libraries but code hangs

Hey guys,

I am learning to make libraries and pointers and all of that, the code is still relatively simple. it is purely for learning purposes and almost no other function… other than keeping two of my house plants alive. so I cannot figure out the problem other than the code hangs in pump.cpp (listed last) in the method runThePump() during turning the pump on and off. it serial prints “turning pump on” and hangs, what seems like right away. anyway to keep things short. here is the code. any help is greatly appreciated as my two house plants won’t live long by my hand alone lol. the comments in the main code are excellent, but I am still working on the library itself. please help as I have no clue as why this is an issue

short version: code hangs during the first run of the pump in the first instance of the class. the pump runs in cycles to keep it from getting to hot. I had this running originally without a library so I know it is not hardware.

Main Code:

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <pump.h>
#include <moisture.h>



#define OLED 9
#define OLED_RESET 10
Adafruit_SSD1306 display(OLED_RESET);


int pumpP1 = 2, // Pump 1
    pumpP2 = 3, // Pump 2
    soilPower  = 4, //Power for soil moisture sensor Pin 4
    soilPower2 = 5, //Power for soil moisture sensor 2 Pin 5
    ledB = 6, //blue
    ledG = 7, //green
    soilSignal = 0, //Analog soil moisture sensor pin
    soilSignal2  = 1; //Analog soil moisture sensor pin


int val = 0,//Declare values to hold soil moisture readings
    val2 = 0, //Declare values to hold soil moisture readings
    moistureLevel = 40; //what percent to water the plant

unsigned long pMills = 0;


long pumpOn = 300000, //millseconds of the interval to run the pump(sec * 1000);
     pumpOff = 60000, //millseconds of the interval to pause the pump(sec * 1000);
     pumpWateredTimer = 86400000, //milliseconds, how often to
     pumpDryTimer = 32400000,
     soilTimer = 0;

//tes
pump pump1(pumpP1); //Pump pin for pump 2
moisture m1(soilSignal, soilPower); //(signal, power)

//Liz
pump pump2(pumpP2); //Pump pin for pump 2
moisture m2(soilSignal2, soilPower2); //(signal, power)


void setup() {
  pinMode(OLED, OUTPUT);
  digitalWrite(OLED, HIGH);
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //Tes
  pump1.setPumpData(6, moistureLevel, ledB); //(cycle, mThresh, led);
  pump1.setPumpTimers(pumpWateredTimer, pumpDryTimer, pumpOn, pumpOff);//(delayAfterWatered, delayAfterDryed, pumpOnTime, pumpOffTime)
  //Liz
  pump2.setPumpData(8, moistureLevel, ledG); //(cycle, mThresh, led)
  pump2.setPumpTimers(pumpWateredTimer, pumpDryTimer, pumpOn, pumpOff); //(delayAfterWatered, delayAfterDryed, pumpOnTime, pumpOffTime)


}


void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - pMills >= soilTimer) {
    pMills = currentMillis;

    val = m1.moistureTest(); // test moisture for pump1
    val2 = m2.moistureTest(); // test moisture for pump2
    dispMoistureOLED(val, val2); //display moisture for plant1 and plant2
    soilTimer = 7200000; //don't check moisture again until this time
  }

/*  Serial.println(pump1.getMoistureValue());
Serial.println(pump2.getMoistureValue()); */ //not necassary with oled

  pump1.setMoisture(val); // set moisture value for pump1
  pump1.runPump(); //now see if the pump needs to run

  pump2.setMoisture(val2); //set moisture for pump2
  pump2.runPump();//now see if the pump needs to run

pump1.pumpFailSafe(); //lets not have any mistakes
pump2.pumpFailSafe();

}



void dispMoistureOLED(int &moisture, int &moisture2) //display that sh**
{ //Display Moisture percentages OLED
  display.clearDisplay();
  display.drawBitmap(0, 15, plantBMP, 64, 64, 1); //deleted the photo to meet character limit
  display.display();
  delay(500);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 1);
  display.println("Moisture -");
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(44, 25);
  display.print("Tes ");
  display.setCursor(85, 25);
  display.println(moisture + String("%"));
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(44, 50);
  display.print("Liz ");
  display.setCursor(85, 50);
  display.println(moisture2 + String("%"));
  display.display();
}

library in comments

pump.cpp (3.52 KB)

pump.h (1.2 KB)

pump.h:

#ifndef PUMP_H
#define PUMP_H



class pump
{

public:
 pump();
 pump(int pumpP);
 void setPumpCycle(int cycle);
 void setPumpTimerWatered(long pTimerW);
 void setPumpTimerDry(long pTimerDry);
 void setPumpDelayOn(long pDelayOn);
 void setPumpDelayOff(long pDelayOff);
 void setMoistureThreshold(int mThresh);
 void setMoisture(int moisture);
 void setLedPin(int led);
 void setPumpData(int cycle, int mThresh, int led);
 void setPumpTimers(long pTimerW, long pTimerD, long pDelayOn, long pDelayOff);
 void setPumpSafetyShutOff(unsigned long shutOffValue);
 int getMoistureThreshold();
 int getMoistureValue();
 long getPumpDelayOn();
 long getPumpDelayOff();
 long getPumpTimer();
 long getPumpTimerWatered();
 long getPumpTimerDry();
 unsigned long getCurrentMillis();
 unsigned long getPreviousMillis();
 unsigned long getPumpSafetyShutOff();
 void pumpFailSafe();
 void runPump();

private:
 int _pumpPin,
 _ledPin,
 _pumpCycle,
 _pumpSwitch,
 _moistureThreshold,
 _val;
 long _pumpDelayOn,
 _pumpDelayOff,
 _pumpTimer,
 _pumpTimerWatered,
 _pumpTimerDry;
 unsigned long _currentMillis,
 _previousMillis,
 _pumpSafetyShutOff;


 void runThePump();
};

#endif

and pump.cpp

#include "pump.h"
#include "Arduino.h"




int _pumpPin,
 _ledPin,
 _pumpCycle,
 _pumpSwitch = 0,
 _moistureThreshold,
 _val;
long _pumpDelayOn,
 _pumpDelayOff,
 _pumpTimer = 0, //value takes on others, so pump will test immediately when plugged in
 _pumpTimerWatered,
 _pumpTimerDry;
unsigned long _previousMillis = 0,
 _pumpSafetyShutOff = 3600000;


 pump::pump() {
 }
 pump::pump(int pumpP) {
 this->_pumpPin = pumpP;
 pinMode(_pumpPin, OUTPUT);
 }

 void pump::setPumpCycle(int cycle) {
 this->_pumpCycle = cycle;
 }

 void pump::setPumpTimerWatered(long pTimerW) {
 this->_pumpTimerWatered = pTimerW;
 }

 void pump::setPumpTimerDry(long pTimerD) {
 this->_pumpTimerDry = pTimerD;
 }

 void pump::setPumpDelayOn(long pDelayOn) {
 this->_pumpDelayOn = pDelayOn;
 }

 void pump::setPumpDelayOff(long pDelayOff) {
 this->_pumpDelayOff = pDelayOff;
 }

 void pump::setMoistureThreshold(int mThresh) {
 this->_moistureThreshold = mThresh;
 }

 void pump::setMoisture(int moisture) {
 this->_val = moisture;
 }

 void pump::setLedPin(int led) {
 this->_ledPin = led;
 pinMode(_ledPin, OUTPUT);
 }

 void pump::setPumpData(int cycle, int mThresh, int led) {
 this->_pumpCycle = cycle;
 this->_moistureThreshold = mThresh;
 this->_ledPin = led;
 pinMode(_ledPin, OUTPUT);
 }

 void pump::setPumpTimers(long pTimerW, long pTimerD, long pDelayOn, long pDelayOff) {
 this->_pumpTimerWatered = pTimerW;
 this->_pumpTimerDry = pTimerD;
 this->_pumpDelayOn = pDelayOn;
 this->_pumpDelayOff = pDelayOff;
 }
 void pump::setPumpSafetyShutOff(unsigned long shutOffValue) {
 this->_pumpSafetyShutOff = shutOffValue;
 } 

 int pump::getMoistureThreshold() {
 return _moistureThreshold;
 }

 int pump::getMoistureValue() {
 return _val;
 }

 long pump::getPumpDelayOn() {
 return _pumpDelayOn;
 }

 long pump::getPumpDelayOff() {
 return _pumpDelayOff;
 }

 long pump::getPumpTimer() {
 return _pumpTimer;
 }

 long pump::getPumpTimerWatered() {
 return _pumpTimerWatered;
 }

 long pump::getPumpTimerDry() {
 return _pumpTimerDry;
 }

 unsigned long pump::getCurrentMillis() {
 return _currentMillis;
 }

 unsigned long pump::getPreviousMillis() {
 return _previousMillis;
 }
 
 unsigned long pump::getPumpSafetyShutOff() {
 return _pumpSafetyShutOff;
 }
 
 void pump::pumpFailSafe()
 {
 unsigned long _cMils = millis();
 if (_cMils - _previousMillis >= _pumpSafetyShutOff)
 {
 digitalWrite(_pumpPin, LOW);
 digitalWrite(_ledPin, LOW);
 }
 }

 void pump::runPump() {
 runThePump();
 }


 void pump::runThePump() 
 {
 unsigned long _currentMillis = millis();
 if (_currentMillis - _previousMillis >= _pumpTimer) 
 {
 _previousMillis = _currentMillis;


 if (_val < _moistureThreshold)
 {
 for (int x = 0; x < _pumpCycle;) {
 if (_pumpSwitch == 0) {
 Serial.println("Turning pump On");
 digitalWrite(_pumpPin, HIGH);
 digitalWrite(_ledPin, HIGH);
 delay(_pumpDelayOn);
 _pumpSwitch = 1;
 }
 else if (_pumpSwitch == 1) {
 Serial.println("Turning pump Off");
 digitalWrite(_pumpPin, LOW);
 digitalWrite(_ledPin, LOW);
 if (x < _pumpCycle) {
 delay(_pumpDelayOff);
 }
 _pumpSwitch = 0;
 x++;
 }
 }
 _pumpTimer = _pumpTimerWatered;
 Serial.println("Exiting for loop");
 }
 else {
 _pumpTimer = _pumpTimerDry;
 Serial.println("Plant moisture is fine, Will check again in 6 hours");
 }
 } 
 }

:o :o :o :o edited weird spacing

pump.cpp declares some global variables with the same names as the class's private variables. You already #included the .h file, so the declarations inside the class are done.

I had to copy the code to run the autoformat on it. I hope that it's properly formatted on your end. It's unreadable to me without proper indenting.

You call pinMode() in one of the class constructors. While that probably will work, it's a bad idea in the Arduino to do any meaningful work at all in a constructor. The constructor is called before the Arduino helper functions are set up so you really should do all of that in a .begin() method.

Try NOT to write blocking methods. runThePump() seems to have a long loop with a lot of delay()s in it. Why should you allow your Arduino to get stuck in this loop when there's other useful things it could be doing, like running the other pump at the same time?

I promise the format is emmaculate on my end. its the copying and pasting it in here. sorry about that. I really do appreciate the time taken here. and these delays are all blink without delays in a library. this code has no delays....... which is my problem. the delays should be _pumpTimer =. My brain must have farted because I had it working and then not. . I have it set to run for 5 minutes, stop for 1, then run for 5 and so on to whatever the user sets then pause for whatever long. I have it set currently for 24 hours. I am trying to avoid flooding the plant and overheating the pump, but that gets into specifics. but in the end that is the issue. I have a delay in my blink without delay lol. thank you for your extra eyes. and your extra input on the correct format.

Ah the begin methods. Thank you for this as I see your point. even if it works, it isn't correct. like I said this is my first library. so really thank you for that one.

          if (x < _pumpCycle) {

delay(_pumpDelayOff);
          }



That most definitely is a delay. Many of them, since it's inside a loop. Coincidentally, a loop where x is checked to be less than _pumpCycle, so the if() is also unnecessary.

yes that is most definitely a delay. I am telling you that was the issue. I am unsure of what you are trying to tell me in the last reply. the code is fixed now. The redundant code you are pointing out is fixed as it was not supposed to be in the blink without delay. no other problems exist as I have deleted the issues you are pointing out.

Thank you for your help, this code needs no more troubleshooting, as you are troubleshooting a non existent code at this time. I will post it when I am home.

I must have hit ctrl z to many times or something because the code should be this and was this at one point. I do thank you for your help seeing this as sometimes its hard to see the problem. I didnt want you to diagnose an issue you already solved. here is the code now if you are curious. you will see an added boolean and everything. that last code was an abomination of the code before I implemented blink without delay.

#include "pump.h"
#include "Arduino.h"






pump::pump() {
}

void pump::pumpBegin(int pumpP) {
	this->_pumpPin = pumpP;
	pinMode(_pumpPin, OUTPUT);
}

void pump::setPumpCycle(int cycle) {
	this->_pumpCycle = cycle;
}

void pump::setPumpTimerWatered(long pTimerW) {
	this->_pumpTimerWatered = pTimerW;
}

void pump::setPumpTimerDry(long pTimerD) {
	this->_pumpTimerDry = pTimerD;
}

void pump::setPumpDelayOn(long pDelayOn) {
	this->_pumpDelayOn = pDelayOn;
}

void pump::setPumpDelayOff(long pDelayOff) {
	this->_pumpDelayOff = pDelayOff;
}

void pump::setMoistureThreshold(int mThresh) {
	this->_moistureThreshold = mThresh;
}

void pump::setMoisture(int moisture) {
	this->_val = moisture;
}

void pump::setLedPin(int led) {
	this->_ledPin = led;
	pinMode(_ledPin, OUTPUT);
}

void pump::setPumpData(int cycle, int mThresh, int led) {
	this->_pumpCycle = cycle;
	this->_moistureThreshold = mThresh;
	this->_ledPin = led;
	pinMode(_ledPin, OUTPUT);
}

void pump::setPumpTimers(long pTimerW, long pTimerD, long pDelayOn, long pDelayOff) {
	this->_pumpTimerWatered = pTimerW;
	this->_pumpTimerDry = pTimerD;
	this->_pumpDelayOn = pDelayOn;
	this->_pumpDelayOff = pDelayOff;
}

void pump::setPumpSafetyShutOff(unsigned long shutOffValue) {
	this->_pumpSafetyShutOff = shutOffValue;
}

int pump::getMoistureThreshold() {
	return _moistureThreshold;
}

int pump::getMoistureValue() {
	return _val;
}

long pump::getPumpDelayOn() {
	return _pumpDelayOn;
}

long pump::getPumpDelayOff() {
	return _pumpDelayOff;
}

long pump::getPumpTimer() {
	return _pumpTimer;
}

long pump::getPumpTimerWatered() {
	return _pumpTimerWatered;
}

long pump::getPumpTimerDry() {
	return _pumpTimerDry;
}

unsigned long pump::getCurrentMillis() {
	return _currentMillis;
}

unsigned long pump::getPreviousMillis() {
	return _previousMillis;
}

unsigned long pump::getPumpSafetyShutOff() {
	return _pumpSafetyShutOff;
}

void pump::pumpFailSafe()
{
	unsigned long _cMils = millis();
	if (_cMils - _previousMillis >= _pumpSafetyShutOff)
	{
		digitalWrite(_pumpPin, LOW);
		digitalWrite(_ledPin, LOW);
	}
}

void pump::runPump() {
	runThePump();
}



	void pump::runThePump()
	{
unsigned long _currentMillis = millis();
  if (_currentMillis - _previousMillis >= _pumpTimer) {
    _previousMillis = _currentMillis;

    if (_val < _moistureThreshold) {
      _test = true;
    } else {
      _test = false;
    }

    if (_test) {
      if (_pumpSwitch == 0) {
        Serial.println("Turning pump On");
        Serial.println(_test);
        digitalWrite(_pumpPin, HIGH);
        digitalWrite(_ledPin, HIGH);
        _pumpSwitch = 1;
        _pumpTimer = _pumpDelayOn;
        _x++;
      }
      else if (_pumpSwitch == 1) {
        Serial.println("Turning pump Off");
        digitalWrite(_pumpPin, LOW);
        digitalWrite(_ledPin, LOW);
        _pumpSwitch = 0;
        _pumpTimer = _pumpDelayOff;
      }
    }
    else {
      _pumpTimer = _pumpTimerDry;
      Serial.println("Plant moisture is fine, Will check again in 6 hours");
    }
    if (_x == _pumpCycle) {
      _x = 0;
      _pumpTimer = _pumpTimerWatered;;
      digitalWrite(_pumpPin, LOW);
      digitalWrite(_ledPin, LOW);
    }
  }
	}

thanks again