Adding PWM and Tuning with Internal Memory

Do you have a question on how to do something.
Ask in here.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

Im not currently running the internal memory option, and anything I change in memory on my ipad does not seem to change anything. Im not sure how to make the change to internal memory and keep my conditional logic.

I recently purchased the PWM Expansion and wanted to run my RA moonlights on channels 5 and 6. This would free up my relay PWM spaces for the WP40. I will need to figure what is the MAX percentage for the WP40 somehow, then use that number to set the range in the "Reef Crest Mode". Internal memory may not be my best option for the long run, but I dont know of an easier way to "tune" this pump.

I also have a few questions about updating the RA+ to accept the PWM:

I did not see any jumpers in my shipment. Are they in the RA+ already?
Can I run the RA moonlights with the PWM?
What would I select within the wizard for the standard PWM port that will run my WP40?
How would I switch to the Internal Memory option and keep my current program? (would I run the wizard to generate a basic code and go in and add my current if/then stuff, then upload?)


Any input would be great. Thanks!
Image
Piper
Posts: 298
Joined: Fri Jul 20, 2012 7:13 am
Location: Oakley, CA

Re: Adding PWM and Tuning with Internal Memory

Post by Piper »

I'm doing the same thing pretty much. I plugged my WP-40 into the PWM module for now but I'll be switching that around when I get a chance to re-wire everything.

If you recently picked up the RA I do believe they come with the jumpers in place now but I'm not 100% sure on that. Might be best for Roberto to answer that or pull it open and take a peek.

Can you post your code now? You can tell the wizard to use internal memory and it should do most of the leg work for you.

~Charlie
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

My current code should be VERY simliar to this:

// Ports that are always on

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


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

void loop()
{
\\Pump Delay 15min
ReefAngel.Relay.DelayedOn( Port1,15 );
\\Actinic 10am-10pm
ReefAngel.StandrdLights( Port3,10,0,22,0 );
\\MH 12pm-7pm
ReefAngel.StandardLights( Port7,12,0,19,0 );
ReefAngel.StandardLights( Port8,12,0,19,0 );
\\Powerhead Delay 1min
ReefAngel.Relay.DelayedOn( Port5,1 );
ReefAngel.Relay.DelayedOn( Port6,1 );
\\Fan on over 80
ReefAngel.StandardFan(Port2,790,800);
\\Overflow Protection
ReefAngel.Relay.Set(Port1,ReefAngel.HighATO.IsActive());
\\PWM Daylight off
ReefAngel.PWM.SetDaylight(0) );
\\Moonlight Phase 9pm-10am
if ( (hour() >=10) && (hour() <21) )
ReefAngel.PWM.SetActinic(0);
else
ReefAngel.PWM.SetActinic(MoonPhase() );
\\Kalk Dose 1min @ 2am-10am (every 30min)
if ( (hour() >=2) && (hour() <10) )
ReefAngel.Relay.Set(Port4, now()%1800<60);
else
ReefAngel.Relay.Off(Port4);
***\\Wave Maker
ReefAngel.WavemakerRandom1(Port5,10,60);
ReefAngel.WavemakerRandom2(Port6,25,90);**** Will be deleting once the WP40 comes
////// Place your custom code below here


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

// This should always be the last line
ReefAngel.Portal( "paulturner911" );
ReefAngel.ShowInterface();
}
Image
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

I don't see any internal memory settings in your code.
That's probably why you can't change anything.
Try running the wizard again, but make sure to pick internal memory settings.
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

rimai wrote:I don't see any internal memory settings in your code.
That's probably why you can't change anything.
Try running the wizard again, but make sure to pick internal memory settings.
Will do! I know it is NOT currently set...I went with what was suggested for new user :)
Any other input as to my questions?
Image
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

Your head unit should have the jumpers pre-installed already.
Yes, the dimmable moonlights actually need to be run on PWM.
You select nothing for the dimming channels, because you will need to change it anyway to add the wave modes
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

You rock!
Image
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

How does this look? I ran the wizard and added what I didnt see in the code. Please let me know if anything is going to conflict. Im not confident to upload this as I will not be around to monitor and I didnt get the gear mounted yet, I also am yet to pick a WP40 code. Is it safe to assume it would go under void loop like all of my other code?

#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 ); ////<----NOT SURE I NEEDED TO ADD THIS


// Ports that are always on

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


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

