Jebao Issue on Daylight/Actinic Channel

Do you have a question on how to do something.
Ask in here.
Post Reply
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

So my Jebao is hooked up to my Daylight channel. Every time I force my Light Relay Ports on through Android App, the RA automatically pulls the default Value for Daylight/Actinic. This in turn affects my Jebao which I have running random custom modes through out the day/night.

Is there a way for me to get the RA to not change the Daylight/Actinic channel dimming % when I turn on the Relay ports associated with my RA?

I guess the easiest solution would be to rewire my Jebao to my dimming expansion....
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

I actually created a variable to disable dimming overide, but declared it wrong within the libraries :(
So, you have no way to change it.
I created a bug report:
https://github.com/reefangel/Libraries/issues/137
Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

Is it something simple to change in the library, so I can manual do it until you push out a new version of libraries?
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

Actually on a second look and quick test, the variable is referenced as extern inside Globals.h
And the PWM class takes care of assigning values to it, but it bases the assignment on whether you use PWMSlope or PWMParabola in your code. If you do, it just assumes you are using the channels for lights.
What I'm thinking is that you have one channel for light and another for Jebao, correct?
If so, your solution is the easiest indeed.
The libraries will override both channels or none.
Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

I use Daylight for Jebao, Actinic is not used. I use dimming expansion channels 0,1,2 for my LED's.

I chose to keep my LED drivers plugged into the relay so I could have the option to force my lights on at any time of the day
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

Can you post your code?
Maybe if we change the order of things, we can make this work.
Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

Excuse my bootleg Random Wave mode code... As I could not get the other Random wave mode code to use Else mode I put something together really quickly.

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

////// Memory Locations used by all formulas
#define Mem_B_AcclDay  100 // Acclimation Day
#define Mem_B_AcclDuration  101 // Days in Accl Cycle
#define Mem_B_SlopeStart  102 // Slopestart for White and Blue channels

/////// Memory Locations used by Blue Formula
#define Mem_B_AcclStartEndBlue  105    // Acclimation starting Slope end%
#define Mem_B_SlopeEndBlue  106    // slope End%

////// Memory Locations used by White Formula
#define Mem_B_AcclStartEndWhite  110 // Acclimation starting Slope end%
#define Mem_B_SlopeEndWhite  111    // Slope End%


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


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    ReefAngel.AddStandardMenu();  // Add Standard Menu

    ReefAngel.Use2014Screen();  // Let's use 2014 Screen 
/////    ReefAngel.AddPHExpansion();  // pH Expansion Module
    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = Port5Bit;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port8Bit;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = Port2Bit | Port4Bit | Port8Bit;
    // 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( 820 );


    // Ports that are always on
    ReefAngel.Relay.On( Port3 );
    ReefAngel.Relay.On( Port7 );

    ////// Place additional initialization code below here

//Custom Port Labels
ReefAngel.CustomLabels[0]="Heater";  
ReefAngel.CustomLabels[1]="BlueLED";  
ReefAngel.CustomLabels[2]="ReturnPump";  
ReefAngel.CustomLabels[3]="WhiteLED";  
ReefAngel.CustomLabels[4]="KalkATO";  
ReefAngel.CustomLabels[5]="CarbPhos";  
ReefAngel.CustomLabels[6]="WP40";  
ReefAngel.CustomLabels[7]="Refugium";  

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


void loop()
{
  int heaterOn=InternalMemory.read_int(Mem_I_HeaterTempOn);
  int heaterOff=InternalMemory.read_int(Mem_I_HeaterTempOff);
    ReefAngel.StandardHeater( Port1,heaterOn,heaterOff );
    ReefAngel.StandardLights( Port2,12,0,22,0 );
    ReefAngel.StandardLights( Port4,13,0,21,0 );
    ReefAngel.SingleATO( true,Port5,1200,1 );
    ReefAngel.StandardLights( Port8,20,30,13,0 );


   ////// Place your custom code below here    

    DCPumpRandMode();
    MediaFilter();
    LEDschedule();

  ////// Place your custom code above here

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

void DCPumpRandMode() {
  static unsigned long feeding;

// Set timer when in feeding mode

if (now()%SECS_PER_DAY<36000 || now()%SECS_PER_DAY>=79200) { // 10pm -> 10am
  ReefAngel.PWM.SetDaylight( ElseMode(35,0,true) );   // Night mode (go to 30%)
}
else if (now()%SECS_PER_DAY>=36000 && now()%SECS_PER_DAY<79200) {
  static byte randMode=2;
  if (now()%SECS_PER_DAY==36001 || now()%SECS_PER_DAY==43200 || now()%SECS_PER_DAY==50400 || now()%SECS_PER_DAY==57600 || now()%SECS_PER_DAY==64800 || now()%SECS_PER_DAY==72000) randMode=random(1,8);
  if (randMode==1) ReefAngel.PWM.SetDaylight( SineMode(40,75,85,true) );
  if (randMode==2) ReefAngel.PWM.SetDaylight( ElseMode(60,20,true) );
  if (randMode==3) ReefAngel.PWM.SetDaylight( SineMode(30,70,180,true) );
  if (randMode==4) ReefAngel.PWM.SetDaylight( ElseMode(50,15,true) );
  if (randMode==5) ReefAngel.PWM.SetDaylight( ReefCrestMode(55,20,true) );
  if (randMode==6) ReefAngel.PWM.SetDaylight( LongPulseMode(25,65,60,true) );
  if (randMode==7) ReefAngel.PWM.SetDaylight( LongPulseMode(40,40,900,true) );
  }
if (ReefAngel.DisplayedMenu==FEEDING_MODE) {
    feeding=now();
    ReefAngel.PWM.SetDaylight( LongPulseMode(0,21,60,true) );
}
else if (now()-feeding>0 && now()-feeding<=9000) {
  // Continue NTM for the 2.5 hours
    ReefAngel.PWM.SetDaylight( NutrientTransportMode(0,70,400,true) );
}
}

void MediaFilter() {
if  ( (now()%SECS_PER_DAY>0) && (now()%SECS_PER_DAY<=7200) ) {
    ReefAngel.Relay.On( Port6 );
}
else if ( (now()%SECS_PER_DAY>=7201) ) {
    ReefAngel.Relay.Off( Port6 );
}
}

void LEDschedule() {
////////// LED Dimming Acclimation Cycle and your standard LED schedule

////////// Variables used for all channels
  byte acclDay = InternalMemory.read(Mem_B_AcclDay);            // What day in the acclimation cycle it is
  byte acclDuration = InternalMemory.read(Mem_B_AcclDuration);  // Acclimation Duration in days
  byte startPercent = InternalMemory.read(Mem_B_SlopeStart);    // Normal start% being used by all 3 channels
////////// Blue Channel Variables
  byte acclStartEndBlue = InternalMemory.read(Mem_B_AcclStartEndBlue); // Starting End% for Acclimation cycle
  float acclendPercentBlue = InternalMemory.read(Mem_B_SlopeEndBlue);  // Your target Blue end% once acclimation is complete
////////// Blue Channel Formula
  float acclPercentPerDayBlue = (acclendPercentBlue - acclStartEndBlue) / acclDuration;  // How much your Blue end% rises per acclimation day 
  float acclFactorBlue = acclDay * acclPercentPerDayBlue;      // endPercentBlue will be offset by this much. If acclDay = 0 then this value will be 0
  byte endPercentBlue = acclendPercentBlue - acclFactorBlue;   // Your final Blue end% for the day
////////// White Channel Variables
  byte acclStartEndWhite = InternalMemory.read(Mem_B_AcclStartEndWhite);  // Starting End% for Acclimation cycle
  float acclEndPercentWhite = InternalMemory.read(Mem_B_SlopeEndWhite);   // Your target White end% once acclimation is complete
////////// White Channel Formula
  float acclPercentPerDayWhite= (acclEndPercentWhite - acclStartEndWhite) / acclDuration;  // How much your White end% rises per acclimation day
  float acclFactorWhite = acclDay * acclPercentPerDayWhite;      // endPercentWhite will be offset by this much. If acclDay = 0 then this value will be 0
  byte endPercentWhite = acclEndPercentWhite - acclFactorWhite; 
////////// Your standard PWM Dimming code using the variables above to determine start% and end%
  ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,21,0,startPercent,endPercentWhite,60,25) );
  ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,22,0,startPercent,endPercentBlue,120,25) ); 
  ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,22,0,startPercent,endPercentBlue,120,25) ); 
