Reef Central Online Community
Premium Aquatics

Home Forum Here you can view your subscribed threads, work with private messages and edit your profile and preferences View New Posts View Today's Posts

Find other members Frequently Asked Questions Search Reefkeeping ...an online magazine for marine aquarists Support our sponsors and mention Reef Central

Go Back   Reef Central Online Community > General Interest Forums > Do It Yourself
Register Blogs FAQ Calendar Mark Forums Read

Notices

User Tag List

Reply
Thread Tools
Old 06/22/2014, 04:29 PM   #1
dudedudedude
Registered Member
 
Join Date: Nov 2006
Location: Virginia
Posts: 179
Universal Arduino Auto Top Off (ATO) Sketch Thread

Hello All,

There are many sketches out there for reef controllers but not too many of them include a robust auto top off function. My goal is to come up with the following sketch that could be added to any of the popular Arduino based reef controller sketches without issue. I have started out with a basic sketch but being more proficient with hardware than software I am asking for the communities help and input so that this goal can be reached.

My ideal ATO would consist of the following:

Hardware-
1) Low water level float switch
2) High water level- float witch
3) Relay to control water/air pump or solenoid.

Software Side-
1) Low water float switch activates relay

2) High water level float switch activates really

3) Failsafe A: If High water relay not activated by a selectable amount of time relay is turned off

4) Failsafe B: A selectable amount of time must past in order for the ATO to be activated again

5) Failsafe C: Float switch must be activated for a selectable amount (i.e. 3 seconds) to lead to change in relay behavior (protects from temporary changes in water level

6) Must be coded without code such as delay () so that the code can be easily inserted into preexisting reef controller sketches without much issue.


Below is the code I have made that covers coding issue 1) and 2). What I can not figure out is how to add the three failsafes.

Code:
// constants won't change. They're used here to
// set pin numbers:
const int sensorPin[] = {2,3};     // the number of the float switch pins
const int pumpPin =  12;      // the number of the relay pin

// variables will change:
int sensorState = 0;         // variable for reading the float switch status

void setup() {
  // initialize the relay pin as an output:
  pinMode(pumpPin, OUTPUT);     
  // initialize the floatswitch pin as an input:
  for(int x=0; x<2; x++)
  {
    pinMode(sensorPin[x], INPUT); 
  }  
}

void loop(){
  // read the state of the float switch value:
  for(int x=0; x<2; x++)
  {
    sensorState = digitalRead(sensorPin[x]);

    // check if the float switch is activated.
    // if it is, the sensorState is HIGH:
    if (sensorState == HIGH && sensorPin[x] == 2) {    
      // turn LED on:   
      digitalWrite(pumpPin, HIGH); 
    }
    if (sensorState == HIGH && sensorPin[x] == 3) {
      // turn relay off:
      digitalWrite(pumpPin, LOW);
    }
  }
}
Thanks in advance for any input.

Sean



Last edited by dudedudedude; 06/22/2014 at 05:03 PM.
dudedudedude is offline   Reply With Quote
Old 06/23/2014, 06:14 AM   #2
ElmoC
Registered Member
 
Join Date: Jun 2013
Posts: 93
Since you are more familiar with hardware, maybe you could help by coming up with a better detector than a float switch. There are lots of horror stories of their failures. I know with the failsafes it helps eliminate them, but personally, I just don't like them.

I have a Smart ATO from AutoAqua. The thing I like about it was it uses and optical sensor and is very compact. It also comes with the pump for it is a complete unit. But one thing I did was to create an adapter on the pump's power line using a mosfet to signal my Apex when it runs. That gives me a way to log when it runs and also another failsafe. If the Apex detects it running too long, it can shut it down. Using this method, it would be fairly simple to interface it into a DIY controller to do the same thing.


ElmoC is offline   Reply With Quote
Old 06/23/2014, 06:05 PM   #3
dudedudedude
Registered Member
 
Join Date: Nov 2006
Location: Virginia
Posts: 179
Quote:
Originally Posted by ElmoC View Post
Since you are more familiar with hardware, maybe you could help by coming up with a better detector than a float switch. There are lots of horror stories of their failures. I know with the failsafes it helps eliminate them, but personally, I just don't like them.

