Reef Central Online Community

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

Notices

User Tag List

Reply
Thread Tools
Unread 06/27/2014, 12:27 PM   #26
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
doughboy has mentioned this idea but didn`t elaborate on his success or failure with them i have read posts on other forums that say they work that is why i am working towards their use along with regular float switches and a timed feed for over-fill prevention


jc286006 is offline   Reply With Quote
Unread 06/27/2014, 12:45 PM   #27
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Quote:
Originally Posted by jc286006 View Post
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

The problem is that you are trying to jam ping sensors into code that was written for float switches. That's not ever going to work. Float switches give a high or low logic level when the water hits a certain point. Ping sensors give you the distance to the water. You're going to have to use those two pieces of information differently.

The code you've got should be able to get the distance to the water pretty easily. That's the top section of your code. Now instead of trying to copy what I did for a float switch, go in there and make it work for distance readings. So I imagine you're still going to have one section that looks at what to do if the pump is running and another section for what to do if it is not running. But instead of checking the state of a digital pin to determine if it is time to change the state of the pump you should be looking at the distance you've measured. You've got it in that nice cm array, use it.

Something like this (but probably not exactly like it)

Code:
if (pumpRunning) {  // pump is on see if it is time to turn it off
  if(cm[2] < highWaterDistance){
    //turn off the pump
  }
} else {   // pump is not running, see if it is time to turn it on
  if(cm[2] > lowWaterDistance{
    // turn the pump on
  }
}

That's all assuming cm[2] is holding the reading in centimeters that you want. You've determined the distance to the water, now just see if that is too high or too low. Just compare it to where you want it to be. There's nothing complicated about it. If you want to add the time stuff into those if statements to make sure it can't run for longer than a set amount of time or whatever like we did above then do that. But use your distance data, don't try to jam distance data in where we were using a pin state.


__________________
David


Current Tank: Undergoing reconstruction...
disc1 is offline   Reply With Quote
Unread 06/27/2014, 12:51 PM   #28
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
doughboy posted a thread about using the ping sensors and have found other peoples posts on other forums about their use so thats why i am working with them i want to use regular float switches as well as a timer back up to prevent over-fills from happening


jc286006 is offline   Reply With Quote
Unread 06/27/2014, 12:55 PM   #29
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
had computer problem i didnt think the other reply posted sorry for the double post


david thank you for the guidance when i have something working i will post my code for further direction and improvements since i am learning this i know i will be making mistakes


jc286006 is offline   Reply With Quote
Unread 06/27/2014, 01:51 PM   #30
_shorty_
Registered Member
 
_shorty_'s Avatar
 
Join Date: May 2010
Location: Decatur, IL
Posts: 1,048
Quote:
Originally Posted by jc286006 View Post
had computer problem i didnt think the other reply posted sorry for the double post


david thank you for the guidance when i have something working i will post my code for further direction and improvements since i am learning this i know i will be making mistakes
Definitely interested in hearing how it works out for you and seeing some tested code. I may have to utilize this if it works out. I just installed a new sump and was thinking about a better way to do this than what i've done in the past.


_shorty_ is offline   Reply With Quote
Unread 06/27/2014, 03:25 PM   #31
disc1
-RT * ln(k)
 
disc1's Avatar
 
Join Date: Sep 2010
Location: Little Rock
Posts: 9,705
Quote:
Originally Posted by jc286006 View Post
since i am learning this i know i will be making mistakes
That's what learning is. And anyone who thinks they're special because they know more than you about it is forgetting that once upon a time they were learning as well.

The problem is, and you'll really see it on the Arduino forum, is that there really isn't a way to critique a code and fix it AND have the person understand what you did without coming off as condescending. I have to ask questions like, "What do you think this does" to try to understand what you are wanting to do so I can help. But at the same time that question comes off really harsh. I don't know what can be done about it. But if you can put on your thick skin, go over to the Arduino forum and post some code and let those guys teach you. Just don't get frustrated or offended.

People who are new to coding tend to get lost in syntax and command names and stuff. Programming is a logic exercise. You should be able to sit down and write out what you want to do in plain english (or whatever language you happen to speak best) first so that you create a logical algorithm for what you want to do. Then you just translate that into code. Once you learn to do that, it doesn't matter what language you need to code in. You can look up syntax online all day. But there are only a few basic logical steps that you can take. If, while, do, <, >, equal to, store a number in memory, retrieve a number from memory. Even the for loop really just breaks down to just a fancy short way to write a specific kind of while loop.

Watch this. Let's develop a basic ping code for one sensor. If I wanted three different sensors doing three different but similar jobs, that's how I would write the code. Write it for one sensor, then encapsulate that and create three instances of it. When you combine all that stuff in the main code, it means that if you want to add a fourth or take one away you're going to have to do a lot of fixing and hacking and debugging of that very complex code. I really like java, and I'm hooked on the object oriented programming style. You should look into how that works.




So let's start by stating what we want to do. Let's say I've already measured the distance from where I'm mounting the sensor to the water levels and I want the low water level to be 22cm below the sensor and the high water level to be 12cm below the sensor. So my main statement written in plain english is going to be:

Get the distance from the sensor to the water in centimeters and store that in a variable. If the pump isn't running and that distance is greater than 22cm then turn the pump on. If the pump is running and that distance is less than or equal to 12cm then turn the pump off.

So I obviously need a few things here. I need a function to read the sensor. I need a function to turn the pump on and off. I need to keep track of whether or not the pump is running. No problem, let's write some code...

Here's what we need for the pump.

Code:
const byte pumpPin = 8;   //  Use for whatever pin drives your relay that turns the pump on and off.  HIGH turns the pump on.
boolean pumpIsRunning = false;  //  A boolean variable to keep up with the state of the pump

void turnPumpOn(){
  digitalWrite(pumpPin, HIGH);
  pumpIsRunning = true;
}

void turnPumpOff(){
  digitalWrite(pumpPin, LOW);
  pumpIsRunning = false;
}
Now we don't need to keep track of both things and turning the pump on or off happens by an obvious name so we can read our code like english later.

And the sensor. Look, I know you have been told to avoid blocking code. And yes that is always a good idea. But we are talking about a fish tank controller, not the space shuttle. The ping is going to bounce back in a matter of microseconds. We can wait a few microseconds. So we're going to go ahead and use the blocking function from the NewPing library, ping_cm(). That function returns an unsigned int, so a number that can't be less than 0. And if it doesn't get an echo it returns 0.

So let's write that part.

Code:
const byte triggerPin = 4;
const byte echoPin = 5;
const unsigned int maxDistance = 60;  //  The distance in cm to the bottom of the sump would be a good number here. 
unsigned int waterLevel;   // A variable so we can keep up with the water level when we read it.  


NewPing sonar(triggerPin, echoPin, maxDistance);   //  Create the NewPing instance

// returns the water levle as an unsigned int in centimeters as the distance from the sensor to the water 
//  Larger distance means a lower water level!!!
unsigned int checkWaterLevel(){
  unsigned int distance = sonar.ping_cm();
  return distance;
}
If this gets stuck for any reason, ping_cm() returns a 0 if it times out. That makes it look like the water is touching the sensor. That would turn the pumps off. That's good since a failure would result in pumps off instead of pumps on.

OK, setup is pretty easy. The NewPing obviously takes care of itself from the examples. We do need to set a pinMode for that pump, and let's do a digtialWrite too to make for certain it is turned off.

Code:
void setup(){
  pinMode(pumpPin, OUTPUT);  // need an output pin to drive the pump.
  digitalWrite(pumpPin, LOW);
}


And this pretty much looks like what we want to say for the loop on our simplest case. We check to see if enough time has past since the last sensor read, and if so we go ahead and take a new reading. Otherwise we just keep spinning around with the one we already had.

The we look to see if the pump is running or not. That's the main thing that determines which road we'll take. One way we're thinking about turning it off and the other way we're thinking about turning it on. There's no reason to mash those two different parts of the code together.

To see if we need to take action with the pump, we'll compare the waterLevel we read from the sensor to the water levels we set for limits. It's a bit backwards looking, because the sensor is looking down on the water, high water is low number and less than and low water is high numbers and greater than. Weird, but that's how it's gotta work.

Code:
unsigned long previousSensorTime = 0;
const unsigned long sensorReadInterval = 1000UL;  // checking once every second for now.  

const unsigned int lowWaterLimit = 22;
const unsigned int highWaterLimit = 12;

void loop(){
  
  unsigned int currentTime = millis();  // do this right from the start so everything sees the same time.
  
  if (currentTime - previousSensorTime > sensorReadInterval) {  //  Classic blink without delay technique.    
    waterLevel = checkWaterLevel();
  }
  
  if (pumpIsRunning){      //  If pump is running, see if we need to shut it off    
    if(waterLevel < highWaterLimit) {
      turnPumpOff();
    }
  }
  else {   // else pump is off so see if we need to turn it on.
    if(waterLevel > lowWaterLimit) {
      turnPumpOn();
    }
  }
}


So when we put it all together we have...



Code:

#include "NewPing.h"



const byte pumpPin = 8;   //  Use for whatever pin drives your relay that turns the pump on and off.  HIGH turns the pump on.
boolean pumpIsRunning = false;  //  A boolean variable to keep up with the state of the pump

const byte triggerPin = 4;
const byte echoPin = 5;
const unsigned int maxDistance = 60;  //  The distance in cm to the bottom of the sump would be a good number here. 
unsigned int waterLevel;   // A variable so we can keep up with the water level when we read it.  

unsigned long previousSensorTime = 0;
const unsigned long sensorReadInterval = 1000UL;  // checking once every second for now.  

const unsigned int lowWaterLimit = 22;
const unsigned int highWaterLimit = 12;


NewPing sonar(triggerPin, echoPin, maxDistance);   //  Create the NewPing instance


void turnPumpOn(){
  digitalWrite(pumpPin, HIGH);
  pumpIsRunning = true;
}

void turnPumpOff(){
  digitalWrite(pumpPin, LOW);
  pumpIsRunning = false;
}

// returns the water levle as an unsigned int in centimeters as the distance from the sensor to the water 
//  Larger distance means a lower water level!!!
unsigned int checkWaterLevel(){
  unsigned int distance = sonar.ping_cm();
  return distance;
}



void setup(){
  pinMode(pumpPin, OUTPUT);  // need an output pin to drive the pump.
  digitalWrite(pumpPin, LOW);
}


void loop(){
  
  unsigned int currentTime = millis();  // do this right from the start so everything sees the same time.
  
  if (currentTime - previousSensorTime > sensorReadInterval) {  //  Classic blink without delay technique.    
    waterLevel = checkWaterLevel();
  }
  
  if (pumpIsRunning){      //  If pump is running, see if we need to shut it off    
    if(waterLevel < highWaterLimit) {
      turnPumpOff();
    }
  }
  else {   // else pump is off so see if we need to turn it on.
    if(waterLevel > lowWaterLimit) {
      turnPumpOn();
    }
  }
}


Now read that loop out loud to yourself. Doesn't it sound just like what I said above we wanted?

Quote:
Get the distance from the sensor to the water in centimeters and store that in a variable. If the pump isn't running and that distance is greater than 22cm then turn the pump on. If the pump is running and that distance is less than or equal to 12cm then turn the pump off.

See how it reads like english instead of computer jibber jabber? You don't need to know how the ping sensor works. You don't need to know how the pump is turned on and off. That is all handled in those nice functions we wrote. And if we need to do any of those things anywhere else in the future, we have those nice functions we can call instead of rewriting any code.


I'll come back in a few and show you how we can encapsulate this. I'll leave it to you to try to add in any time based safeguards. Post them here and we'll fix them if you get it wrong.


__________________
David


Current Tank: Undergoing reconstruction...

Last edited by disc1; 06/27/2014 at 03:38 PM.
disc1 is offline   Reply With Quote
Unread 06/27/2014, 11:14 PM   #32
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
hello all
thank you David for breaking it all down into understandable explanations for noobs like me! I know you have other and more important things to be doing I appreciate you taking the time to do what you did in the last post to explain how to get what I want to happen to work and to go about getting it accomplished
thanks James


jc286006 is offline   Reply With Quote
Unread 06/27/2014, 11:44 PM   #33
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
i have a lot of reading to do tonight and in the future i think i need to go to a book store and purchase some books i am the type that can read a book and process what i have read into learning but reading from the internet seems to take more time to sink into my hard head LOL


jc286006 is offline   Reply With Quote
Unread 07/05/2014, 08:32 PM   #34
dudedudedude
Registered Member
 
Join Date: Nov 2006
Location: Virginia
Posts: 179
Quote:
Originally Posted by disc1 View Post
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.
disc1, thanks so much for the code!!!!!!!! I did not have time to play around with the hardware until today and made some changes to it to fit my system as follows:

Code:
byte lowWaterPin = 3;    // Goes HIGH when water below switch
byte highWaterPin = 2;   // Goes HIGH when water above switch
byte pumpPin = 12;        // Relay to control the water pump


unsigned long maxRunTime = 8000;   // pump on for max of X miliseconds
unsigned long minOffTime = 4000;  // pump must be off for at least Y miliseconds
unsigned long switchDebounceTime = 10;  // Switch must be activated for at least Z miliseconds.

unsigned long lastPumpTime = 0;

unsigned long lastLowWaterDetectTime = 0;
boolean lastLowWaterState = HIGH;

boolean pumpRunning = true;


void setup(){
  pinMode(lowWaterPin, INPUT_PULLUP);
  pinMode(highWaterPin, 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, HIGH);
      pumpRunning = false;
      lastPumpTime = currentMillis;
    }
  }
  else {   // pump is not running, see if we need to turn it on

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

  lastLowWaterState = lowWaterState;

}



dudedudedude is offline   Reply With Quote
Unread 07/27/2014, 10:21 PM   #35
jc286006
Registered Member
 
Join Date: Oct 2006
Location: ramsey illinois
Posts: 218
hello all
I have expanded the code from Disc1 and dudedudedude to include control of display,ato holding tank, and water change holding tank water levels.
It compiles and seems to work correctly on my breadboard simulation setup if anyone has time please look at it and see if you can identify any problems or ways that it might be simplified or made more reliable.
All pin assignments and runtimes etc will have to be set when i put it into actual use on my display.
Thanks James
Code:
byte sumplowWaterPin = 32;
byte atolowWaterPin = 33;
byte wclowWaterPin = 34;

byte sumphighWaterPin = 35;
byte atohighWaterPin = 36;
byte wchighWaterPin = 37;

byte sumppumpPin = 28;
byte atopumpPin = 29;
byte wcpumpPin = 30;


unsigned long maxsumpRunTime = 8000;
unsigned long maxatoRunTime = 8000;
unsigned long maxwcRunTime = 8000;

unsigned long minsumpOffTime = 4000;
unsigned long minatoOffTime = 4000;
unsigned long minwcOffTime = 4000;

unsigned long sumpswitchDebounceTime = 10;
unsigned long atoswitchDebounceTime = 10;
unsigned long wcswitchDebounceTime = 10;

unsigned long lastsumpPumpTime = 0;
unsigned long lastatoPumpTime = 0;
unsigned long lastwcPumpTime = 0;

unsigned long lastsumplowWaterDetectTime = 0;
unsigned long lastatolowWaterDetectTime = 0;
unsigned long lastwclowWaterDetectTime = 0;

boolean lastlowsumpWaterState = HIGH;
boolean lastlowatoWaterState = HIGH;
boolean lastlowwcWaterState = HIGH;

boolean sumppumpRunning = true;
boolean atopumpRunning = true;
boolean wcpumpRunning = true;

void setup() { 

  Serial.begin (9600); 

  pinMode (sumplowWaterPin, INPUT_PULLUP);
  pinMode (atolowWaterPin, INPUT_PULLUP);
  pinMode (wclowWaterPin, INPUT_PULLUP);

  pinMode (sumphighWaterPin, INPUT_PULLUP);
  pinMode (atohighWaterPin, INPUT_PULLUP);
  pinMode (wchighWaterPin, INPUT_PULLUP);

  pinMode (sumppumpPin, OUTPUT);
  pinMode (atopumpPin, OUTPUT);
  pinMode (wcpumpPin, OUTPUT);

}


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

  boolean lowsumpWaterState = digitalRead(sumplowWaterPin);
  boolean highsumpWaterState = digitalRead(sumphighWaterPin);

  if(lowsumpWaterState != lastlowsumpWaterState){
    lastsumplowWaterDetectTime = currentMillis;
  }


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

    if ((highsumpWaterState == HIGH) || (currentMillis - lastsumpPumpTime >= maxsumpRunTime)){
      digitalWrite(sumppumpPin, HIGH);
      sumppumpRunning = false;
      lastsumpPumpTime = currentMillis;
    }
  }
  else {   // pump is not running, see if we need to turn it on

    if((lowsumpWaterState == HIGH)  &&  (currentMillis - lastsumplowWaterDetectTime >= sumpswitchDebounceTime) && (currentMillis - lastsumpPumpTime > minsumpOffTime)){   // switch is low and has been for at least 3 seconds
      digitalWrite(sumppumpPin, LOW);
      sumppumpRunning = true;
      lastsumpPumpTime = currentMillis;
    }
  }

  lastlowsumpWaterState = lowsumpWaterState;


  boolean lowatoWaterState = digitalRead(atolowWaterPin);
  boolean highatoWaterState = digitalRead(atohighWaterPin);

  if(lowatoWaterState != lastlowatoWaterState){
    lastatolowWaterDetectTime = currentMillis;
  }


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

    if ((highatoWaterState == HIGH) || (currentMillis - lastatoPumpTime >= maxatoRunTime)){
      digitalWrite(atopumpPin, HIGH);
      atopumpRunning = false;
      lastatoPumpTime = currentMillis;
    }
  }
  else {   // pump is not running, see if we need to turn it on

    if((lowatoWaterState == HIGH)  &&  (currentMillis - lastatolowWaterDetectTime >= atoswitchDebounceTime) && (currentMillis - lastatoPumpTime > minatoOffTime)){   // switch is low and has been for at least 3 seconds
      digitalWrite(atopumpPin, LOW);
      atopumpRunning = true;
      lastatoPumpTime = currentMillis;
    }
  }

  lastlowatoWaterState = lowatoWaterState;


  boolean lowwcWaterState = digitalRead(wclowWaterPin);
  boolean highwcWaterState = digitalRead(wchighWaterPin);

  if(lowwcWaterState != lastlowwcWaterState){
    lastwclowWaterDetectTime = currentMillis;
  }


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

    if ((highwcWaterState == HIGH) || (currentMillis - lastwcPumpTime >= maxwcRunTime)){
      digitalWrite(wcpumpPin, HIGH);
      wcpumpRunning = false;
      lastwcPumpTime = currentMillis;
    }
  }
  else {   // pump is not running, see if we need to turn it on

    if((lowwcWaterState == HIGH)  &&  (currentMillis - lastwclowWaterDetectTime >= wcswitchDebounceTime) && (currentMillis - lastwcPumpTime > minwcOffTime)){   // switch is low and has been for at least 3 seconds
      digitalWrite(wcpumpPin, LOW);
      wcpumpRunning = true;
      lastwcPumpTime = currentMillis;
    }
  }

  lastlowwcWaterState = lowwcWaterState;

}



jc286006 is offline   Reply With Quote
Unread 07/28/2014, 09:11 AM   #36
ElmoC
Registered Member
 
Join Date: Jun 2013
Posts: 93
You don't have to check for the overflow when doing unsigned arithmetic.


ElmoC is offline   Reply With Quote
Unread 05/22/2018, 02:33 PM   #37
kal1gvla
Registered Member
 
Join Date: Jan 2017
Location: mexico city
Posts: 5
Hi, excellent post and great code.
Do you make work the code?
Do you sell the module?

Thanks


kal1gvla is offline   Reply With Quote
Unread 05/23/2018, 07:56 AM   #38
BigDave
Registered Member
 
BigDave's Avatar
 
Join Date: Jul 2002
Location: Wylie, TX
Posts: 473
I find when helping someone with code, the best thing to ask is, "what are you trying to do?"

From there, you can usually see how they're trying to do it.

My ATO is fairly robust.

I have 3 float switches. Two in the sump about 2" apart and 1 in the top-off tank.

My top off tank is 10 gallons. My sump is 40 gallons. Even with the main return pump turned off, the sump still has enough room to hold 10 extra gallons. 10 gallons of freshwater dumped into my 140+ gallon system isn't enough of a salt drop to cause too much issue. This alleviates me worrying about a top-off pump getting stuck on.

The float switches have the following jobs.

Top-off tank switch... lives at bottom of the top-off tank and alerts when the tank is too low. It disables the top-off pump so that it doesn't suck air (although I now use a paristaltic pump for top-off so it's less of an issue).

Two switches in the sump... Switch one is the top-off switch. This one is the level I try to keep the sump at. The top-off pump only runs at 2.5gph, so it typically runs for a minute or so each time it's triggered.

The second switch is about 2" lower than the other sump switch. This switch is the lowest point the sump can get to before the return pump starts to suck air. If this switch is triggered, then I get an email that the sump water got too low and the return pump is shut off to keep it from sucking air.

This does have the downside that water is no longer circulating from the sump to the main tank, but the main tank does still have the closed loop to keep water moving around in the tank. I've only ever had this happen once or twice in the last year and both instances were because I forgot to put water in the top-off tank the day before.

I like the idea of the ping sensor for measuring water height in the two tanks. I may look into incorporating something like that.

Here's the arduino code that runs my tank. You can find the top-off code embedded throughout. I suck at breaking code parts into different files. Sorry

https://github.com/niget2002/AquaCon...rduinoCode.ino


BigDave 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



All times are GMT -6. The time now is 10:59 PM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Powered by Searchlight © 2024 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-2022
User Alert System provided by Advanced User Tagging v3.3.0 (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.