Getting my new RA configured, function questions

Do you have a question on how to do something.
Ask in here.
Post Reply
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Getting my new RA configured, function questions

Post by lnevo »

You can plot it out... put a smaller window of time like over 2-3 hours... You can add this to set it somewhere that you can chart...

ReefAngel.CustomVar[0]=PWMSmoothRamp(.....);

Then go to

http://forum.reefangel.com/status/chart ... &filter=c0
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Getting my new RA configured, function questions

Post by lnevo »

Oh and one thing to keep in mind the ReefAngel.CustomVar variables are bytes so they can only go to 256.

Not sure if your function is returning 0-100 or 0-4096. You can use the map function to translate it down to a byte to at least see the curve.
AlanM
Posts: 263
Joined: Wed Jan 01, 2014 7:26 am

Re: Getting my new RA configured, function questions

Post by AlanM »

I haven't actually loaded any code into the RA yet since I got it. It's still shrink-wrapped while I get the code how I want it, actually, never plugged it in yet.

I just did it like the PWMParabola (which is actually a sine peak, not a parabola) function which, I think, expects percentages. I would swap it to an integer output and change the startPWM and endPWM into ints if I wanted it to give back 4096 for 12 bit dimming module, which I probably do.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Getting my new RA configured, function questions

Post by lnevo »

We'll get it online :)
AlanM
Posts: 263
Joined: Wed Jan 01, 2014 7:26 am

Re: Getting my new RA configured, function questions

Post by AlanM »

hah, I will do that tonight. Here's my latest code, for my future reference.

I have nearly everything I am doing on my current controller in plus extras.

1) 12-bit PWM rise and dim over 3 hours for my 6 light channels and PWM fans using the CustomExpansion module
2) Shut off skimmer recirc pump if skimmate locker sensor closes
3) controls heaters
4) doses alk and calcium and stops dosing alk if pH goes above 8.4
5) Runs my 4 powerheads in permanent nutrient transport mode.

Number 5 is the one I would like to work on next with the setPHModes function. to be able to set the sync state and the wave mode state of the 4 powerheads from some kind of time commands in the loop and from the GUI.

Is the NutrientTransportMode function smart enough to know that DC pumps are not supposed to be run between 0 and 30, so if I put a min speed of 0 it will skip up to 30 percent when it needs to exceed 0?

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 <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>

////// Place global variable code below here

// define default argument of isPercent in function prototype instead of definition, maybe an Arduino bug?
void CustomExpansion(byte id, byte channel, int percentage, boolean isPercent=true);
#define antiSyncMode 0; // pumps on alternate sides alternating in speed
#define syncMode 1; // pumps on alternate sides on at same time and flow meeting in middle
#define gyreMode 2; // pumps on opposite corners on at same time so that flow turns in a circle.  Opposite corners on at different times

////// Place global variable code above here


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    ReefAngel.Use2014Screen();  // Let's use 2014 Screen 
    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = Port6Bit;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = 0;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = Port3Bit;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = Port1Bit;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 830 );

    // Feeeding and Water Change mode speed
    ReefAngel.DCPump.FeedingSpeed=0;
    ReefAngel.DCPump.WaterChangeSpeed=0;


    // Ports that are always on
    ReefAngel.Relay.On( Port5 );
    ReefAngel.Relay.On( Port6 );

    ////// Place additional initialization code below here
    