I have a Smart ATO from AutoAqua. The thing I like about it was it uses and optical sensor and is very compact. It also comes with the pump for it is a complete unit. But one thing I did was to create an adapter on the pump's power line using a mosfet to signal my Apex when it runs. That gives me a way to log when it runs and also another failsafe. If the Apex detects it running too long, it can shut it down. Using this method, it would be fairly simple to interface it into a DIY controller to do the same thing.
Well, part of the point is to save money by DIY so I am looking for something that uses cheap parts. However, it would be possible to replicate the Smart ATO with Infrared optical water level sensor switches rather than mechanical float switches which can be had for $20-$30 a pair. Regardless, I want coding that has those additional failsafes.


dudedudedude is offline   Reply With Quote
Old 06/23/2014, 07:16 PM   #4
ElmoC
Registered Member
 
Join Date: Jun 2013
Posts: 93
The SmartATO was more an example of alternative sensors to float switches. I had looked for something else, but nothing really stood out. I'm on the software side of things and what you are wanting is not that difficult. What you do is when one of the failsafe events happen, record the time using millis. When the event occurs again, check the current millis (milliseconds since the program started running) and see if enough time has passed. In the main loop, you can check for elapsed time since the event and act accordingly.

Now the value returned by millis will reset about every 50 days. So you will need to check if the current time is less than the start time, meaning it wrapped and have to adjust accordingly.


ElmoC is offline   Reply With Quote
Old 06/24/2014, 06:34 AM   #5
Yodeling
Registered Member
 
Yodeling's Avatar
 
Join Date: May 2004
Location: Atlanta
Posts: 556
Something like this should work similarly to the tunze electronic eye.


Yodeling is offline   Reply With Quote
Old 06/24/2014, 07:56 AM   #6
kaskiles
Registered Member
 
Join Date: Oct 2004
Location: Merritt Island, FL
Posts: 726
I use an RTC and explicit start/stop times during the day as a fail-safe. So the fill pump can only run for 1 minute, but if the high top pops before the minute expires, the pump is stopped. Then I set 4 of these start/stop times per day.

There is a pressure sensor that Reef Angel has used to determine the level, I've been planning to replace my floats with it someday... I believe it's made by Freescale.


kaskiles is offline   Reply With Quote
Old 06/24/2014, 11:31 AM   #7
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Quote:
Originally Posted by ElmoC View Post

Now the value returned by millis will reset about every 50 days. So you will need to check if the current time is less than the start time, meaning it wrapped and have to adjust accordingly.
Not if you understand how unsigned int math works you don't.

millis() returns an unsigned long, so that's the type you should be storing these things in. With unsigned math, all you need to do is use subtraction instead of addition and the rollover works itself out for you.

ie.

if (currentMillis - previousMillis > interval) {
// code
}

Here, if currentMillis is 10 because it just had a rollover and previousMillis is 4,294,967,285 (10 millisecconds away from rollover) then

currentMillis - previousMillis == 10 - 4294967285 == 20

So you get the 20 milliseconds, exactly the right amount of time. Sure millis rolled over, but so did your unsigned math.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/24/2014, 05:04 PM   #8
ElmoC
Registered Member
 
Join Date: Jun 2013
Posts: 93
Quote:
Originally Posted by disc1 View Post
Not if you understand how unsigned int math works you don't.
I was just about to post a follow up on that to correct my error. I had several things going on at the time I wrote that and got them all mixed up.


ElmoC is offline   Reply With Quote
Old 06/24/2014, 06:40 PM   #9
dudedudedude
Registered Member
 
Join Date: Nov 2006
Location: Virginia
Posts: 179
Quote:
Originally Posted by disc1 View Post
Not if you understand how unsigned int math works you don't.

millis() returns an unsigned long, so that's the type you should be storing these things in. With unsigned math, all you need to do is use subtraction instead of addition and the rollover works itself out for you.

ie.

if (currentMillis - previousMillis > interval) {
// code
}

Here, if currentMillis is 10 because it just had a rollover and previousMillis is 4,294,967,285 (10 millisecconds away from rollover) then

currentMillis - previousMillis == 10 - 4294967285 == 20

So you get the 20 milliseconds, exactly the right amount of time. Sure millis rolled over, but so did your unsigned math.
David, you seam to be a Arduino Guru based on many posts I have seen. I understand the coding for milis() to do a blinkwithdelay example. But how would I code so that the mills() starts when the pumpPin turns on and then can be used to override a stuck high water float switch, i.e. makes pumpPin low after something like long interval = 120000 regardless of float switch status.


