I/O Expansion and ATO 1, 2, 3, 4....

Expansion modules and attachments

Posts: 24
Joined: Fri Aug 18, 2017 10:11 am
PostPosted: Sun Aug 20, 2017 8:55 am
Hi everyone :), I am new here... based in East London, Eastern Cape, South Africa.

I hope you are all well!! I am needing some help with adding more ATO pumps to my Reef Angel (RA) system I currently have ATO1 (StandardAto) operating fine on relay box port 1 with float switches connected to the high and low ATO float switches input ports on the RA controller.

I am needing to sort out ATO2 which I want on relay box port 2 with float switches connected to channnel 0 and channel 1 on the i/o expansion module.

I may also add more ATO's in the future so can anyone please assist with the code.

@rimai

Code is as follows:

#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <ReefAngel.h>
#include <Salinity.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>


byte x,y;
byte bkcolor;

void DrawCustomMain()
{
// the graph is drawn/updated when we exit the main menu &
// when the parameters are saved
ReefAngel.LCD.DrawDate(6, 112);
pingSerial();
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor(15, 60, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor(15, 60, ReefAngel.Params);
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 93, TempRelay);
y=10;
x=15;
for (int a=0;a<6;a++)
{
if(ReefAngel._IO.GetChannel(a)) bkcolor=COLOR_RED;
else bkcolor=COLOR_GREEN;
if (a>2) x=75;
if (a==3) y=10;
ReefAngel.LCD.Clear(bkcolor, x, y-3, x+40,y-1);
ReefAngel.LCD.Clear(bkcolor, x, y+8, x+40,y+10);
ReefAngel.LCD.Clear(bkcolor, x, y, x+3,y+8);
ReefAngel.LCD.Clear(bkcolor, x+37, y, x+40,y+8);
ReefAngel.LCD.DrawText(COLOR_WHITE, bkcolor, x+3, y, "Input");
ReefAngel.LCD.DrawText(COLOR_WHITE, bkcolor, x+32, y, a);
y+=15;
}
}

void DrawCustomGraph()
{
}

/*

For more information about custom main screen (RA forum URL removed)
*/

// Define Relay Ports By Name
#define ATO1 1
#define ATO2 2 *This is the one i must sort out.
#define Skimmer 3
#define Daylights 4
#define Flowpumps1 5
#define Flowpumps2 6
#define Heaters 7
#define Return 8

void setup()
{
ReefAngel.Init(); // Initialize Controller
ReefAngel.AddDateTimeMenu();
ReefAngel.AddStandardMenu();
ReefAngel.SetTemperatureUnit(Celsius); // set Temperature to Celsius
ReefAngel.FeedingModePorts = Port5Bit | Port6Bit; // Turn off Ports 5 and 6 when Feeding Mode is activated
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port3Bit | Port5Bit | Port6Bit | Port7Bit | Port8Bit; // Turn off Ports 1, 2, 3, 5, 6, 7 and 8 when Water Change Mode is activated
ReefAngel.OverheatShutoffPorts = Port4Bit | Port7Bit; // Turn off Ports 4 and 7 when Overheat Occurs
ReefAngel.LightsOnPorts = Port4Bit; // Turn on/off Ports 4 when Turn Lights On/Off is activated
ReefAngel.OverheatProbe = T1_PROBE | T2_PROBE | T3_PROBE; // Use Temperature probe 1, 2 and 3 to check for overheat
ReefAngel.TempProbe = T1_PROBE | T2_PROBE | T3_PROBE; // Use Temperature probe 1, 2 and 3 to check temperature

// Always on
ReefAngel.Relay.On(Return);
ReefAngel.Relay.On(Skimmer);
ReefAngel.Relay.On(Flowpumps1);
ReefAngel.Relay.On(Flowpumps2);
}

void loop()
{
ReefAngel.StandardATO(ATO1); // Standard ATO
ReefAngel.StandardLights(Daylights); // Daylight Lights
ReefAngel.StandardHeater(Heaters); // Heater
ReefAngel.PWM.StandardDaylight(); // Dimming for Daylight Channel
ReefAngel.PWM.StandardActinic(30); // Dimming for Actinic Channel
ReefAngel.ShowInterface(); // Display everything on the LCD screen
}