void loop()
{
ReefAngel.Relay.DelayedOn( Port1 );
ReefAngel.StandardFan( Port2 );
ReefAngel.ActinicLights( Port3 );
ReefAngel.Wavemaker1( Port5 );
ReefAngel.Wavemaker1( Port6 );
ReefAngel.DayLights( Port7 );
ReefAngel.DayLights( Port8 );
//Moonlight Phase 9pm-11am (CH4-CH5)
if ( (hour() >=11) && (hour() <21) )
ReefAngel.PWM.SetChannel( 4,(0) );
else
ReefAngel.PWM.SetChannel( 4, MoonPhase() );
if ( (hour() >=11) && (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.DelayedOn( Port1,15 );
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);


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


////// 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()
{
}

I would also like to have the return pump on "delay" ONLY when I run feed mode, NOTHING else. How would I write that conditional?
Image
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

Code looks good.
Yes, the wave code would go into the loop() section.
By default, the delay is on wc and feeding. Are you saying that you do not want it on wc?
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

My feed mode is 15min, then the wavemaker would run for another 15 and THEN the return pump would start. I would like the return pump (port1) to come on 15min after the feed mode has timed out. BUT when I do a water change I have to wait 15 min before it resumes. So I end up "masking" by overriding...
Image
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Adding PWM and Tuning with Internal Memory

Post by lnevo »

Why would you want your return pump on delayed start? I would just extend your feeding timer to 30 minutes.

Also any maintenance you do to your ra, or if any power outage/restore you're pump will be offline for 15 minutes...

I would switch that to an on port, make your feeding timer what you want (mem location 214 i believe) and then worry about your wavemaker...
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

lnevo has a good point.
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

I agree. I will end up with this as an always on(is that right ALWAYS??) in the event I can achieve what Im trying to do. I end up masking the pump all of the time. BUT, I would still want my wavemaker to run for 15min AFTER the 15min feed mode is complete, and BEFORE the return pump started filtering out the spot feed. My return pump will just suck everything out. What I want is (feedmode)15min zero flow; 15min Reefcrest- flow to stir anything up; 15min later return pump to clean it out.

Any way to do this?
Image
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

Try this:

Code: Select all

  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);
      }
    }
  }
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

Thanks, Ill run it and see what happens tonight. I do have a question:
When I install the WP it is NOT going to be port 5 or 6. It will be standard PWM daylight. How would I code that? This is also me assuming that I can provide 120v to the pump on a non system outlet and use the harness to activate it. I was also planning this for the future 4 MW drivers (non system 120v) and simply tie the PWM in to the RA vis PWM expansion. Is this correct?

Thanks so much.
Image
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

Yes, you can do that.
In which case, you would use something like this:

Code: Select all

ReefAngel.PWM.SetChannel(0,ShortPulseMode(20,100,300,true));
ReefAngel.PWM.SetChannel(1,ShortPulseMode(20,100,300,false));
ReefAngel.PWM.SetChannel(2,PWMSlope(11,0,21,0,15,100,60,0));
ReefAngel.PWM.SetChannel(3,PWMSlope(11,0,21,0,15,100,60,0));
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

Here is my current code:

////// 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.Wavemaker1( Port5 );
ReefAngel.Wavemaker1( Port6 );
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


////// 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()
{
}
Im having a few issues.
(fixed) 1.My powerheads (5-6) are cycling together every 10 seconds. I would like the to both be completely random..edit: I see why because BOTH are wavemaker1. I would like to randomize the time. Would I do this: ReefAngel.WavemakerRandom1( Port5,180,900 ); Repeat for 2 ????

2.I have run the wizard with internal memory. I cannot change the feed time length on my ipad in order to test the final section in my void loop (should make power heads turn random 1min after feed mode is complete and keep return pump off for additional 15min) NOW I dont see anything within the code referring to port 1(pump) ?!?! (this may have to do with the line in the code (900)??

3. My Standard PWM (D&A) are showing a percentage (100&20) While I did NOT program them for anything. (I also cannot adjust them via ipad) The PWM expansion is working showing 70% on ch4-5 (which is correct for my moonphase) that has yet to be corrected on my side. I was waiting for the new libs.


I think thats all for now. Please help (I know you guys will)

Thanks
Image
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

#2-Not understand what you are asking about port1.
#3-If you do not set channels AP/DP, they default to whatever is in memory location LEDPWMDaylight(220) and LEDPWMActinic(221)
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

2- Shouldnt I be able to change the feed mode length from my ipad under settings-memory-feed mode? Its there, it just doesnt change when I save it. Ill try from the portal instead.

3- How can I change this? Once I hook up and code the WP40 will it override StandardPWMDaylight? I would still like to clear the Actinic once I have the WP40.
Thanks
Image
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Adding PWM and Tuning with Internal Memory

Post by lnevo »

The iOS apps don't work right in my experience changing memory modes. Try doing it from a direct http connection...

http://reefangelwifi:2000/mi214,900

Modify the above to suit your needs.
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

Like I said, if you don't code anything, it defaults to whatever is in the memory. Once you code anything, it will do whatever you coded.
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

rimai wrote:#2-Not understand what you are asking about port1.
#3-If you do not set channels AP/DP, they default to whatever is in memory location LEDPWMDaylight(220) and LEDPWMActinic(221)
In the ipad app-settings-memory I have "custom" memloc: value:

I tried the locations you mentioned with 0 as the value. But it didnt take. What should it be? Im guessing this would also be how I tune the WP40 with memloc 220 and try to "up" the value untill I feel that its too much flow. Take that number and enter it is my max in the reefcrest code and choose a range?

Thanks a bunch!
Image
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

lnevo wrote:The iOS apps don't work right in my experience changing memory modes. Try doing it from a direct http connection...

http://reefangelwifi:2000/mi214,900

Modify the above to suit your needs.
Ok, it seems to be sketchy, it takes banner labels and time changes. What does mi214,900 mean? Is that the memory location, value? Should it be mi221,000 & 220,000? Ill pick back up in the morning. Thanks so much guys. I appreciate your help walking me through this!
Image
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Adding PWM and Tuning with Internal Memory

Post by rimai »

Yes, memory location and then value, but you need to use the correct size.
There are 2 sizes, int and byte size.
Feeding timer is int size and is located at 214, so you would browse /mi214.
DP and AP default settings are byte size and are located at 220 and 221, so you would browse /mb220.
I think the ipad app is broken. I know the android app works really well, but I have no experience with the iphone/ipad app :(
Roberto.
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

Awesome, it took. I was not seeing the change on the screen of the controller but it was browsing and showing the corrected values. So I then changed the feedtime, that took, but the DP/AP still showed 100/20. I just unplugged it and restarted the controller. 0/0 and 1000 feed time!! Thanks!!
Image
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

My WP does not turn off when in feedmode. Could someone fix this?

#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 | 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 | 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.DayLights( Port7 );
ReefAngel.DayLights( Port8 );
//Pull PWM Mem Loc Values
ReefAngel.PWM.SetActinic(InternalMemory.LEDPWMActinic_read());
ReefAngel.PWM.SetDaylight(InternalMemory.LEDPWMDaylight_read());
//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 HERE!!!
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)
{
ReefAngel.PWM.SetDaylight( 0 );
}
}
}


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

