Go Down

Topic: Water Cooler for an Axolotl tank [Solved] (Read 196 times) previous topic - next topic

lukey385

Dec 08, 2019, 06:40 am Last Edit: Dec 09, 2019, 05:51 am by lukey385
Hi everyone.
I have some axolotls if you don't know what they are they look like night furies from How To Train Your Dragon.
Anyhow they have a pretty cold environment that needs to be kept between 16-18degres Celcius during the summer and 14-16 degrees Celcius in the Winter(in order to ensure they mate during the right time of the year and not randomly as the tank of the water generally causes mating).
Heres where the Arduino comes in.
I bought a chiller that works on a Peltier module for $75 and its starting to fail(its cheap junk).
If I buy a decent one I'm looking at $150+ so I took a DIY approach, I got a bucket with pumps and hoses allowing tank water to come from the tank to the bucket and back to the tank.
Inside the bucket is a thermometer and one inside the tank.
Also in the bucket is an evaporator from a countertop Ice machine that the control board went bad on.
I have everything tested and working so that when the water in the tank and the bucket are too warm the compressor comes on and cools the water I also have a solenoid that opens to defrost the evaporator and a fan all being controlled by the Arduino.
The problem I'm having lies in that I have one (loop) that is controlling the fan the compressor and the temps. With a second (loop2) on a timer for the defrost.
But I need a way for the second loop to know that if the compressor is running and the fan is on.
So that when the solenoid is open the fan needs to turn off until the solenoid closes then turns back on the fan but also know to leave the fan off if it's already off.
The other problem I have is I need a way for the Arduino to know that if the compressor were to turn off that it needs to wait for like a minute before restarting so as not to shorten the life of the compressor (this is merely a safety).
If anyone has any ideas on other improvements or ideas on how I could make this happen it would be greatly appreciated.
Also, this is my first time using Arduino so I'm sorry if some of my code is clunky but I am self-taught.

Code: [Select]

// for relays LOW is on, HIGH is off
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Scheduler.h>
// Data wire is plugged into port 10 on the Arduino
#define ONE_WIRE_BUS 10
#define TEMPERATURE_PRECISION 9

//set the temp of the tank
int tanklowerlimit =18;
int tankupperlimit =19;
int chillerlowerlimit =16;
int chillerupperlimit= 17;

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
DeviceAddress tankThermometer, chillerThermometer;

/* pin 6 controls the relay running the compressor
   pin 8 controls the relay running the Defrost solenoid
   pin 10 reads the temperature from the sensor in the tank and from sensor in the chiller
   pin 9 controls the fan on the Evaporator*/

void setup()
{
 Serial.begin(9600);

//set pins to off during setup
digitalWrite(6, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
 
 pinMode (6, OUTPUT);
 pinMode (8, OUTPUT);
 pinMode (10, INPUT);
 pinMode (9, OUTPUT);

//add loop 2 to scheaduling loop is started by default
Scheduler.startLoop(loop2);
 
  sensors.begin();

  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: ");
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");

//set names for thermometers
 if (!sensors.getAddress(tankThermometer, 0)) Serial.println("Unable to find address for Device 0");
 if (!sensors.getAddress(chillerThermometer, 1)) Serial.println("Unable to find address for Device 1");
 
  // set the resolution to 9 bit per device
  sensors.setResolution(tankThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(chillerThermometer, TEMPERATURE_PRECISION);

  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(tankThermometer), DEC);
  Serial.println();

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(chillerThermometer), DEC);
  Serial.println();
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
}
// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
  Serial.print("Device Address: ");
  printAddress(deviceAddress);
  Serial.print(" ");
  printTemperature(deviceAddress);
  Serial.println();
}
void loop() {
 /*call sensors.requestTemperatures() to issue a global temperature
  request to all devices on the bus*/
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  // print the device information
  printData(tankThermometer);
  printData(chillerThermometer);

  if(tankThermometer <= tanklowerlimit){
    Serial.println(", Tank is at optimal temperature no cooling is required");
    digitalWrite(6, HIGH); //turns off compressor
    digitalWrite(9, HIGH); //turns fan off
    }

    if(tankThermometer >= tankupperlimit){
    Serial.println(", Tank is too warm checking temp of chiller"); 
    digitalWrite(6,HIGH); //keeps off compressor
    digitalWrite(9,HIGH); //keeps fan off
    }

    if(chillerThermometer <= chillerlowerlimit){
    Serial.println(", Cooling not required due to temperature of chiller");
    digitalWrite(6, HIGH); //keeps compressor off
    digitalWrite(9,HIGH); //turns fan off
    }

    if(chillerThermometer >= chillerupperlimit){
    Serial.println(", Cooling is on");
    digitalWrite(6, LOW); //turns compressor on
    digitalWrite(9,LOW); //turns fan on
    }
     
delay(5000);
}

void loop2()
{
//defrost timer
delay(1000000); //wait 16min after start
Serial.println(", Defrosting");
digitalWrite(9, HIGH); //turn off fan
digitalWrite(8, LOW); //open defrost solenoid
delay (15000); //wait 15 sec
Serial.println(", Done Defrosting");
digitalWrite(8, HIGH); //close the defrost solenoid
digitalWrite(9, LOW); //turn fan on

yield();
}

