My RA Plus .ino - w/Cust Main, PWM and RF Exp

Share you PDE file with our community
Post Reply
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

My RA Plus .ino - w/Cust Main, PWM and RF Exp

Post by TanksNStuff »

OK, I've been working on my .ino in my spare time over the past month or two. After a while, I realized that I had so many attachments and custom functions that I realized that I needed to upgrade to the RA Plus board. Before I get started with my code and pics, here's a list of my RA equipment:

1. RA Plus w/standard relay box
2. Expansion relay box
3. Expansion Module 10 port hub (required with more than one attachment)
4. WiFi Attachment
5. PWM Expansion Module (actually modified to analog signals since my LED drivers are analog)
6. RF Module
7. (2) Temp Probes (original + 1 extra)
8. (1) Temp probe extension cable (to reach my canopy... may still need to extend it to reach)
9. Original RA board (plans to include as extra display pages in the future)

I used the "InitialInternalMemory" from the Example Codes so I'm not going to include it here.

For my .ino, I started with a RAGen created base file, then manually added/edited bits and pieces from others who posted here. If you see anything resembling your code, thank you! :D

OK, here's my .ino file. I tried to separate out and label each section to make it easier to read/follow.

Code: Select all

// Autogenerated file by RAGen (v1.2.1.158), (03/08/2012 22:54)
// RA_030812_2254.ino
//
// This version designed for v0.9.0 or later

/* The following features are enabled for this File: 
#define DisplayImages
#define DateTimeSetup
#define DirectTempSensor
#define DisplayLEDPWM
#define wifi
#define StandardLightSetup
#define SaveRelayState
#define RelayExp
#define InstalledRelayExpansionModules 1
#define WDT
#define PWMEXPANSION
#define CUSTOM_MAIN
#define RFEXPANSION
#define FONT_8x16
#define NUMBERS_8x16
*/

#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 <RF.h>
#include <ReefAngel.h>
#include <avr/wdt.h>

//*********************************************************************************************************************************
//--------------------------------------------------- Start of Global Variables ---------------------------------------------------
// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5

// Initial values to all 6 PWM channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};

// Globals Needed for Params on Custom Main
byte x,y;
char text[10];
int v;

// Globals Needed for RF Mode on Custom Main
byte vtechmode;
boolean bFeeding=false;
//------------------------------------------------------ End of Global Variables --------------------------------------------------
//*********************************************************************************************************************************
//---------------------------------------------Custom Main for PWM Expansion Module------------------------------------------------

void DrawCustomMain()
{
        //Top Banner
        ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_SKYBLUE, 9, 2, " George's 75G Reef "); 
        
        // Display T1 Header Text
        ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,8,14,"Tank");
  
        // Display the T1 Temp Value
        char text[7];
        ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
        ReefAngel.LCD.Clear(255, 4, 21, 37, 37);
        ReefAngel.LCD.DrawLargeText(COLOR_CORNFLOWERBLUE, 255, 4, 24, text, Num8x16);
        pingSerial();

        // Display the T2 Header Text
        ReefAngel.LCD.DrawText(COLOR_CRIMSON,255,52,14,"Canopy");
  
        // Display the T2 Temp Value
        ConvertNumToString(text, ReefAngel.Params.Temp[T2_PROBE], 10);
        ReefAngel.LCD.Clear(255, 52, 21, 75, 37);
        ReefAngel.LCD.DrawLargeText(COLOR_CRIMSON, 255, 52, 24, text, Num8x16);
        pingSerial();

        // Display pH Header Text
        ReefAngel.LCD.DrawText(COLOR_INDIGO,255,108,14,"pH");
  
        // Display pH Value
        ConvertNumToString(text, ReefAngel.Params.PH, 100);
        ReefAngel.LCD.Clear(255, 94, 21, 106, 37);
        ReefAngel.LCD.DrawLargeText(COLOR_INDIGO, 255, 94, 24, text, Num8x16);
        pingSerial();
        
        // Display Vortech MP40wES Mode Header Text
        ReefAngel.LCD.Clear(DefaultFGColor,5,39,127,39);
        ReefAngel.LCD.DrawText(0,255,18,42,"EcoSmart Vortech");

        // Display EcoSmart Mode Value      
        ReefAngel.LCD.Clear(255, 1, 49, 128, 64);
        if (vtechmode == 0) ReefAngel.LCD.DrawLargeText(COLOR_LIMEGREEN,255,35,50,"Constant");
        else if(vtechmode == 1) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,42,50,"Lagoon");
        else if (vtechmode == 2) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,25,50,"Reef Crest");
        else if (vtechmode == 3) ReefAngel.LCD.DrawLargeText(COLOR_CORNFLOWERBLUE,255,22,50,"Short Pulse");
        else if (vtechmode == 4) ReefAngel.LCD.DrawLargeText(COLOR_PINK,255,25,50,"Long Pulse");
        else if (vtechmode == 5) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,8,50,"Nutrient Trnsp.");
        else if (vtechmode == 6) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,23,50,"Tidal Swell");
        else if (vtechmode == 9) ReefAngel.LCD.DrawLargeText(COLOR_WHITE,0,45,50,"Night");

        // Display PMW Expansion Channel Headers and % Values
        ReefAngel.LCD.Clear(DefaultFGColor,5,65,127,65);
        ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,31,68,"LED Dimming");
        x=15;
        y=78;
        for (int a=0;a<4;a++)
        {
          if (a>1) x=75;
          if (a==2) y=78;
          ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x,y,"Ch :");
          ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+12,y,a);
          v = int(ReefAngel.PWM.GetChannelValue(a)/2.55);
          ConvertNumToString(text, v, 1);
          strcat(text,"  ");
          ReefAngel.LCD.DrawText(COLOR_DARKGOLDENROD,DefaultBGColor,x+24,y,text);
          y+=10;
        }
        pingSerial();
        
        // Display Main Relay Box
        byte TempRelay = ReefAngel.Relay.RelayData;
        TempRelay &= ReefAngel.Relay.RelayMaskOff;
        TempRelay |= ReefAngel.Relay.RelayMaskOn;
        ReefAngel.LCD.DrawOutletBox(13, 97, TempRelay);
        pingSerial();
 
        // Display Expansion Relay Box 1
        TempRelay = ReefAngel.Relay.RelayDataE[0];
        TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
        TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
        ReefAngel.LCD.DrawOutletBox(13, 109, TempRelay);
        pingSerial();
        
        //Draw Date & Time
        ReefAngel.LCD.DrawDate(6, 123);
        pingSerial();
}