////////// At the end of the day, we need to decrement the acclimation counter.
  static boolean acclCounterReady=false; // We need a boolean so we only do this once per day
  if (now()%SECS_PER_DAY!=0) acclCounterReady=true; // If it's not midnight we'll get the boolean ready
  if (now()%SECS_PER_DAY==0 && acclCounterReady && acclDay>0) { // It's midnight, our bool is true and acclDay is more than 0
  acclDay--; // Reduce the counter
  acclCounterReady=false; // Reset the boolean flag
  InternalMemory.write(Mem_B_AcclDay,acclDay); // Update memory
}
}



byte ElseMode( byte MidPoint, byte Offset, boolean WaveSync )
{
////////// Static's only initialize the first time they are called
  static unsigned long LastChange=millis();        // Set the inital time that the last change occurred
  static int Delay = random(2000,3000);           // Set the initial delay - default 500, 3000
  static int NewSpeed = MidPoint;                  // Set the initial speed
  static int AntiSpeed = MidPoint;                 // Set the initial anti sync speed
  if ((millis()-LastChange) > Delay)               // Check if the delay has elapsed
  {
    Delay=random(2000,10000);                        // If so, come up with a new delay - default - 500, 5000
    int ChangeUp = random(Offset);                 // Amount to go up or down
    if (random(100)<50)                            // 50/50 chance of speed going up or going down
    {
      NewSpeed = MidPoint - ChangeUp;
      AntiSpeed = MidPoint + ChangeUp;
    }
    else
    {
      NewSpeed = MidPoint + ChangeUp;
      AntiSpeed = MidPoint - ChangeUp;
    }
    LastChange=millis();                           // Reset the time of the last change
  }
  if (WaveSync)
  {
    return NewSpeed;
  }
  else
  {
    return AntiSpeed;
  }
  
}
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