dudedudedude is offline   Reply With Quote
Old 06/24/2014, 08:56 PM   #10
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
This is a pretty simple code. You've got one thing you're controlling, a pump, so let's put that on a pin and hook it to a relay. HIGH turns the pump on and LOW turns it off.

Deciding to turn the pump on requires three things to be true, the low water switch has to be down, AND it has to have been down for the three seconds, AND it has to have been enough time since the last time the pump ran. So that's one if statement with three conditions &&'ed together.

Deciding to turn the pump off requires one of two things, either the high water switch is up OR the pump has been on for longer than a certain amount of time. So that's an if statement with 2 conditions ||'ed together.

I split out the test for the pump running to keep the if statements from getting too clogged, but this could be done in just two or three lines if you really wanted to.


Code:
byte lowWaterPin = 6;    // Goes LOW when water below switch
byte highWaterPin = 7;   // Goes LOW when water below switch
byte pumpPin = 8;        // Relay to control the water pump


unsigned long maxRunTime = 60 * 1000L;   // pump on for max of one minute
unsigned long minOffTime = 60 * 60 * 1000L;  // pump must be off for at least one hour
unsigned long switchDebounceTime = 3 * 1000L;  // Switch must be activated for at least 3 seconds.

unsigned long lastPumpTime = 0;

unsigned long lastLowWaterDetectTime = 0;
boolean lastLowWaterState = HIGH;

boolean pumpRunning = false;


void setup(){
  pinMode(lowWaterPin, INPUT_PULLUP);
  pinMode(higheWaterPin, INPUT_PULLUP);
  pinMode(pumpPin, OUTPUT);
}

void loop(){

  unsigned long currentMillis = millis;

  boolean lowWaterState = digitalRead(lowWaterPin);
  boolean highWaterState = digitalRead(highWaterPin);

  if(lowWaterState != lastLowWaterState){
    lastLowWaterDetectTime = currentMillis;
  }


  if (pumpRunning) {  // if the pump is on then let's see if we should turn it off yet

    if ((highWaterState == HIGH) || (currentMillis - lastPumpTime >= maxRunTime)){
      digitalWrite(pumpPin, LOW);
      pumpRunning = false;
      lastPumpTime = currentMillis;
    }
  }
  else {   // pump is not running, see if we need to turn it on

      if((lowWaterState == LOW)  &&  (currentMillis - lastLowWaterDetectTime >= switchDebounceTime) && (currentMillis - lastPumpTime > minOffTime)){   // switch is low and has been for at least 3 seconds
        digitalWrite(pumpPin, HIGH);
        pumpRunning = true;
        lastPumpTime = currentMillis;
      }
  }

  lastLowWaterState = lowWaterState;

}



__________________
David


Current Tank: Undergoing reconstruction...

Last edited by Sugar Magnolia; 06/25/2014 at 04:50 PM.
disc1 is offline   Reply With Quote
Old 06/25/2014, 04:26 PM   #11
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
hello all

I just found this thread and am starting to work on my ATO system code for my new double 40B display it was posted at a very good time for me!!

Disc1 when i compile your sketch it gives me an error of "currentMillis' cannot be used as a function" in the second to last line of your sketch.

I would like to incorporate a code like this into my sketch but also include ping sensors to do the actual monitoring of the water levels with floats as a mechanical back-up or vice versa and timers as extra back-up for system problems.

could you tell me what is causing this error on compiling and possibly give me some direction as to how to incorporate the ping sensors into the sketch

thanks for any help in my project
James


jc286006 is offline   Reply With Quote
Old 06/25/2014, 04:38 PM   #12
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Oops. My bad. The code was simple enough that I didn't bother to compile it and I missed a typo there.

Take the parenthesis off currentMillis. The parenthesis are for calling a function and currentMillis is a variable not a function.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/25/2014, 04:46 PM   #13
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
thanks for your extremely fast reply to that question!

do you see a possibility that ping sensors could be incorporated into this sketch?

either as the main control or the secondary back-up

thanks James


jc286006 is offline   Reply With Quote
Old 06/25/2014, 08:56 PM   #14
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
You mean a ping pointed at the water to get the level? I don't know if that works or not but it would be super easy to code if it does. Just read the ping sensor instead of a digital pin and test for the distance instead of a pin state.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/25/2014, 10:05 PM   #15
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Quote:
Originally Posted by disc1 View Post
Oops. My bad. The code was simple enough that I didn't bother to compile it and I missed a typo there.