//Custom Port Labels
ReefAngel.CustomLabels[0]="Heater"; 
ReefAngel.CustomLabels[1]="Skimmer"; 
ReefAngel.CustomLabels[2]="LEDPower"; 
ReefAngel.CustomLabels[3]="Fuge Light"; 
ReefAngel.CustomLabels[4]="Return"; 
ReefAngel.CustomLabels[5]="PowerHeads"; 
ReefAngel.CustomLabels[6]="Alkdoser"; 
ReefAngel.CustomLabels[7]="Caldoser";  


    ////// Place additional initialization code above here
}
/*

Want to use one float valve port for skimmate locker

Relay Ports:
1 = Heater
2 = Skimmer
3 = LEDPower
4 = Fuge Light 
5 = Reeflo Return
6 = Powerheads, 2xTunze 2xJebao
7 = Alkdoser
8 = CalDoser

DC Pumps:
Actinic: Tunze Left
Daylight: Tunze Right

CustomDimmer: // Want lights with sinusoidal ramp up and down with center at 1pm starting and ending at 7am/7pm
              // want Jebaos to operate in conjunction with Tunzes some of the time and opposite some of the time, so sometimes it will be 
              // pushing water at each other, sometimes it will be turning a gyre back and forth.
0 = Jebao Left
1 = Jebao Right
2 = Violet
3 = Royal Blue
4 = White
5 = Cool Blue
6 = Deep Red
7 = Cyan
8 = PWM fans

*/
void loop()
{
    ReefAngel.StandardHeater( Port1,785,790 ); 
    ReefAngel.Relay.DelayedOn( Port2,1 );
    ReefAngel.StandardLights( Port3,7,0,19,0 ); // led power
    ReefAngel.StandardLights( Port4,15,0,10,0 ); // fuge light
    if (ReefAngel.Params.PH < 840) 
    {
      ReefAngel.DosingPumpRepeat( Port7,0,30,50 ); // alk doser
    }
    else
    {
      ReefAngel.Relay.Off(Port7);  // turn it off if the pH is too high
    }
    ReefAngel.DosingPumpRepeat( Port8,15,30,50 ); // cal doser
    ReefAngel.DCPump.UseMemory = false;
    ReefAngel.DCPump.SetMode( NutrientTransport,75,10 );
    ReefAngel.DCPump.DaylightChannel = Sync; // Tunze right
    ReefAngel.DCPump.ActinicChannel = AntiSync; // Tunze left
    ////// Place your custom code below here
    CustomExpansion(0x41,0,NutrientTransportMode(0,75,500,false),true); // Jebao Left
    CustomExpansion(0x41,1,NutrientTransportMode(0,75,500,true),true); // Jebao Right
    // lights
    CustomExpansion(0x41,2,PWMSmoothRamp(13,00,22,00,0,(int)(75*40.95),180,0),false); // V, feeding value, not percent from smoothramp
    CustomExpansion(0x41,3,PWMSmoothRamp(13,30,21,30,0,(int)(75*40.95),180,0),false); // RB, feeding value, not percent from smoothramp
    CustomExpansion(0x41,4,PWMSmoothRamp(13,30,21,30,0,(int)(75*40.95),180,0),false); // W, feeding value, not percent from smoothramp
    CustomExpansion(0x41,5,PWMSmoothRamp(13,30,21,30,0,(int)(50*40.95),180,0),false); // CB, feeding value, not percent from smoothramp
    CustomExpansion(0x41,6,PWMSmoothRamp(13,30,21,30,0,(int)(50*40.95),180,0),false); // DR, feeding value, not percent from smoothramp
    CustomExpansion(0x41,7,PWMSmoothRamp(13,30,21,30,0,(int)(50*40.95),180,0),false); // Cy, feeding value, not percent from smoothramp
    // fans
    CustomExpansion(0x41,8,PWMSmoothRamp(13,00,22,00,25,75,180,0),true); // Cy, feeding value, percent from smoothramp
    
    // Turn off Skimmer if Locker is full
    if(ReefAngel.HighATO.IsActive())
    {
        ReefAngel.Relay.Off(Port2);
    }
    else
    {
        ReefAngel.Relay.On(Port2);
    }
    
    ////// Place your custom code above here

    // This should always be the last line
    ReefAngel.Portal( "AlanM" );
    ReefAngel.ShowInterface();
}

void setPHModes(byte syncModeIn, byte waveModeIn)
{
  switch (syncModeIn) {
    case 0:
      ReefAngel.DCPump.DaylightChannel = Sync;
      ReefAngel.DCPump.ActinicChannel = AntiSync;
      // want to add code here to also set the daylight and actinic ones to the wave function/syncmode I set here
      // custom port 0 left should be AntiSync, custom port 1 on right should be Sync and set to same wave function as DC pumps
      break;
    case 1:
      ReefAngel.DCPump.DaylightChannel = Sync;
      ReefAngel.DCPump.ActinicChannel - Sync;
      // want to add code here to also set the daylight and actinic ones to the wave function/syncmode I set here
      // custom port 0 on left should be Sync, custom port 1 on right should be Sync and set to same wave function as DC pumps
      break;
    case 2:
      ReefAngel.DCPump.DaylightChannel = Sync;
      ReefAngel.DCPump.ActinicChannel - AntiSync;
      // want to add code here to also set the daylight and actinic ones to the wave function/syncmode I set here
      // custom port 0 on left should be Sync, custom port 1 on right should be AntiSync and set to same wave function as DC pumps
      break;
  }
}

int PWMSmoothRamp(byte startHour, byte startMinute, byte endHour, byte endMinute, int startPWM, int endPWM, byte slopeLength, int oldValue)
{
  LightsOverride=true;
  int current_hour = hour();
  int start = NumMins(startHour, startMinute);
  int end = NumMins(endHour, endMinute);
  if (start > end) // Start is greater than End so it is over midnight
  {
    if (current_hour < endHour) start -= 1440; // past midnight
    if (current_hour >= startHour) end += 1440; // before midnight
  }
  int current = NumMins(current_hour, minute());
  if (slopeLength > ((end-start)/2) ) slopeLength = (end-start)/2; // don't allow a slope length greater than half the total period
  if (current <= start || current >= end) 
    return oldValue; // it's before the start or after the end, return the default
  else
  { // do the slope calculation
    int pwmDelta = endPWM - startPWM;
    int smoothPhase;
    if ((current > (start + slopeLength)) && (current < (end - slopeLength))) 
      return endPWM; // if it's in the middle of the slope, return the high level
    else if ((current - start) < slopeLength) 
    {  // it's in the beginning slope up
      smoothPhase = constrain(map(current, start, start+slopeLength, 180, 360), 180, 360);
    }
    else if ((end - current) < slopeLength)
    { // it's in the end slope down
      smoothPhase = constrain(map(current, end-slopeLength, end, 0, 180), 0, 180);
    }
    return startPWM + (pwmDelta*(1.0+(cos(radians(smoothPhase)))/2.0));
  }
}


void CustomExpansion(byte id, byte channel, int percentage, boolean isPercent)
{
  Wire.beginTransmission(id);
  Wire.write(0);
  Wire.write(0xa1);
  Wire.endTransmission();
  int newdata = 0;
  if (isPercent)
  {
    newdata=(int)(percentage*40.95);
  }
  else
  {
    newdata=percentage;
  }
  Wire.beginTransmission(id);
  Wire.write(0x8+(4*channel));
  Wire.write(newdata&0xff);
  Wire.write(newdata>>8);
  Wire.endTransmission();
}

Post Reply