void DrawCustomGraph()  // Not Used
{
}
//------------------------------------------------------ End Custom Main ----------------------------------------------------------
//*********************************************************************************************************************************
//-------------------------------------------------------- Begin Setup ------------------------------------------------------------
void setup()
{
    ReefAngel.Init();  //Initialize controller

    ReefAngel.FeedingModePorts = Port1Bit | Port8Bit;
    ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port6Bit | Port7Bit |Port8Bit;
    ReefAngel.OverheatShutoffPortsE[0] = Port1Bit | Port2Bit | Port3Bit | Port4Bit;
    ReefAngel.LightsOnPortsE[0] = Port1Bit | Port2Bit | Port3Bit | Port4Bit;

    // Ports that are always on
    ReefAngel.Relay.On(Port1);
    ReefAngel.Relay.On(Port3);
    ReefAngel.Relay.On(Port5);
    ReefAngel.Relay.On(Port6);
    ReefAngel.Relay.On(Port7);
    ReefAngel.Relay.On(Port8);
    ReefAngel.Relay.On(Box1_Port7);
    ReefAngel.Relay.On(Box1_Port8);
//--------------------------------------------------------- RF Module Setup -------------------------------------------------------
    ReefAngel.RF.SetMode(Slave_Start,0,0);
    /*
    If you get a compile error similar to this:
    'class ReefAngelClass' has no member named 'RF'
    Please make sure that you enabled RF Expansion on your features file.
  
    Open RAGen and make sure you have RF Expansion checked under the Features tab.

    Or, you can manually edit the file.
    The file is located at "Documents\Arduino\libraries\ReefAngel_Features.h" file and has to include this line in it:
    #define RFEXPANSION  
    */
    InternalMemory.RFMode_write(0);
    InternalMemory.RFSpeed_write(128);
    InternalMemory.RFDuration_write(10);
//------------------------------------------------------ End RF Module Setup ------------------------------------------------------  
}
//---------------------------------------------------------- End Setup ------------------------------------------------------------
//*********************************************************************************************************************************
//--------------------------------------------------------- Begin Loop ------------------------------------------------------------
void loop()
{
    // Specific functions
    ReefAngel.Refresh();  //WDT check
    ReefAngel.StandardLights(Box1_Port1); //Left Blue LEDs
    ReefAngel.StandardLights(Box1_Port2); //Right Blue LEDs
    ReefAngel.MHLights(Box1_Port3); //Left White LEDs
    ReefAngel.MHLights(Box1_Port4); //Right White LEDs
 
    ReefAngel.StandardHeater(Port2);
    ReefAngel.MoonLights(Box1_Port5); //Left Moonlight
    ReefAngel.MoonLights(Box1_Port6); //Right Moonlight
    ReefAngel.MoonLights(Port4); //Fuge light on when main lights are out
    ReefAngel.Portal("tanksnstuff");
    
//------------------------------------------------ Start PWM Expansion Code for Slope ----------------------------------------------
    //  Temporarily using Memory Locations from PWM Slope Actinic (for LEDPWM0 and LEDPWM1) and 
    //  PWM Slope Daylight (for LEDPWM2 and LEDPWM3) for the start, end, durations.
    //  Will change the start%, end%, duration of each to new memory locations for each channel when Curt provides libraries update.
    PWMChannel[LEDPWM0]=PWMSlope(
      InternalMemory.StdLightsOnHour_read(),
      InternalMemory.StdLightsOnMinute_read(),
      InternalMemory.StdLightsOffHour_read(),
      InternalMemory.StdLightsOffMinute_read(),
      InternalMemory.read(852),  // start %
      InternalMemory.read(853),  // end %
      InternalMemory.read(854),  // duration
      PWMChannel[LEDPWM0]);
      
    PWMChannel[LEDPWM1]=PWMChannel[LEDPWM0];

    PWMChannel[LEDPWM2]=PWMSlope(
      InternalMemory.MHOnHour_read(),
      InternalMemory.MHOnMinute_read(),
      InternalMemory.MHOffHour_read(),
      InternalMemory.MHOffMinute_read(),
      InternalMemory.read(849),  // start %
      InternalMemory.read(850),  // end %
      InternalMemory.read(851),  // duration
      PWMChannel[LEDPWM2]);

    PWMChannel[LEDPWM3]=PWMChannel[LEDPWM2];

    // The lines above are what calculates the slope.
    // You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
    // The are as follow:
    // 1st parameter: hour to start slope
    // 2nd parameter: minute to start slope
    // 3rd parameter: hour to end slope
    // 4th parameter: minute to end slope
    // 5th parameter: % of the PWM signal to start slope
    // 6th parameter: % of the PWM signal to end slope
    // 7th parameter: duration of slope in minutes
    // 8th parameter: always the same as the variable before the PWMSlope() call

    //PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);

    // In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
    // Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
    // Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
    //CheckCloud(); (May be used at a later date with cloud/storm effects)
    ReefAngel.PWM.Expansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
    ReefAngel.PWM.Expansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
    ReefAngel.PWM.Expansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
    ReefAngel.PWM.Expansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
    ReefAngel.ShowInterface();

//------------------------------------------------- End PWM Expansion Code for Slope ----------------------------------------------

//------------------------------------------------ Start Time-of-Day Based Functions ----------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ These are the mode numbers for the RF Expansion Module for reference ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //#define Constant      0
    //#define Random1       1 // Lagoonal
    //#define Random2       2 // Reef Crest
    //#define ShortWave     3
    //#define LongWave      4
    //#define Smart_NTM     5 // Nutrient Transport Mode
    //#define Smart_TSM     6 // Tidal Swell Mode
    //#define Feeding_Start 7
    //#define Feeding_Stop  8
    //#define Night         9
    //#define Slave_Start   97
    //#define Slave_Stop    98
    //#define None          99
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//------------------------------ Start Feeding Mode Schedule (Start 1st Feeding at 9:55 AM and 2nd at 1:55 PM)---------------------
    // if the hour is 9a or 1p, minute is 55 and seconds is 0
    // start the feeding mode
    if ( ((hour() == 9) || (hour() == 13)) && 
       (minute() == 55) && 
       (second() == 0) ) 
    {
      ReefAngel.FeedingModeStart();
      vtechmode = InternalMemory.RFMode_read();     
    }
//------------------------------------------------------ End of Feeding Mode Schedule ---------------------------------------------

//-------------------------------------------------------- Start RF Daytime Control -----------------------------------------------
  if (hour() >=8 && hour() <= 22)
  {  
    if (ReefAngel.DisplayedMenu==FEEDING_MODE) bFeeding=true;
    if (ReefAngel.DisplayedMenu==DEFAULT_MENU && bFeeding )
    {
      bFeeding=false; 
      ReefAngel.RF.UseMemory=false;
      ReefAngel.RF.SetMode(Smart_NTM,155,5);
      ReefAngel.Timer[4].SetInterval(1800); // Timer for 30min
      ReefAngel.Timer[4].Start();
      vtechmode = 5;
    }
    if (ReefAngel.DisplayedMenu==DEFAULT_MENU && ReefAngel.Timer[4].IsTriggered())
    {
      ReefAngel.RF.UseMemory=true;
      vtechmode = InternalMemory.RFMode_read();
    }  
  }
//---------------------------------------------------------- End RF Daytime Control -----------------------------------------------   

//-------------------------------------------------------- Start RF Nightmode Control ---------------------------------------------    

  if (hour()>=23 || hour()<7) // Defining "Nightmode" hours for VorTech = between 11 PM and 7 AM
    {
      ReefAngel.RF.UseMemory=false;
      ReefAngel.RF.SetMode(Night,15,0);
      vtechmode = 9;
    }
  else
    {
      ReefAngel.RF.SetMode(Feeding_Stop,0,0); //Temp fix for coming out of Night mode
      ReefAngel.RF.UseMemory=true;
      vtechmode = InternalMemory.RFMode_read();
    } 
//---------------------------------------------------------- End RF Nightmode Control ---------------------------------------------
//------------------------------------------------------ End Time-of-Day Based Functions ------------------------------------------
}
//--------------------------------------------------------------- End Loop --------------------------------------------------------
//*********************************************************************************************************************************

