Water Tank Monitor Using Hall Effect Switches

@aiannarelli, PVC compatibility is questionable with those acids depending on the concentrations.


As you know, the IBC totes are vented at the top, which allows air to enter the tanks when liquid leaves.
You will need to maintain a Vent Path if you plan to use the 2" port in the Center of the Screw Cap for your instrumentation.
You might be able to use a PVC distributor in some way for this, IDK ?
image

I agree with @seulater, the industry has moved to radar for this "severe-duty" chemical application.
Radar is hard to justify for every IBC tote, so I hope you are successful with a cheaper alternative.

Rftop - I read I think that same chart. I need to check the acid concentrations and if need be change to HDPE. I found it interesting that concentration of hydrochloric was worse than the middle concentration.

Lots of people sell PTFE (teflon) float switches in both the free-floating and around-a-pole styles. I wouldn’t bother with PVC.

1 Like

To follow the level of our pits we use a sensor LIDAR-Lite v3hp IPx7

It is often under water is continues to give us very precise values ​​on the water level.

https://buy.garmin.com/en-US/US/p/578152

Hello @Ric, I am curious about the OneShot utility you have at the top of your code. Is it something you wrote, or can you point me to a link? I have not been able to find it on this forum or the user docs.

Yes, that is something I wrote. I have a file called Extras where I put some utility methods. It has a couple of simple timers and a method to take care daylight savings time. Here’s the code for the .h file

#include "Particle.h"

void setZone();


enum Unit {
    MILLIS, SECONDS, MINUTES
};


class Wait {

    public:

		Wait(unsigned long period, enum Unit unitOfTime);
		void begin();
        bool isUp(void);
		void reset();

	private:

        unsigned long start;
        unsigned long waitTime = 0;
};




class OneShot {

public:

	OneShot(int hour, int minute);
	bool fired(void);
	void cancel();

//private:

	int timeToFire;
	int weekdayToFire;
};

Here is the .cpp file,

#include "Extras.h"
#include "Particle.h"

void setZone() {
	int month = Time.month();
	int day = Time.day();
	int weekday = Time.weekday();
	int previousSunday = day - weekday + 1;

	if (month < 3 || month > 11) {
		Time.zone(-8);
	}else if (month > 3 && month < 11) {
		Time.zone(-7);
	}else if (month == 3) {
		int offset = (previousSunday >= 8)? -7 : -8;
		Time.zone(offset);
	} else{
		int offset = (previousSunday <= 0)? -7 : -8;
		Time.zone(offset);
	}
}


 Wait::Wait(unsigned long period, enum Unit unitOfTime) {
	 unsigned long multiplier;
     switch (unitOfTime) {
         case MILLIS:
            multiplier = 1;
            break;
         case SECONDS:
            multiplier = 1000;
            break;
         case MINUTES:
            multiplier = 60000;
            break;
     }

	 waitTime = period * multiplier;
 }


 void Wait::begin() {
	 start = millis();
 }


 bool Wait::isUp() {
     if (millis() - start >= waitTime) {
         start = millis();
         return true;
     }else{
         return false;
     }
 }

 void Wait::reset() {
	 start = millis();
 }


 OneShot::OneShot(int hour, int minute) { // timer for once a day events
	 setZone();
	 timeToFire = hour * 60 + minute;
	 if (timeToFire < (Time.hour() * 60  + Time.minute())) {
		 weekdayToFire = (Time.weekday() % 7) + 1;
	 }else{
		 weekdayToFire = Time.weekday();
	 }
 }




 bool  OneShot::fired() {
	int theTime = Time.hour() * 60 + Time.minute();
 	if (theTime >= timeToFire && weekdayToFire == Time.weekday()) {
 		weekdayToFire = (weekdayToFire % 7) + 1; // setup for the next day to run again
 		return true;
	}else{
 		return false;
 	}
 }

1 Like

Thanks for sharing, @Ric . I am looking for a simple scheduler that works with time of day, so I don’t have to count millis or create crazy data structures.
I am going to show my lack of programming skills, so how would I modify the OneShot object without reflashing the FW? IOW: I want to change a timer from an external input (e.g., Particle.function), say from 6AM to 7AM.
Looks like I could make a new method to reach into the timer definition to change the variable timeToFire, but I don’t understand if the scope of this variable includes the main loop() function.

I think that should work. You could add an update function which probably should look like the constructor, but without the call to setZone(),

OneShot::update(int hour, int minute) { // timer for once a day events
	 timeToFire = hour * 60 + minute;
	 if (timeToFire < (Time.hour() * 60  + Time.minute())) {
		 weekdayToFire = (Time.weekday() % 7) + 1;
	 }else{
		 weekdayToFire = Time.weekday();
	 }
 }
1 Like

Got it. I’ll play with that. Thanks.