Take the parenthesis off currentMillis. The parenthesis are for calling a function and currentMillis is a variable not a function.
Thanks Sugar Mag for fixing that. There's no error in that post anymore.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/26/2014, 05:20 PM   #16
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
i have made modifications to the sketch you posted inserting the ping sensors so far it compiles but when i try to insert what levels the ATO pump should turn on and off at i get errors
Code:
include 

#define SONAR_NUM     3 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 1000 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).



unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(22, 23, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(24, 25, MAX_DISTANCE),
  NewPing(26, 27, MAX_DISTANCE),
};

byte atoSensor = (cm[0] );    // sensor to activate RO/DI filter to refill ATO holding tank
byte waterchangeSensor = (cm[1] ); // sensor to activate RO/DI filter to refill water change holding tank
byte displaySensor = (cm[2] ); // sensor to activate ATO pump to maintain water level in display tank
byte pumpPin1 = 31;  // Relay to control the water pump for ATO system
byte rodiPin =32; // Relay to control RO/DI filter 

unsigned long maxRunTime = 60 * 1000L;   // pump on for max of one minute
unsigned long minOffTime = 60 * 60 * 1000L;  // pump must be off for at least one hour
unsigned long switchDebounceTime = 3 * 1000L;  // Switch must be activated for at least 3 seconds.

unsigned long lastPumpTime = 0;

unsigned long lastLowWaterDetectTime = 0;
boolean lastLowWaterState = HIGH;

boolean pumpRunning = false; 


void setup() {

  pinMode(pumpPin1, OUTPUT); 
  pinMode(atoSensor, INPUT);
  pinMode(waterchangeSensor, INPUT);
  pinMode(displaySensor, INPUT);
  Serial.begin(9600);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }
  unsigned long currentMillis = millis();

  boolean lowWaterState = digitalRead(displaySensor);
  boolean highWaterState = digitalRead(displaySensor);

  if(lowWaterState != lastLowWaterState){
    lastLowWaterDetectTime = currentMillis;
  }


  if (pumpRunning) {  // if the pump is on then let's see if we should turn it off yet

    if ((highWaterState == HIGH) || (currentMillis - lastPumpTime >= maxRunTime)){
      digitalWrite(pumpPin1, LOW);
      pumpRunning = false;
      lastPumpTime = currentMillis;


    }
  }
  else {   // pump is not running, see if we need to turn it on

    if((lowWaterState == LOW)  &&  (currentMillis - lastLowWaterDetectTime >= switchDebounceTime) && (currentMillis - lastPumpTime > minOffTime)){   // switch is low and has been for at least 3 seconds
      digitalWrite(pumpPin1, HIGH);
      pumpRunning = true;
      lastPumpTime = currentMillis;
    }

  }

  lastLowWaterState = lowWaterState;



}



void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {



    Serial.print(i);
    Serial.print("=");
    Serial.print(cm[i]);
    Serial.print("cm ");
  }
  Serial.println();
}
i assume these values should be inserted in the high and low water states == areas but when i have tried this i get errors when you would have time to look at this and offer any suggestions it would be greatly appreciated and as you can see i plan on implementing this sketch to control the ATO holding Tank,water change tank and the display tank water levels if you think it would be possible
thanks for any input James



Last edited by jc286006; 06/26/2014 at 05:31 PM.
jc286006 is offline   Reply With Quote
Old 06/26/2014, 06:14 PM   #17
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
got it to compile with the sensor values i want for a test but the led i am using to simulate a relay load will not light any suggestions were i am not doing something right
Code:
#include 

#define SONAR_NUM     3 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 1000 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).



unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(22, 23, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(24, 25, MAX_DISTANCE),
  NewPing(26, 27, MAX_DISTANCE),
};

byte atoSensor = (cm[0] );    // sensor to activate RO/DI filter to refill ATO holding tank
byte waterchangeSensor = (cm[1] ); // sensor to activate RO/DI filter to refill water change holding tank
byte displaySensor = (cm[2] ); // sensor to activate ATO pump to maintain water level in display tank
byte pumpPin1 = 31;  // Relay to control the water pump for ATO system
byte rodiPin =32; // Relay to control RO/DI filter 