If i can see the ReefAngel.StandardATO code as it is written in the RA memory then i may be able to use that as the only difference will be that the input ports for the float switches will be on the i/o expansion module and not the RA controller as with ATO1.
User avatar
Posts: 2732
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Sun Aug 20, 2017 6:19 pm
the libraries code is inside the Arduino/libraries folder. inside there, look for the ReefAngel folder. inside there, the StandardATO function is located in the ReefAngel.cpp file.

you can then simply copy the function and paste it into your INO file with some modifications to use the other I/O pins.

Sent from my iPad using Tapatalk

Posts: 24
Joined: Fri Aug 18, 2017 10:11 am
PostPosted: Tue Aug 22, 2017 12:30 am
Thanks @binder i first had to figure out where exactly i find this library folder so i researched a bit and came across some useful information at www.arduino/en/hacking/libraries which directed me to it's location on Windows: My Documents\Arduino\libraries\. When I went there I ended up at C:\Users\User\Documents\Arduino\libraries\ReefAngel as i was searching for the Reef Angel folder and Cpp file and i found it!

I removed the StandardAto part and it is as follows:
void ReefAngelClass::StandardATO(byte ATORelay, int ATOTimeout)
{
// Input: Relay port and timeout value (max number of seconds that ATO pump is allowed to run)
unsigned long TempTimeout = ATOTimeout;
TempTimeout *= 1000;

/*
Is the low switch active (meaning we need to top off) and are we not currently topping off
Then we set the timer to be now and start the topping pump
*/
if ( LowATO.IsActive() && ( !LowATO.IsTopping()) )
{
LowATO.Timer = millis();
LowATO.StartTopping();
Relay.On(ATORelay);
}

// If the high switch is activated, this is a safeguard to prevent over running of the top off pump
if ( HighATO.IsActive() )
{
LowATO.StopTopping(); // stop the low ato timer
Relay.Off(ATORelay);
}

/*
If the current time minus the start time of the ATO pump is greater than the specified timeout value
AND the ATO pump is currently running:
We turn on the status LED and shut off the ATO pump
This prevents the ATO pump from contniously running.
*/
if ( (millis()-LowATO.Timer > TempTimeout) && LowATO.IsTopping() )
{
LED.On();
bitSet(AlertFlags,ATOTimeOutFlag);
#ifdef ENABLE_EXCEED_FLAGS
if (InternalMemory.read(ATO_Exceed_Flag)==0)
InternalMemory.write(ATO_Exceed_Flag, 1);
#endif // ENABLE_EXCEED_FLAGS
Relay.Off(ATORelay);
#ifdef ENABLE_ATO_LOGGING
// bump the counter if a timeout occurs
AtoEventCount++;
if ( AtoEventCount >= MAX_ATO_LOG_EVENTS ) { AtoEventCount = 0; }
#endif // ENABLE_ATO_LOGGING
}
}

I now just need to figure out where to insert i/o channel 0 (Low) and i/o channel 1 (High). If i don't revert back soon with info that i came right will you mind just showing me where this changes must be please? Another thing i am wondering about is will this code effect my current timeout setting of 150 seconds and if so must i put this value in somewhere.

Thanks,
Juan

Posts: 24
Joined: Fri Aug 18, 2017 10:11 am
PostPosted: Tue Aug 22, 2017 12:35 am
JclaasSA wrote:void ReefAngelClass::StandardATO(byte ATORelay, int ATOTimeout)


Just to answer my own question it looks like the 150 seconds time out must be put in lace of ATOTimeout.

Posts: 24
Joined: Fri Aug 18, 2017 10:11 am
PostPosted: Tue Aug 22, 2017 12:51 am
If I insert a value here then how will i be able to change this via the App or Portal?

Posts: 24
Joined: Fri Aug 18, 2017 10:11 am
PostPosted: Tue Aug 22, 2017 2:16 am
I haven't managed to come right yet so i tried a more basic approach.. still without any luck!