// ToDo List Functions that still need to be added above:
// 1. Add Sunrise/Sunset/MoonPhase/Cloud Chance, etc. (PWM Slope data may be altered by these?)
// 2. *Option for later date* Relay box Ports 7 and 8 changed to "Off" normally, then add line in Loop to power them on if Overheat 
//    Shutoff is active (when I get fans to plug into those ports.)
// 3. Use original RA board as an auxilliary display board with multiple displays.   
Some basic functions I've included in there are:
1. Since I have the RA Plus board with tons of memory, I'm using the standard menu that includes more setup features than I'll need... but it doesn't hurt to have them if I do. Therefore, the ability to set date/time, calibrate pH probe, etc. can be done if needed later on.
2. Custom Main Screen showing all the important things I wanted (see pics/description below).
3. PWM slope to control LED dimming. I can control start/end/duration %'s and times with android app on the fly. ;)
4. Two "feeding modes" set to activate automatically during the day. This will be timed up with my auto feeder filled with flake food.
5. "Night mode" setup for the RF module to handle when I want that to start/stop.
6. I didn't include any functions for ATO because I have a Tunze Osmo that handles that. However, the relay outlet it's plugged into is set to power off during feeding mode and water change mode. This is because my sump level will drop during those modes and I don't want extra RO water added unnecessarily.
7. Manual control of many things with Android App. Two important ones for me are Fuge Light (Port 4) and the ability to customize the PWM slope data fields (allowing me to acclimate my corals to the new LEDs and also find a good blue/white color combination)