unsigned long maxRunTime = 60 * 1000L;   // pump on for max of one minute
unsigned long minOffTime = 60 * 60 * 1000L;  // pump must be off for at least one hour
unsigned long switchDebounceTime = 3 * 1000L;  // Switch must be activated for at least 3 seconds.

unsigned long lastPumpTime = 0;

unsigned long lastLowWaterDetectTime = 0;
boolean lastLowWaterState = HIGH;

boolean pumpRunning = false; 


void setup() {

  pinMode(pumpPin1, OUTPUT); 
  pinMode(atoSensor, INPUT);
  pinMode(waterchangeSensor, INPUT);
  pinMode(displaySensor, INPUT);
  Serial.begin(9600);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }
  unsigned long currentMillis = millis();

  boolean lowWaterState = digitalRead(displaySensor);
  boolean highWaterState = digitalRead(displaySensor);

  if(lowWaterState != lastLowWaterState){
    lastLowWaterDetectTime = currentMillis;
  }

 if (pumpRunning) {  // if the pump is on then let's see if we should turn it off yet

    if ((highWaterState == displaySensor <15) || (currentMillis - lastPumpTime >= maxRunTime)){
      digitalWrite(pumpPin1, HIGH);
      pumpRunning = false;
      lastPumpTime = currentMillis;


    }
  }
  else {   // pump is not running, see if we need to turn it on

    if((lowWaterState == displaySensor  >50)  &&  (currentMillis - lastLowWaterDetectTime >= switchDebounceTime) && (currentMillis - lastPumpTime > minOffTime)){   // switch is low and has been for at least 3 seconds
      digitalWrite(pumpPin1, LOW);
      pumpRunning = true;
      lastPumpTime = currentMillis;
    }

  }

  lastLowWaterState = lowWaterState;



}



void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {



    Serial.print(i);
    Serial.print("=");
    Serial.print(cm[i]);
    Serial.print("cm ");
  }
  Serial.println();
}



jc286006 is offline   Reply With Quote
Old 06/26/2014, 06:46 PM   #18
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Probably not your problem, but will become a problem after it runs for about 49 days...

This:

Code:
if (millis() >= pingTimer[i])
is the wrong way.

Look at how I did it in the sketch a few posts up or how it is done in the glorious blink Without Delay sketch. You don't keep up with the next time it needs to run. You keep up with the last time it ran and the interval it is supposed to wait. You'll find that as you do this, a lot of the complications in your above code will disappear.


Then this line:
Code:
pingTimer[i] += PING_INTERVAL * SONAR_NUM;
If the times are already staggered, you don't need to multiply by the sonar number anymore. You just need to add the interval.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/26/2014, 06:59 PM   #19
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Code:
 boolean lowWaterState = digitalRead(displaySensor);
  boolean highWaterState = digitalRead(displaySensor);
What the heck is this?

You set displaySensor = cm[2] for some reason. cm[2] was zero at that point in time. So what do you have connected to pin 0?



Then on this line:

Code:
if ((highWaterState == displaySensor <15) || (currentMillis - lastPumpTime >= maxRunTime))
Specifically this part:

Code:
(highWaterState == displaySensor <15)
What do you think this means? It is syntactically correct, but I wonder if you understand it. displaySensor is still equal to 0, cause nowhere in this code do you ever tell it to be anything else. So it will always be less than 15. So the right side of that will always be true, so it really just tests if highWaterState (which is a digitalRead on pin 0 remember) is HIGH. Is that really what you want to do here?


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/26/2014, 07:02 PM   #20
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Explain what you think this part does too please. echoCheck is a function. You can't use it this way. But I can't understand what you want it to do well enough to tell you how to fix it.

Code:
sonar[currentSensor].ping_timer(echoCheck);
...

Code:
void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}



__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/26/2014, 08:19 PM   #21
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Quote:
Originally Posted by disc1 View Post
Explain what you think this part does too please. echoCheck is a function. You can't use it this way. But I can't understand what you want it to do well enough to tell you how to fix it.

Code:
sonar[currentSensor].ping_timer(echoCheck);
...

Code:
void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

OK, after going through the NewPing library a bit i get what you have going on here. I didn't realize that timer function took a callback. I thought it was supposed to take a reference to where to store the data.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/26/2014, 11:30 PM   #22
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
hello i got the time roll over issue fixed per the blink without delay sketch