12Stepper

// relays are backwards LOW is on, HIGH is off
Why's that backwards? Why should high be on any more that low should be?

Relay boards are more often than not, low on, afaik.

I usually put this in sketches with relays:

Code: [Select]
//to use RELAY_ON or RELAY_OFF in digitalWrite(), instead of HIGH or LOW
//(un-)comment the next line depending on the relay's logic <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#define weHaveAnActiveLowRelay
#ifdef weHaveAnActiveLowRelay
#define RELAY_ON LOW   // most relay modules use this *active low* logic
#define RELAY_OFF HIGH
#else
#define RELAY_ON HIGH   // for testing with an *active high* relay or led
#define RELAY_OFF LOW
#endif

Paul__B

OK, so most of the opto-isolated relay modules do function with active-low inputs and active-low functions are in fact pretty much the default in digital logic due to some extent to the nature of TTL and "open-collector" circuits using NPN transistors - also sustained by the fact that N-channel FETs function better than P-channel (for whatever reason).

As such, and presuming that you wish your relay-switched devices to default to OFF, your code should write the respective pins HIGH before setting them to OUTPUT, otherwise the relays tend to glitch ON briefly on initialisation.

This probably will not concern the axolotls, but it can be dangerous in some situations.  :smiley-eek:

lukey385

#3
Dec 08, 2019, 07:53 am Last Edit: Dec 08, 2019, 10:34 am by lukey385
@Paul__B
I gotcha my bad I was assuming that HIGH was on LOW was off my mistake like I said this is my first time using Arduino.

@12Stepper
Thank you for the suggestion I am implementing that now!

GoForSmoke

Signal idle and 0 is HIGH.
External transients are more likely to take a LOW wire to HIGH than a VCC wire to LOW.
Idle HIGH tells the RX a working device is connected.

OP should shop more. Peltier wafers are pretty cheap depending on wattage and temperature as well as temperature differences they can take. Some can take over 200C on the hot side while some would melt but all those are < US$10, the cheap ones are 4 or 5 for $10.

Get a few and never push more than 50% of rated watts, they should last if you keep the hot side cool.
How warm is the place where the tank is kept? How big is the tank?
Given what you want, maybe cool the tank base and frame or cool water that you circulate through the tank.
The cooling system in a small fridge should be more efficient but noisier.
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

PaulRB

#5
Dec 08, 2019, 10:08 am Last Edit: Dec 08, 2019, 10:15 am by PaulRB
Does your code work as it is? I spotted many errors, I am surprised it even compiles (i.e. "verifies"). In particular, your "}" are all over the place, like you don't understand what they are for. Some are in strange places and some are even inside comments and will be ignored. Also "Low" is not the same as "LOW" because C language is case sensitive.

Your requirements, especially when you include the ones you have not coded yet, are a classic case of "doing several things at once" and an ideal use for a "state machine". I would recommend removing the scheduler library and timing all actions/state-changes using millis().


TomGeorge

Hi, 
Welcome to the forum.
+karma for using code tags.

Quote
Hi everyone.
I have some axolotls if you don't know what they are they look like night furies from How To Train Your Dragon. 
Anyhow they have a pretty cold environment that needs to be kept between 16-18degres Celcius during the summer and 14-16 degrees Celcius in the Winter(in order to ensure they mate during the right time of the year and not randomly as the tank of the water generally causes mating). 
Heres where the Arduino comes in. 
I bought a chiller that works on a Peltier module for $75 and its starting to fail(its cheap junk). 
If I buy a decent one I'm looking at $150+ so I took a DIY approach, I got a bucket with pumps and hoses allowing tank water to come from the tank to the bucket and back to the tank. 
Inside the bucket is a thermometer and one inside the tank. 
Also in the bucket is an evaporator from a countertop Ice machine that the control board went bad on. 
I have everything tested and working so that when the water in the tank and the bucket are too warm the compressor comes on and cools the water I also have a solenoid that opens to defrost the evaporator and a fan all being controlled by the Arduino. 
The problem I'm having lies in that I have one (loop) that is controlling the fan the compressor and the temps. With a second (loop2) on a timer for the defrost. 
But I need a way for the second loop to know that if the compressor is running and the fan is on. 
So that when the solenoid is open the fan needs to turn off until the solenoid closes then turns back on the fan but also know to leave the fan off if it's already off. 
The other problem I have is I need a way for the Arduino to know that if the compressor were to turn off that it needs to wait for like a minute before restarting so as not to shorten the life of the compressor (this is merely a safety). 
If anyone has any ideas on other improvements or ideas on how I could make this happen it would be greatly appreciated. 
Also, this is my first time using Arduino so I'm sorry if some of my code is clunky but I am self-taught.
Sorry I had to spread it out to see your points.

Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

lukey385

@GoForSmoke
thank you for the suggestions I already have a cheap Peltier cooler and want to use this method but thank you anyway

