Re: JEBO WP-40
Posted: Sat Mar 30, 2013 10:07 pm
Community discussion about Reef Angel Controllers and reefing related subjects
https://forum.reefangel.com/
Code: Select all
// Read memory for RF Wave Settings and use for Tunze/Jaebo
int mode=InternalMemory.RFMode_read();
int speed=InternalMemory.RFSpeed_read();
int duration=InternalMemory.RFDuration_read();
// Change this to what you want your min/max based on vortech speed
// This is for those functions that take both, but only one memory slot.
int minOffset=5;
int maxOffset=10;
int min=speed-minOffset;
int max=speed+maxOffset;
if (mode==Constant) {
// Constant
ReefAngel.PWM.SetDaylight( speed );
ReefAngel.PWM.SetActinic( speed );
} else if (mode==Lagoon) {
// Lagoon
ReefAngel.PWM.SetDaylight( SineMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( SineMode(min,max,duration,false) );
} else if (mode==ReefCrest) {
// Reef Crest
ReefAngel.PWM.SetDaylight( ReefCrestMode(speed,duration,true) );
ReefAngel.PWM.SetActinic( ReefCrestMode(speed,duration,false) );
} else if (mode==ShortPulse) {
// Short Pulse
ReefAngel.PWM.SetDaylight( ShortPulseMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( ShortPulseMode(min,max,duration,false) );
} else if (mode==LongPulse) {
// Long Pulse
ReefAngel.PWM.SetDaylight( LongPulseMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( LongPulseMode(min,max,duration,false) );
} else if (mode==TidalSwell) {
// Tidal Swell
ReefAngel.PWM.SetDaylight( TidalSwellMode(speed,true) );
ReefAngel.PWM.SetDaylight( TidalSwellMode(speed,false) );
} else if (mode=NutrientTransport) {
// Smart_NTM
ReefAngel.PWM.SetDaylight( NutrientTransportMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( NutrientTransportMode(min,max,duration,false) );
} else {
// Default
ReefAngel.PWM.SetDaylight( TideMode(speed,minOffset,maxOffset) );
ReefAngel.PWM.SetActinic( TideMode(speed,minOffset,maxOffset) );
}
////// Place your custom code above here
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 <ReefAngel.h>
////// Place global variable code below here
////// Place global variable code above here
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port1Bit | Port5Bit | Port6Bit | Port7Bit | Port8Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port7Bit | Port8Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port2Bit | Port3Bit | Port7Bit | Port8Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port3Bit | Port5Bit | Port6Bit | Port7Bit | Port8Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
InternalMemory.OverheatTemp_write( 869 );
// Ports that are always on
////// Place additional initialization code below here
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.Relay.On( Port1 );
ReefAngel.StandardFan( Port2 );
ReefAngel.ActinicLights( Port3 );
ReefAngel.WavemakerRandom1( Port5,180,900 );
ReefAngel.WavemakerRandom2( Port6,90,900 );
ReefAngel.DayLights( Port7 );
ReefAngel.DayLights( Port8 );
//Moonlight Phase 9pm-10am (CH4-CH5)
if ( (hour() >=10) && (hour() <21) )
ReefAngel.PWM.SetChannel( 4,(0) );
else
ReefAngel.PWM.SetChannel( 4, MoonPhase() );
if ( (hour() >=10) && (hour() <21) )
ReefAngel.PWM.SetChannel( 5,(0) );
else
ReefAngel.PWM.SetChannel( 5, MoonPhase() );
//Pump Delay and Over Flow Protection
if (ReefAngel.HighATO.IsActive())
ReefAngel.Relay.On(Port1);
else
ReefAngel.Relay.Off(Port1);
//ATO Protection
if (ReefAngel.LowATO.IsActive())
ReefAngel.Relay.On(Port4);
else
ReefAngel.Relay.Off(Port4);
//Kalk Dose 20sec @ 8pm-12pm (every 15min)
if (hour() >=20 || hour() < 12)
ReefAngel.Relay.Set(Port4, now()%900<22);
else
ReefAngel.Relay.Off(Port4);
//Feed Mode Delay on Pump
static boolean feeding=false;
static unsigned long feedingstarted = now();
if (ReefAngel.DisplayedMenu==FEEDING_MODE)
{
if (!feeding)
{
feeding=true;
feedingstarted = now();
}
else
{
if (now()-feedingstarted>900)
{
bitSet(ReefAngel.Relay.RelayMaskOff,Port5-1);
bitSet(ReefAngel.Relay.RelayMaskOff,Port6-1);
}
}
}
////// Place your custom code below here
// Read memory for RF Wave Settings and use for Tunze/Jaebo
int mode=InternalMemory.RFMode_read();
int speed=InternalMemory.RFSpeed_read();
int duration=InternalMemory.RFDuration_read();
// Change this to what you want your min/max based on vortech speed
// This is for those functions that take both, but only one memory slot.
int minOffset=5;
int maxOffset=10;
int min=speed-minOffset;
int max=speed+maxOffset;
if (mode==Constant) {
// Constant
ReefAngel.PWM.SetDaylight( speed );
ReefAngel.PWM.SetActinic( speed );
} else if (mode==Lagoon) {
// Lagoon
ReefAngel.PWM.SetDaylight( SineMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( SineMode(min,max,duration,false) );
} else if (mode==ReefCrest) {
// Reef Crest
ReefAngel.PWM.SetDaylight( ReefCrestMode(speed,duration,true) );
ReefAngel.PWM.SetActinic( ReefCrestMode(speed,duration,false) );
} else if (mode==ShortPulse) {
// Short Pulse
ReefAngel.PWM.SetDaylight( ShortPulseMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( ShortPulseMode(min,max,duration,false) );
} else if (mode==LongPulse) {
// Long Pulse
ReefAngel.PWM.SetDaylight( LongPulseMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( LongPulseMode(min,max,duration,false) );
} else if (mode==TidalSwell) {
// Tidal Swell
ReefAngel.PWM.SetDaylight( TidalSwellMode(speed,true) );
ReefAngel.PWM.SetDaylight( TidalSwellMode(speed,false) );
} else if (mode=NutrientTransport) {
// Smart_NTM
ReefAngel.PWM.SetDaylight( NutrientTransportMode(min,max,duration,true) );
ReefAngel.PWM.SetActinic( NutrientTransportMode(min,max,duration,false) );
} else {
// Default
ReefAngel.PWM.SetDaylight( TideMode(speed,minOffset,maxOffset) );
ReefAngel.PWM.SetActinic( TideMode(speed,minOffset,maxOffset) );
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "paulturner911" );
ReefAngel.ShowInterface();
}
void DrawCustomMain()
{
int x,y;
char text[10];
// Dimming Expansion
x = 15;
y = 2;
for ( int a=0;a<6;a++ )
{
if ( a>2 ) x = 75;
if ( a==3 ) y = 2;
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x,y,"Ch :" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x+12,y,a );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x+24,y,ReefAngel.PWM.GetChannelValue(a) );
y += 10;
}
pingSerial();
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 43, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 43, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();
// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 84, TempRelay );
pingSerial();
// Date and Time
ReefAngel.LCD.DrawDate( 6, 122 );
pingSerial();
}
void DrawCustomGraph()
{
}
byte ShortPulseMode(byte PulseMinSpeed, byte PulseMaxSpeed, int PulseDuration, boolean PulseSync)
{
byte tspeed=0;
PulseMinSpeed=constrain(PulseMinSpeed,30,100);
PulseMaxSpeed=constrain(PulseMaxSpeed,30,100);
tspeed=(millis()%(PulseDuration*2)<PulseDuration?PulseMinSpeed:PulseMaxSpeed);
if (PulseSync)
return tspeed;
else
return (tspeed==PulseMinSpeed)?PulseMaxSpeed:PulseMinSpeed;
}
byte LongPulseMode(byte PulseMinSpeed, byte PulseMaxSpeed, int PulseDuration, boolean PulseSync)
{
byte tspeed=0;
PulseMinSpeed=constrain(PulseMinSpeed,30,100);
PulseMaxSpeed=constrain(PulseMaxSpeed,30,100);
tspeed=(now()%(PulseDuration*2)<PulseDuration?PulseMinSpeed:PulseMaxSpeed);
if (PulseSync)
return tspeed;
else
return (tspeed==PulseMinSpeed)?PulseMaxSpeed:PulseMinSpeed;
}
byte SineMode(byte PulseMinSpeed, byte PulseMaxSpeed, int PulseDuration, boolean PulseSync) {
double x,y;
x=double(now()%(PulseDuration));
x/=PulseDuration;
x*=2.0*PI;
if (!PulseSync) x+=PI; // shift the sine wave for the right pump
y=sin(x);// y is now between -1 and 1
y+=1.0; // y is now between 0 and 2
y/=2.0; // y is now between 0 and 1
// now compute the tunze speed
y*=double(PulseMaxSpeed-PulseMinSpeed);
y+=double(PulseMinSpeed);
y+=0.5; // for proper rounding
// y is now between PulseMinSpeed and PulseMaxSpeed, constrain for safety
return constrain(byte(y),30,100);
}
byte ReefCrestMode(byte WaveSpeed, byte WaveOffset, boolean PulseSync)
{
static unsigned long lastwavemillis=millis();
static int newspeed=WaveSpeed;
if ((millis()-lastwavemillis) > 5000)
{
if (random(100)<50) newspeed--; else newspeed++;
newspeed=constrain(newspeed,WaveSpeed-WaveOffset,WaveSpeed+WaveOffset);
newspeed=constrain(newspeed,0,100);
lastwavemillis=millis();
}
if (PulseSync)
return newspeed;
else
return WaveSpeed-(newspeed-WaveSpeed);
}
byte NutrientTransportMode(byte PulseMinSpeed, byte PulseMaxSpeed, int PulseDuration, boolean PulseSync)
{
static unsigned long lastwavemillis=millis();
static byte WavePhase=0;
static time_t WaveStart=0;
static byte speed=PulseMinSpeed;
static byte anti_speed=PulseMinSpeed;
if (WavePhase==0)
{
WavePhase++;
WaveStart=now();
}
else if (WavePhase==1)
{
if (now()-WaveStart>2700)
{
WavePhase++;
}
if ((millis()-lastwavemillis) > PulseDuration)
{
if (speed==PulseMinSpeed)
{
speed=PulseMaxSpeed;
anti_speed=PulseMinSpeed;
}
else
{
speed=PulseMinSpeed;
anti_speed=PulseMaxSpeed;
}
lastwavemillis=millis();
}
}
else if (WavePhase==2)
{
if (now()-WaveStart>4500) WavePhase++;
if (now()-WaveStart<=2760)
speed=PulseMinSpeed;
else
speed=PulseMaxSpeed;
if (now()-WaveStart<=3300)
anti_speed=PulseMinSpeed;
else
anti_speed=PulseMaxSpeed*sin(radians(map(now()-WaveStart,3300,4500,0,180)));
}
else if (WavePhase==3)
{
if (now()-WaveStart>7200) WavePhase++;
if ((millis()-lastwavemillis) > PulseDuration)
{
if (speed==PulseMinSpeed)
{
speed=PulseMaxSpeed;
anti_speed=PulseMinSpeed;
}
else
{
speed=PulseMinSpeed;
anti_speed=PulseMaxSpeed;
}
lastwavemillis=millis();
}
}
else if (WavePhase==4)
{
if (now()-WaveStart>9000) WavePhase=0;
if (now()-WaveStart<=7260)
speed=PulseMinSpeed;
else
speed=PulseMaxSpeed;
if (now()-WaveStart<=8400)
anti_speed=PulseMaxSpeed*sin(radians(map(now()-WaveStart,7200,8400,0,180)));
else
anti_speed=0;
}
if (PulseSync)
return speed;
else
return anti_speed;
}
byte TidalSwellMode(byte WaveMaxSpeed, boolean PulseSync)
{
static unsigned long lastwavemillis=millis();
static byte WavePhase=0;
static time_t WaveStart=0;
static byte speed=0;
static byte anti_speed=0;
if (WavePhase==0)
{
WavePhase++;
WaveStart=now();
}
else if (WavePhase==1)
{
if (now()-WaveStart>900) WavePhase++;
speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,0,900,0,90))))/10;
speed+=WaveMaxSpeed/2;
anti_speed=(WaveMaxSpeed*2*sin(radians(map(now()-WaveStart,0,900,0,90))))/5;
anti_speed+=WaveMaxSpeed/2;
}
else if (WavePhase==2)
{
if (now()-WaveStart>1800) WavePhase++;
speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,900,1800,90,180))))/20;
speed+=WaveMaxSpeed/2;
speed+=WaveMaxSpeed/20;
anti_speed=(WaveMaxSpeed*3*sin(radians(map(now()-WaveStart,900,1800,90,180))))/20;
anti_speed+=WaveMaxSpeed/2;
anti_speed+=WaveMaxSpeed/4;
}
else if (WavePhase==3)
{
if (now()-WaveStart>2700) WavePhase++;
speed=(WaveMaxSpeed*3*sin(radians(map(now()-WaveStart,1800,2700,0,90))))/20;
speed+=WaveMaxSpeed/2;
speed+=WaveMaxSpeed/20;
anti_speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,1800,2700,0,90))))/20;
anti_speed+=WaveMaxSpeed/2;
anti_speed+=WaveMaxSpeed/4;
}
else if (WavePhase==4)
{
if (now()-WaveStart>3600) WavePhase++;
speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,2700,3600,90,180))))/20;
speed+=WaveMaxSpeed/2;
speed+=(WaveMaxSpeed*3)/20;
anti_speed=(WaveMaxSpeed*3*sin(radians(map(now()-WaveStart,2700,3600,90,180))))/20;
anti_speed+=WaveMaxSpeed/2;
anti_speed+=(WaveMaxSpeed*3)/20;
}
else if (WavePhase==5)
{
if (now()-WaveStart>4500) WavePhase++;
speed=(WaveMaxSpeed*3*sin(radians(map(now()-WaveStart,3600,4500,0,90))))/20;
speed+=WaveMaxSpeed/2;
speed+=(WaveMaxSpeed*3)/20;
anti_speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,3600,4500,0,90))))/20;
anti_speed+=WaveMaxSpeed/2;
anti_speed+=(WaveMaxSpeed*3)/20;
}
else if (WavePhase==6)
{
if (now()-WaveStart>5400) WavePhase++;
speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,4500,5400,90,180))))/20;
speed+=WaveMaxSpeed/2;
speed+=(WaveMaxSpeed*5)/20;
anti_speed=(WaveMaxSpeed*3*sin(radians(map(now()-WaveStart,4500,5400,90,180))))/20;
anti_speed+=WaveMaxSpeed/2;
anti_speed+=WaveMaxSpeed/20;
}
else if (WavePhase==7)
{
if (now()-WaveStart>6300) WavePhase++;
speed=(WaveMaxSpeed*3*sin(radians(map(now()-WaveStart,5400,6300,0,90))))/20;
speed+=WaveMaxSpeed/2;
speed+=(WaveMaxSpeed*5)/20;
anti_speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,5400,6300,0,90))))/20;
anti_speed+=WaveMaxSpeed/2;
anti_speed+=WaveMaxSpeed/20;
}
else if (WavePhase==8)
{
if (now()-WaveStart>7200) WavePhase++;
speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,6300,7200,90,180))))/20;
speed+=WaveMaxSpeed/2;
speed+=(WaveMaxSpeed*7)/20;
anti_speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,6300,7200,90,180))))/10;
anti_speed+=WaveMaxSpeed/2;
}
else if (WavePhase==9)
{
if (now()-WaveStart>8100) WavePhase++;
speed=(WaveMaxSpeed*3*sin(radians(map(now()-WaveStart,7200,8100,0,90))))/20;
speed+=WaveMaxSpeed/2;
speed+=(WaveMaxSpeed*7)/20;
anti_speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,7200,8100,0,90))))/2;
anti_speed+=WaveMaxSpeed/2;
}
else if (WavePhase==10)
{
if (now()-WaveStart>9000) WavePhase=0;
speed=(WaveMaxSpeed*sin(radians(map(now()-WaveStart,8100,9000,90,180))))/2;
speed+=WaveMaxSpeed/2;
anti_speed=speed;
}
if (PulseSync)
return speed;
else
return anti_speed;
}
byte TideMode(byte WaveSpeed, byte minOffset, byte maxOffset)
{
// Contribution of lnevo
double moonOffset; // gap between high and low
double amplitude; // tide curve
double wavelength=12*SECS_PER_HOUR;
// Calculate the gap between high and low tide based on MoonPhase()
moonOffset=cos(((2*PI)/100)*MoonPhase());
moonOffset=((moonOffset+1)/2)*100; // Convert to percentage
// Find out the current tidal height
amplitude=sin(((2*PI)/wavelength)*now());
moonOffset=map(moonOffset,0,100,minOffset,maxOffset);
amplitude=amplitude*moonOffset;
// Adjust the calculate speed to be in our adjusted range
return constrain(WaveSpeed+amplitude,0,100);
}
lnevo wrote:You know all in all a case statement would probably have been simpler for you.
MI255 or MB255?lnevo wrote:255. But its a basically a constant mode by itself
Code: Select all
#define Mem_B_RFMode VarsStart+55
rimai wrote:It's byte size.
From Globals.h file:Code: Select all
#define Mem_B_RFMode VarsStart+55
You certainly don't need to run it via the RA but as the others already mentioned it's all about the controllability. The WP-40 at 100% speed was too much for my tank. I run it at ~80% with the RA and it's fine. I also want to do my own night modes and integrate it with my feeding mode.cosmith71 wrote:Can someone summarize the benefits of using RA to control this pump vs the stock controller? I tried to read through this thread, but it made my head hurt.![]()
--Colin