Add this to your code below LEDschedule:

Code: Select all

    int dummy=ShortPulseMode(0,0,0,true);
The order things happen within the code matters.
Your LEDschedule function is setting the variable LightsOverride to true. We need a way to set it to false.
The functions that do that are all the waveforms we have available, so we just call one of them, just to assign the LightsOverride to false, but we really don't need to do anything with the return value.
Just make sure that the waveform comes always after any call of PWMSlope or PWMParabola.
Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

What if I just swapped the order that the functions are called in my loop? Since my randmode function is called first... if I move that function after the LEDschedule function would that provide the same result?
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

Your randmode is custom and doesn't use any of our waveforms or it would work too...
Roberto.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

You need to call any one of these waveforms after the PWMSlope/PWMParabola:
http://forum.reefangel.com/viewtopic.php?f=7&t=2844
Roberto.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

BTW, this:

Code: Select all

  int heaterOn=InternalMemory.read_int(Mem_I_HeaterTempOn);
  int heaterOff=InternalMemory.read_int(Mem_I_HeaterTempOff);
    ReefAngel.StandardHeater( Port1,heaterOn,heaterOff );
is the same as this:

Code: Select all

    ReefAngel.StandardHeater( Port1 );
Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

Yeah, I tried to switch back to using DCPump class and use the other random wave mode in another thread for DCPump wave modes... However, I could never get it to select Else mode, it would only choose DCPump modes...

Reason I want else mode is I like that I am able to adjust the delay range and the offset which I have not been able to figure out with any of the other modes.. It seems that they are all based off the same wave speed and I feel restricted by not being able to really change all of their parameters.
Image
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

rimai wrote:BTW, this:

Code: Select all

  int heaterOn=InternalMemory.read_int(Mem_I_HeaterTempOn);
  int heaterOff=InternalMemory.read_int(Mem_I_HeaterTempOff);
    ReefAngel.StandardHeater( Port1,heaterOn,heaterOff );
is the same as this:

Code: Select all

    ReefAngel.StandardHeater( Port1 );

Lol.... thank you. I knew there was a simpler way to do it. I was trying to figure it out by looking in the libraries but couldn't. Still trying to learn the depths of your code...
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