@PaulRB
It does work as is after I fixed the commented out ones I missed that and I only realized when I was looking over it again but I think that the state changes idea sounds intriguing can you elaborate more again I am a first time user and this is seriously the first program I've written ever. I have edited my post to include these changes.

lukey385

Hi,
Welcome to the forum.
+karma for using code tags.
Sorry I had to spread it out to see your points.

Tom... :)

Hi thankyou and why are you sorry and spreading it out what do you mean?

12Stepper

spreading it out what do you mean?
One loooooong paragraph is hard on the eyeballs...


12Stepper

It's ummm spread out.... in the quote, it's not identical to yours, it's broken into paragraphs.


lukey385

It's ummm spread out.... in the quote, it's not identical to yours, it's broken into paragraphs.


HAHA I feel dumb now I was viewing on my phone and didn't notice so I was worried it meant something else.

lukey385

I have finally figured it out by using some combinations of your ideas as well as some trial and error that I did thank you for all that helped. If you would like to see how I solved it my code is below.

Code: [Select]
// for relays LOW is on, HIGH is off
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Scheduler.h>
// Data wire is plugged into port 10 on the Arduino
#define ONE_WIRE_BUS 10
#define TEMPERATURE_PRECISION 9

//set the temp of the tank
const int tanklowerlimit =18;
const int tankupperlimit =19;
const int chillerlowerlimit =16;
const int chillerupperlimit= 17;

//states for relays
int fanState = LOW; //holds state for fan
int compressorState = LOW; //holds state for compressor

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
DeviceAddress tankThermometer, chillerThermometer;

/* pin 6 controls the relay running the compressor
   pin 8 controls the relay running the Defrost solenoid
   pin 10 reads the temperature from the sensor in the tank and from sensor in the chiller
   pin 9 controls the fan on the Evaporator*/


void setup()
{
 Serial.begin(9600);

//set pins to off during setup
digitalWrite(6, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
 
 pinMode (6, OUTPUT);
 pinMode (8, OUTPUT);
 pinMode (10, INPUT);
 pinMode (9, OUTPUT);

//add loop 2 to scheaduling loop is started by default
Scheduler.startLoop(loop2);
 
  sensors.begin();

  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: ");
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");

//set names for thermometers
 if (!sensors.getAddress(tankThermometer, 0)) Serial.println("Unable to find address for Device 0");
 if (!sensors.getAddress(chillerThermometer, 1)) Serial.println("Unable to find address for Device 1");
 
  // set the resolution to 9 bit per device
  sensors.setResolution(tankThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(chillerThermometer, TEMPERATURE_PRECISION);

  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(tankThermometer), DEC);
  Serial.println();

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(chillerThermometer), DEC);
  Serial.println();
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
}
// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
  Serial.print("Device Address: ");
  printAddress(deviceAddress);
  Serial.print(" ");
  printTemperature(deviceAddress);
  Serial.println();
}
void loop() {
 /*call sensors.requestTemperatures() to issue a global temperature
  request to all devices on the bus*/
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");

  // print the device information
  printData(tankThermometer);
  printData(chillerThermometer);

  if(tankThermometer <= tanklowerlimit){
    Serial.println(", Tank is at optimal temperature no cooling is required");
    if (compressorState == LOW) {
      compressorState = HIGH;
  }
    digitalWrite(6, compressorState);
    if (fanState ==LOW){
      fanState = HIGH;
    }
    digitalWrite(9, fanState);
 }
    if(tankThermometer >= tankupperlimit){
    Serial.println(", Tank is too warm checking temp of chiller"); 
    if (compressorState == LOW) {
      compressorState = HIGH;
  }
    digitalWrite(6, compressorState);
    if (fanState ==LOW){
      fanState = HIGH;
    }
    digitalWrite(9, fanState);
 }

    if(chillerThermometer <= chillerlowerlimit){
    Serial.println(", Cooling not required due to temperature of chiller");
    if (compressorState == LOW) {
      compressorState = HIGH;
  }
    digitalWrite(6, compressorState);
    if (fanState ==LOW){
      fanState = HIGH;
    }
    digitalWrite(9, fanState);
 }

    if(chillerThermometer >= chillerupperlimit){
    Serial.println(", Cooling is on");
    if (compressorState == HIGH){
      compressorState = LOW;
    }
    digitalWrite(6, compressorState);
    if (fanState == HIGH){
      fanState = LOW;
    }
    digitalWrite(9, fanState);
 }
     
delay(5000);
}

void loop2()
{
 //defrost timer
delay(840000); //wait 14min after start
Serial.println(", Defrosting");
if (fanState == LOW){
  fanState = HIGH;
}
digitalWrite(9, fanState);
digitalWrite(8, LOW); //open defrost solenoid
delay (15000); //wait 15 sec
Serial.println(", Done Defrosting");
digitalWrite(8, HIGH); //close the defrost solenoid
if (fanState == HIGH){
  fanState = LOW;
}
digitalWrite(9, fanState);
yield();
}

TomGeorge

Hi,
Good to hear you got it sorted.
What model Arduino are you using?

Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

lukey385


Go Up