//RA Standard ATO code for ATO2 on IO exansion
void StandardATO()
{
// If the low switch is active, turn ATO2 pump on
if (ReefAngel.IO.GetChannel(0))
{
ReefAngel.Relay.On(ATO2);
}
// If the high switch is activated, turn ATO2 pump off
if ( ReefAngel.IO.GetChannel(1))
{
ReefAngel.Relay.Off(ATO2);
}

If this code can be corrected to work please assist and then i want the timeout to also be included as it appears in the RA cpp file.

@binder
User avatar
Posts: 2732
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Tue Aug 22, 2017 3:09 am
I will look at it more later (in several hours) when I am done at work and can spend a little time on it to give you an answer.

Sent from my XT1585 using Tapatalk

Posts: 24
Joined: Fri Aug 18, 2017 10:11 am
PostPosted: Tue Aug 22, 2017 2:58 pm
OK thanks a lot I'm looking forward to your positive response.
User avatar
Posts: 2732
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Tue Aug 22, 2017 6:13 pm
On a side note, you have a problem with the TempProbe and OverheatProbe lines.
You have these 2 lines:
Code: Select all
ReefAngel.OverheatProbe = T1_PROBE | T2_PROBE | T3_PROBE; // Use Temperature probe 1, 2 and 3 to check for overheat
ReefAngel.TempProbe = T1_PROBE | T2_PROBE | T3_PROBE; // Use Temperature probe 1, 2 and 3 to check temperature

This will not work properly. In fact, this code just tells the controller to use the T3_PROBE to monitor the Overheat and Temp probes. Unfortunately, you cannot use the built-in Overheat check to monitor all 3 probes and you cannot use the Temp probe to be all three probes either. The built-in functions only operate when you have 1 of those 3 probes selected. If you want all three probes to be used, then you must have a custom function written.
User avatar
Posts: 2732
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Tue Aug 22, 2017 7:03 pm
Ok. I took the time to write out some code for you. I wrote it so it could be incorporated into your INO file.

I have created your entire code and you should just be able to copy and paste the entire code block and run it. I have not tried to compile it or run it, but it should work. I have it set to where you could easily add in an ATO 3 or 4 just by adding a few more lines.

I assume that you are controlling port2 (ATO2) for the relay and that IO port 0 is the low switch and IO port 1 is the high switch. The switches should be mounted exactly like the standard switches are. I have hard coded the 150s timeout value as well. This can be changed in the future but that's a minor change. I wanted to get the code working first.

The function you call in your loop() is ATOoverIO(ato2). The variable ato2 is different from your port ATO2. ato2 is a special variable that i created just for the function. You will see how it is created when you look through the code.

Anyways, give this code a try and see how it works.

Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <ReefAngel.h>
#include <Salinity.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>


byte x,y;
byte bkcolor;

void DrawCustomMain()
{
// the graph is drawn/updated when we exit the main menu &
// when the parameters are saved
ReefAngel.LCD.DrawDate(6, 112);
pingSerial();
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor(15, 60, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor(15, 60, ReefAngel.Params);
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 93, TempRelay);
y=10;
x=15;
for (int a=0;a<6;a++)
{
if(ReefAngel._IO.GetChannel(a)) bkcolor=COLOR_RED;
else bkcolor=COLOR_GREEN;
if (a>2) x=75;
if (a==3) y=10;
ReefAngel.LCD.Clear(bkcolor, x, y-3, x+40,y-1);
ReefAngel.LCD.Clear(bkcolor, x, y+8, x+40,y+10);
ReefAngel.LCD.Clear(bkcolor, x, y, x+3,y+8);
ReefAngel.LCD.Clear(bkcolor, x+37, y, x+40,y+8);
ReefAngel.LCD.DrawText(COLOR_WHITE, bkcolor, x+3, y, "Input");
ReefAngel.LCD.DrawText(COLOR_WHITE, bkcolor, x+32, y, a);
y+=15;
}
}

void DrawCustomGraph()
{
}

/*

For more information about custom main screen (RA forum URL removed)
*/

// Define Relay Ports By Name
#define ATO1 1
#define ATO2 2 *This is the one i must sort out.
#define Skimmer 3
#define Daylights 4
#define Flowpumps1 5
#define Flowpumps2 6
#define Heaters 7
#define Return 8

// Custom ATO Functions
typedef struct _ATOIO {
  byte relay;  // port to control
  int timeout;  // max number of seconds that the ATO pump is allowed to run
  byte low_ioport; // IO port the low switch is connected
  byte high_ioport; // IO port the high switch is connected
  unsigned long timer;
  boolean topping; // are we currently topping off / running
} ATOIO;

void ATOoverIO(ATOIO &ato)
{
   unsigned long TempTimeout = ato.timeout;
   TempTimeout *= 1000;

   /*
   Is the low switch active (meaning we need to top off) and are we not currently topping off
   Then we set the timer to be now and start the topping pump
    */
  if ( ReefAngel.IO.GetChannel(ato.low_ioport) && (!ato.topping)) {
    ato.timer = millis();
    ato.topping = true;
    ReefAngel.Relay.On(ato.relay);
  }

   // If the high switch is activated, this is a safeguard to prevent over running of the top off pump
  if ( ReefAngel.IO.GetChanngel(ato.high_ioport) ) {
    ato.topping = false;
    ReefAngel.Relay.Off(ato.relay);
  }

   /*
    If the current time minus the start time of the ATO pump is greater than the specified timeout value
    AND the ATO pump is currently running:
    We turn on the status LED and shut off the ATO pump
    This prevents the ATO pump from continuously running.
    */
  if ( (millis() - ato.timer > TempTimeout) && ato.topping ) {
    ReefAngel.LED.On();
    // Verify the bitset function works properly
    bitSet(ReefAngel.AlertFlags, ReefAngel.ATOTimeOutFlag);
    ReefAngel.Relay.Off(ato.relay);
  }
}
// End Custom ATO Functions

// Create additional ATO's
ATOIO ato2;
ato2.relay = ATO2;  // Relay to use
ato2.timeout = 150;  // 150s timeout
ato2.low_ioport = 0;  // IO Port 0
ato2.high_ioport = 1;  // IO Port 1
ato2.timer = 0;  // always initialize to 0
ato2.topping = false;  // always initialize to false


void setup()
{
ReefAngel.Init(); // Initialize Controller
ReefAngel.AddDateTimeMenu();
ReefAngel.AddStandardMenu();
ReefAngel.SetTemperatureUnit(Celsius); // set Temperature to Celsius
ReefAngel.FeedingModePorts = Port5Bit | Port6Bit; // Turn off Ports 5 and 6 when Feeding Mode is activated
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port3Bit | Port5Bit | Port6Bit | Port7Bit | Port8Bit; // Turn off Ports 1, 2, 3, 5, 6, 7 and 8 when Water Change Mode is activated
ReefAngel.OverheatShutoffPorts = Port4Bit | Port7Bit; // Turn off Ports 4 and 7 when Overheat Occurs
ReefAngel.LightsOnPorts = Port4Bit; // Turn on/off Ports 4 when Turn Lights On/Off is activated
ReefAngel.OverheatProbe = T1_PROBE; // Use Temperature probe 1
ReefAngel.TempProbe = T1_PROBE; // Use Temperature probe 1

// Always on
ReefAngel.Relay.On(Return);
ReefAngel.Relay.On(Skimmer);
ReefAngel.Relay.On(Flowpumps1);
ReefAngel.Relay.On(Flowpumps2);
}

void loop()
{
ReefAngel.StandardATO(ATO1); // Standard ATO
ATOoverIO(ato2); // Alternate ATO2
ReefAngel.StandardLights(Daylights); // Daylight Lights
ReefAngel.StandardHeater(Heaters); // Heater
ReefAngel.PWM.StandardDaylight(); // Dimming for Daylight Channel
ReefAngel.PWM.StandardActinic(30); // Dimming for Actinic Channel
ReefAngel.ShowInterface(); // Display everything on the LCD screen
}
Next

Return to Addons

Who is online

Users browsing this forum: Google [Bot] and 1 guest

cron