ReEfnWrX wrote:Yeah, I tried to switch back to using DCPump class and use the other random wave mode in another thread for DCPump wave modes... However, I could never get it to select Else mode, it would only choose DCPump modes...

Reason I want else mode is I like that I am able to adjust the delay range and the offset which I have not been able to figure out with any of the other modes.. It seems that they are all based off the same wave speed and I feel restricted by not being able to really change all of their parameters.
Which is totally fine :)
That's the beauty of the controller.... You can pick and choose what you want and if you don't like, just change it and come up with a totally different solution :ugeek:
Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

Yes, but I really like the DCPump screen that I now do not get :(

As well as the DCPump screen in the portal
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

My bad....
I totally missed the function DCPumpRandMode you mentioned before.
Yeah, if you switch the order, it would work too, just like you said. Disregard my previous comment, because you are indeed using the SineMode inside your function.
If we change the code to put the screen back, you won't be able to achieve the Longpulse during feeding. The waveform for feeding is constant. Other than that, I think it can be changed.
Roberto.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

Maybe something like this:

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

////// Memory Locations used by all formulas
#define Mem_B_AcclDay  100 // Acclimation Day
#define Mem_B_AcclDuration  101 // Days in Accl Cycle
#define Mem_B_SlopeStart  102 // Slopestart for White and Blue channels

/////// Memory Locations used by Blue Formula
#define Mem_B_AcclStartEndBlue  105    // Acclimation starting Slope end%
#define Mem_B_SlopeEndBlue  106    // slope End%

////// Memory Locations used by White Formula
#define Mem_B_AcclStartEndWhite  110 // Acclimation starting Slope end%
#define Mem_B_SlopeEndWhite  111    // Slope End%


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


void setup()
{
  // This must be the first line
  ReefAngel.Init();  //Initialize controller
  ReefAngel.AddStandardMenu();  // Add Standard Menu

    ReefAngel.Use2014Screen();  // Let's use 2014 Screen 
  /////    ReefAngel.AddPHExpansion();  // pH Expansion Module
  // Ports toggled in Feeding Mode
  ReefAngel.FeedingModePorts = Port5Bit;
  // Ports toggled in Water Change Mode
  ReefAngel.WaterChangePorts = Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port8Bit;
  // Ports toggled when Lights On / Off menu entry selected
  ReefAngel.LightsOnPorts = Port2Bit | Port4Bit | Port8Bit;
  // 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( 820 );

  // Feeeding and Water Change mode speed
  ReefAngel.DCPump.FeedingSpeed=0;
  ReefAngel.DCPump.WaterChangeSpeed=0;
  ReefAngel.DCPump.UseMemory = false;
  ReefAngel.DCPump.DaylightChannel = Sync;
  ReefAngel.DCPump.ActinicChannel = None;

  // Ports that are always on
  ReefAngel.Relay.On( Port3 );
  ReefAngel.Relay.On( Port7 );

  ////// Place additional initialization code below here

  //Custom Port Labels
  ReefAngel.CustomLabels[0]="Heater";  
  ReefAngel.CustomLabels[1]="BlueLED";  
  ReefAngel.CustomLabels[2]="ReturnPump";  
  ReefAngel.CustomLabels[3]="WhiteLED";  
  ReefAngel.CustomLabels[4]="KalkATO";  
  ReefAngel.CustomLabels[5]="CarbPhos";  
  ReefAngel.CustomLabels[6]="WP40";  
  ReefAngel.CustomLabels[7]="Refugium";  

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


void loop()
{
  int heaterOn=InternalMemory.read_int(Mem_I_HeaterTempOn);
  int heaterOff=InternalMemory.read_int(Mem_I_HeaterTempOff);
  ReefAngel.StandardHeater( Port1,heaterOn,heaterOff );
  ReefAngel.StandardLights( Port2,12,0,22,0 );
  ReefAngel.StandardLights( Port4,13,0,21,0 );
  ReefAngel.SingleATO( true,Port5,1200,1 );
  ReefAngel.StandardLights( Port8,20,30,13,0 );


  ////// Place your custom code below here    

  MediaFilter();
  LEDschedule();
  DCPumpRandMode();

  ////// Place your custom code above here

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

void DCPumpRandMode() {
  static unsigned long feeding;

  // Set timer when in feeding mode

  if (now()%SECS_PER_DAY<36000 || now()%SECS_PER_DAY>=79200) { // 10pm -> 10am
    ReefAngel.PWM.SetDaylight( ElseMode(35,0,true) );   // Night mode (go to 30%)
    ReefAngel.DCPump.SetMode( Custom,35,0 );
  }
  else if (now()%SECS_PER_DAY>=36000 && now()%SECS_PER_DAY<79200) {
    static byte randMode=2;
    if (now()%SECS_PER_DAY==36001 || now()%SECS_PER_DAY==43200 || now()%SECS_PER_DAY==50400 || now()%SECS_PER_DAY==57600 || now()%SECS_PER_DAY==64800 || now()%SECS_PER_DAY==72000) randMode=random(1,8);
    if (randMode==1) 
    {
      ReefAngel.PWM.SetDaylight( SineMode(40,75,85,true) );
      ReefAngel.DCPump.SetMode( Custom,75,85 );
    }
    if (randMode==2)
    {
      ReefAngel.PWM.SetDaylight( ElseMode(60,20,true) );
      ReefAngel.DCPump.SetMode( Custom,60,20 );
    }
    if (randMode==3)
    {
      ReefAngel.PWM.SetDaylight( SineMode(30,70,180,true) );
      ReefAngel.DCPump.SetMode( Custom,70,180 );
    }
    if (randMode==4)
    {
      ReefAngel.PWM.SetDaylight( ElseMode(50,15,true) );
      ReefAngel.DCPump.SetMode( Custom,50,15 );
    }
    if (randMode==5)
    {
      //      ReefAngel.PWM.SetDaylight( ReefCrestMode(55,20,true) );
      ReefAngel.DCPump.SetMode( ReefCrest,55,20 );
    }
    if (randMode==6)
    {
      //      ReefAngel.PWM.SetDaylight( LongPulseMode(25,65,60,true) );
      ReefAngel.DCPump.SetMode( LongPulse,65,60 );
    }
    if (randMode==7)
    {
      //      ReefAngel.PWM.SetDaylight( LongPulseMode(40,40,900,true) );
      ReefAngel.DCPump.SetMode( LongPulse,40,900 );
    }
  }
  if (ReefAngel.DisplayedMenu==FEEDING_MODE) {
    feeding=now();
    //    ReefAngel.PWM.SetDaylight( LongPulseMode(0,21,60,true) );
  }
  else if (now()-feeding>0 && now()-feeding<=9000) {
    // Continue NTM for the 2.5 hours
    //    ReefAngel.PWM.SetDaylight( NutrientTransportMode(0,70,400,true) );
    ReefAngel.DCPump.SetMode( NutrientTransport,70,400 );
  }
}

void MediaFilter() {
  if  ( (now()%SECS_PER_DAY>0) && (now()%SECS_PER_DAY<=7200) ) {
    ReefAngel.Relay.On( Port6 );
  }
  else if ( (now()%SECS_PER_DAY>=7201) ) {
    ReefAngel.Relay.Off( Port6 );
  }
}

void LEDschedule() {
  ////////// LED Dimming Acclimation Cycle and your standard LED schedule

    ////////// Variables used for all channels
  byte acclDay = InternalMemory.read(Mem_B_AcclDay);            // What day in the acclimation cycle it is
  byte acclDuration = InternalMemory.read(Mem_B_AcclDuration);  // Acclimation Duration in days
  byte startPercent = InternalMemory.read(Mem_B_SlopeStart);    // Normal start% being used by all 3 channels
  ////////// Blue Channel Variables
  byte acclStartEndBlue = InternalMemory.read(Mem_B_AcclStartEndBlue); // Starting End% for Acclimation cycle
  float acclendPercentBlue = InternalMemory.read(Mem_B_SlopeEndBlue);  // Your target Blue end% once acclimation is complete
  ////////// Blue Channel Formula
  float acclPercentPerDayBlue = (acclendPercentBlue - acclStartEndBlue) / acclDuration;  // How much your Blue end% rises per acclimation day 
  float acclFactorBlue = acclDay * acclPercentPerDayBlue;      // endPercentBlue will be offset by this much. If acclDay = 0 then this value will be 0
  byte endPercentBlue = acclendPercentBlue - acclFactorBlue;   // Your final Blue end% for the day
  ////////// White Channel Variables
  byte acclStartEndWhite = InternalMemory.read(Mem_B_AcclStartEndWhite);  // Starting End% for Acclimation cycle
  float acclEndPercentWhite = InternalMemory.read(Mem_B_SlopeEndWhite);   // Your target White end% once acclimation is complete
  ////////// White Channel Formula
  float acclPercentPerDayWhite= (acclEndPercentWhite - acclStartEndWhite) / acclDuration;  // How much your White end% rises per acclimation day
  float acclFactorWhite = acclDay * acclPercentPerDayWhite;      // endPercentWhite will be offset by this much. If acclDay = 0 then this value will be 0
  byte endPercentWhite = acclEndPercentWhite - acclFactorWhite; 
  ////////// Your standard PWM Dimming code using the variables above to determine start% and end%
  ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,21,0,startPercent,endPercentWhite,60,25) );
  ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,22,0,startPercent,endPercentBlue,120,25) ); 
  ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,22,0,startPercent,endPercentBlue,120,25) ); 
  ////////// At the end of the day, we need to decrement the acclimation counter.
  static boolean acclCounterReady=false; // We need a boolean so we only do this once per day
  if (now()%SECS_PER_DAY!=0) acclCounterReady=true; // If it's not midnight we'll get the boolean ready
  if (now()%SECS_PER_DAY==0 && acclCounterReady && acclDay>0) { // It's midnight, our bool is true and acclDay is more than 0
    acclDay--; // Reduce the counter
    acclCounterReady=false; // Reset the boolean flag
    InternalMemory.write(Mem_B_AcclDay,acclDay); // Update memory
  }
}