/* Reference for possible modes...

#define Constant 0
#define Lagoon 1
#define Random1 1 // Lagoonal
#define ReefCrest 2
#define Random2 2 // Reef Crest
#define ShortPulse 3
#define ShortWave 3
#define LongPulse 4
#define LongWave 4
#define NutrientTransport 5
#define Smart_NTM 5 // Nutrient Transport Mode
#define TidalSwell 6
#define Smart_TSM 6 // Tidal Swell Mode

*/
// Read memory for RF Wave Settings
int mode=InternalMemory.RFMode_read();
int speed=InternalMemory.RFSpeed_read();
int duration=InternalMemory.RFDuration_read();
//ReefCrest
if (mode = ReefCrest) {
ReefAngel.PWM.SetDaylight ( ReefCrestMode(50,30,false) ); // ReefCrest at 50 +/- 30 in anti-sync mode
} else {
ReefAngel.PWM.SetDaylight( speed / 2 );
}
//Short Pulse

//Long Pulse

//Sine

//Nutrient Trans

//Tide Mode

//Tidal Swell Call



////// 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()
{
}


//ShortPulseMode
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;
}


//LongPulseMode
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;
}


//SineMode
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);
}


//ReefCrestMode
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);
}


//NutrientTransportMode
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;
}

//TidalSwellMode
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;
}

//TideMode
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);
}


I thought it was //Feed Mode Delay on Pump HERE!!!
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)
{
ReefAngel.PWM.SetDaylight( 0 ); <----THIS

Maybe it is conflicting with reefcrest?
Image
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Adding PWM and Tuning with Internal Memory

Post by lnevo »

I'll fix it on the train tomorrow. The new code is overriding it...
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Adding PWM and Tuning with Internal Memory

Post by lnevo »

Ok Paul,

This should do it.... all modes implemented. Feeding delay in place. Please read through and let me know if any questions.i'd like to make sure you understand all that we've added. The logic that rimai gave you threw me off, and I had to read through the thread a bit. Let me know if 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 <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();
  }
}

///// 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;

// keep wavemakers off for first 15 minutes of feeding mode.
if (now()-feedingstarted<=900 && ReefAngel.DisplayedMenu==FEEDING_MODE) {
    ReefAngel.PWM.SetDaylight( 0 );
    ReefAngel.PWM.SetActinic( 0 );
} else 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);
}
Paulturner911
Posts: 287
Joined: Wed Jan 23, 2013 12:36 pm

Re: Adding PWM and Tuning with Internal Memory

Post by Paulturner911 »

I understand most of ti when I read it, Because Ive asked for "xxx" I just have no skill at translating it to code.
Thank You!!

I see where you created a boolean for feed mode then reference it above the rf functionis. So Im pretty sure inorder to do what I want I will set the feedmode to 30min and for the first 15min I will have zero flow, 15min in the wp will kick on in any mode I had chosen in the portal, it will run my pumps at the 30min point in which feed mode is complete.
Image
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Adding PWM and Tuning with Internal Memory

Post by lnevo »

Yep
Post Reply