cm[0],cm[1],cm[2] are the three ping sensors. in a sketch i have them working to return distance values but to get them to power the led for each load simulation i plan to use them to monitor, they had to be shown like this in the code
Code:
 void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    if(cm[0] < 15)
      digitalWrite(ledPin1,HIGH);
    else
      digitalWrite(ledPin1,LOW);

    if(cm[1] < 15)
      digitalWrite(ledPin2,HIGH);
    else
      digitalWrite(ledPin2,LOW);

    if(cm[2] < 15)
      digitalWrite(pumpPin,HIGH);
    else
      digitalWrite(pumpPin,LOW);
that is why byte displaySensor = (cm[2] ); made me assume that lowWaterState = digitalRead(displaySensor); needed to be written this way

in the first post i hurried through it and didnt name them correctly for what i had planned on using each one for in this sketch. sorry about that!!!

this sketch only deals with one of sensors jobs as i said in the first posting of code i hope that it can be expanded to encompass management of the ATO system for the display tank , the refilling of the ATO storage tank ,and the water change storeage tank.
in this statement i assumed that cm[2] could be used to give a value in both states
Code:
 boolean lowWaterState = digitalRead(displaySensor);
  boolean highWaterState = digitalRead(displaySensor);
then on this line
Code:
(highWaterState == displaySensor <15)
again i assumed that all i had to do was insert the value of the ping sensors reading for the upper limit of the water level in my sump tank


jc286006 is offline   Reply With Quote
Old 06/27/2014, 08:17 AM   #23
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
I'm reading your post above and it doesn't make a lot of sense to me. I'm still stuck on what exactly you think those digitalRead lines do. digitalRead reads the state of a digital pin. What you've got in that line has nothing at all to with any digital pins.

Now you've got this part:
Code:
for (uint8_t i = 0; i < SONAR_NUM; i++) {
    if(cm[0] < 15)
      digitalWrite(ledPin1,HIGH);
    else
      digitalWrite(ledPin1,LOW);

    if(cm[1] < 15)
      digitalWrite(ledPin2,HIGH);
    else
      digitalWrite(ledPin2,LOW);

    if(cm[2] < 15)
      digitalWrite(pumpPin,HIGH);
    else
      digitalWrite(pumpPin,LOW);
You're running a for loop but you're checking all three distances in each iteration. So you're doing each check three times. Either use the for loop and check one sensor per loop or check each sensor individually and ditch the for loop.

I'm starting to think maybe you don't have much experience or knowledge with C++ or with Arduino and if that is the case then this project is probably a bit over your head. Go back through some examples and make LED's flash and read some simple buttons and such. Learn what the commands like digitalRead and digitalWrite do and learn how for loops and arrays actually work. Once you have that under your belt, this code will be trivial.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Old 06/27/2014, 11:17 AM   #24
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
hello david
No I don`t know C++ all I know is what I have read on the internet about arduino and its code in tutorials I am not schooled in programming I am not a dumb person just not taught in the correct way of doing things. The bit of code I posted was part of the 15 sensor ping example that is in the new ping library. I got that sketch modified to return values for the 3 ping sensors I am using and lighting leds to simulate the load that I want to control but as you can see it only senses the high/full water level.
The modifications I posted above to the 15 sensor example sketch were from suggestions from people at the arduino forum. I was hoping to incorporate the sketch you posted in this thread and the new ping sketch together to use each of the 3 sensors to control not only the high/full water level but to also control when a pump for the ATO and the solenoid controlling my RO/DI filter would turn on at a certain lower level and run for so many minutes until the upper limit was met so that they were not pulsing on and off at short intervals.I will read more at the arduino site and try everything i can learn before posting code for help
thanks james


jc286006 is offline   Reply With Quote
Old 06/27/2014, 11:47 AM   #25
_shorty_
Registered Member
 
_shorty_'s Avatar
 
Join Date: May 2010
Location: Decatur, IL
Posts: 1,048
i like the ping sensor idea! Anyone tried this in a sump before?


_shorty_ is offline   Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump


All times are GMT -6. The time now is 10:55 AM.


TapaTalk Enabled

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
Powered by Searchlight © 2021 Axivo Inc.
Use of this web site is subject to the terms and conditions described in the user agreement.
Reef CentralTM Reef Central, LLC. Copyright 1999-2014
User Alert System provided by Advanced User Tagging v3.3.0 (Pro) - vBulletin Mods & Addons Copyright © 2021 DragonByte Technologies Ltd.