byte ElseMode( byte MidPoint, byte Offset, boolean WaveSync )
{
  ////////// Static's only initialize the first time they are called
  static unsigned long LastChange=millis();        // Set the inital time that the last change occurred
  static int Delay = random(2000,3000);           // Set the initial delay - default 500, 3000
  static int NewSpeed = MidPoint;                  // Set the initial speed
  static int AntiSpeed = MidPoint;                 // Set the initial anti sync speed
  if ((millis()-LastChange) > Delay)               // Check if the delay has elapsed
  {
    Delay=random(2000,10000);                        // If so, come up with a new delay - default - 500, 5000
    int ChangeUp = random(Offset);                 // Amount to go up or down
    if (random(100)<50)                            // 50/50 chance of speed going up or going down
    {
      NewSpeed = MidPoint - ChangeUp;
      AntiSpeed = MidPoint + ChangeUp;
    }
    else
    {
      NewSpeed = MidPoint + ChangeUp;
      AntiSpeed = MidPoint - ChangeUp;
    }
    LastChange=millis();                           // Reset the time of the last change
  }
  if (WaveSync)
  {
    return NewSpeed;
  }
  else
  {
    return AntiSpeed;
  }

}

Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

I switched the Function order to

Code: Select all

    MediaFilter();
    LEDschedule();
    DCPumpRandMode();
And when I turn on the Relay port for the LED's it still overrides the Daylight channel to internal memory.

Maybe this is because the random mode selected was Else mode... and not one of the other's that are defined in the libraries.
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

I know why.... :(
When the time is for ElseMode, the LightsOverride variable is set to true because it is not one of the default wave patterns... So, you still need to call the dummy waveform just to ensure we are always calling it.
Roberto.
ReEfnWrX
Posts: 234
Joined: Tue Nov 05, 2013 8:40 am
Location: Houston TX

Re: Jebao Issue on Daylight/Actinic Channel

Post by ReEfnWrX »

So I see in the globals.cpp that the wave mode codes have this

Code: Select all

	LightsOverride=false;
Could I just add this into my byte elsemode code? That should end the problem?
Last edited by ReEfnWrX on Sat Jan 25, 2014 12:09 pm, edited 1 time in total.
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Jebao Issue on Daylight/Actinic Channel

Post by rimai »

That would work too, I think.
Roberto.
Post Reply