Here are a few pics of my custom main screen (sorry a few are blurry, camera phone didn't focus well):

Image

Image

Image

Image

Image

Short description of the custom main screen:
- Custom banner across the top
- Tank(T1)/Canopy(T2)/pH in large numbers and colored individually to distinguish them better [note... the temp probes were in the open air... my tank isn't that cold]
- Vortech Mode (displaying mode in matching color as the Vortech controller) [I took several pics using the android app to change modes so you can see the colored text for each.]
- LED Dimming (showing the 4 PWM expansion channels I'm using) [note... these show 0% because it's after my PWM slope end time]
- Main relay box (top) and Expansion relay box (bottom)
- Date/Time

In case anyone is interested, here are the relay outlet port assignments I'm using:
Main Relay box
1. ATO
2. HEATER
3. CARBON-GFO (reactor)
4. FUGE LIGHT
5. VORTECH
6. BP REACTOR
7. SKIMMER
8. RETURN PUMP

Expansion Relay box
1. LED1 Actinic (Blues)
2. LED2 Actinic (Blues)
3. LED1 Daylight (Whites)
4. LED2 Daylight (Whites)
5. LED1 Moonlight (non-dimmable)
6. LED2 Moonlight (non-dimmable)
7. Open (always on)
8. Open (always on)

I'd say it's finished enough to setup on my tank now, and as soon as I finish my canopy for my new LED lights, I'll do just that. In the mean time, feel free to review it for any errors and comment.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: My RA Plus .ino - w/Cust Main, PWM and RF Exp

Post by rimai »

Awesome!!!
Show us the canopy when it's completed :)
Roberto.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: My RA Plus .ino - w/Cust Main, PWM and RF Exp

Post by TanksNStuff »

Thanks! Will do Roberto.

I have the frame built and painted, plywood sides stained and ready for 2-3 coats of Polyurethane, then I can screw the sides on and get it setup. With my schedule, it's probably going to be next weekend before I get it all finished.

I'll also get some pics of how/where I mount the RA equipment under my stand. ;)
Post Reply