Page 1 of 2
Dim LEDs with PWM expansion and alternate wavemaker
Posted: Sun Feb 12, 2012 9:50 pm
by Aricml
I am trying to set up my RA I purchased. I bought the main unit, expansion hub, PWM expansion, two moonlights and will have my Wifi expansion here shortly. I am trying to figure out how to get some things set up how I was dreaming. I read the tutorials and have tried my best to understand the threads and I'll just get it out of the way and say this is what I've got so far for a PDE
Code: Select all
// Autogenerated file by RAGen (v1.0.4.92), (09/17/2011 15:54)
// RA_091711_1554.pde
//
// This version designed for v0.8.5 Beta 12 or later
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
//*********************************************************************************************************************************
//Start of PWM Expansion Code Header
// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5
// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};
//End of PWM Expansion Code Header
//*********************************************************************************************************************************
//*********************************************************************************************************************************
//Start of PWM slope function code designed for the PWM Expansion module
void PWMExpansion(byte cmd, byte data)
{
Wire.beginTransmission(8); // transmit to device #2
Wire.send('$'); // sends $
Wire.send('$'); // sends $
Wire.send('$'); // sends $
Wire.send(cmd); // sends a value
Wire.send(data); // sends 255
Wire.endTransmission(); // stop transmitting
}
//End of PWM slope function code designed for the PWM Expansion module
//*********************************************************************************************************************************
void setup()
{
ReefAngel.Init(); //Initialize controller
ReefAngel.FeedingModePorts = B00110000;
ReefAngel.WaterChangePorts = B00110001;
ReefAngel.OverheatShutoffPorts = B00001101;
ReefAngel.LightsOnPorts = B00111101;
//*********************************************************************************************************************************
//Start of PWM Expansion Code for Slope
PWMChannel[LEDPWM0]=PWMSlope(09,0,18,00,10,75,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(09,0,18,00,10,75,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(07,30,20,00,20,90,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(07,30,20,00,20,90,75,PWMChannel[LEDPWM3]);
// The lines above are what calculates the slope.
// You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
// The are as follow:
// 1st parameter: hour to start slope
// 2nd parameter: minute to start slope
// 3rd parameter: hour to end slope
// 4th parameter: minute to end slope
// 5th parameter: % of the PWM signal to start slope
// 6th parameter: % of the PWM signal to end slope
// 7th parameter: duration of slope in minutes
// 8th parameter: always the same as the variable before the PWMSlope() call
//PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);
// In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
// Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
// Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
PWMExpansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
PWMExpansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
PWMExpansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
PWMExpansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
//End of PWM Expansion Code for Slope
//*********************************************************************************************************************************
}
void loop()
{
ReefAngel.ShowInterface();
// Specific functions
ReefAngel.StandardLights(Port2);
ReefAngel.StandardLights(Port3);
ReefAngel.StandardLights(Port4);
ReefAngel.Wavemaker1(Port5);
ReefAngel.Wavemaker2(Port6);
}
I built two LED lights which work fantastically althought so far I'd just been using a regulated power supply to make them work. I want desperately to be able to dim my LEDs, with the Actinic (which I've connected to Channels 2 and 3 on the PWM expansion) coming on around 7:30am, ramping up, then ramping back down to be off by 8pm. The Daylight LEDs (on channels 0 and 1 on the PWM expansion) would come on at 9, ramp, deramp and be off by 6pm. I was hoping to be able to plug the moonlights into the PWM inputs on the relay and have them come on when the Daylights are not on, but I have not yet figured this out at all.
I would also like to be able to figure out how to have my Wavemakers (on ports 5 and 6) alternate like it was capable of with the stock software instead of being both-on/both-off like they are now due to my ignorance.
Before my RA got here I dreamed of being able to start a cloud function (or even series) by selecting something from the menu as well as start a thunderstorm function that would last a minute or so. I realize that such things aren't likely to be possible for me now, and would just like to be able to get the PWM expansion to work for me and get my circulation pumps alternating again to keep my tank functioning.
Sorry to pour all these words out, but if anyone can take a look at this and help me, it would mean the world to me.
As of right now when I try to verify this code I get the following error message..
PWMExpansionCommands.cpp:90:34: error: invalid digit "9" in octal constant
PWMExpansionCommands.cpp:91:34: error: invalid digit "9" in octal constant
Honestly I'm desperate and would be willing to pay for a PDE file that could make this controller work like I was hoping to be able to make it work
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Mon Feb 13, 2012 8:44 am
by rimai
Almost there
It was a pretty good start!!!
The error was caused by the 0 in front of the 9.
Code: Select all
PWMChannel[LEDPWM0]=PWMSlope(09,0,18,00,10,75,60,PWMChannel[LEDPWM0]);
Removing it would compile your code without errors
Anyway, I changed your code a bit to include the opposite cycle WM and moonlights.
I also went ahead and already created the custom menu and added the clouds/thunderstorm to it.
Check it out and let me know if it works.
You will need to overwrite your features file with this.
The features file is located at "Documents\Arduino\libraries\ReefAngel_Features"
Code: Select all
#ifndef __REEFANGEL_FEATURES_H__
#define __REEFANGEL_FEATURES_H__
#define VersionMenu
#define DisplayLEDPWM
#define wifi
#define WDT
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 5
#define PWMEXPANSION
#endif // __REEFANGEL_FEATURES_H__
And here is your code:
Code: Select all
// Autogenerated file by RAGen (v1.0.4.92), (09/17/2011 15:54)
// RA_091711_1554.pde
//
// This version designed for v0.8.5 Beta 12 or later
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
//*********************************************************************************************************************************
//Start of PWM Expansion Code Header
// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5
// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};
//End of PWM Expansion Code Header
//*********************************************************************************************************************************
boolean ForceCloud=false;
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Water Change Mode";
prog_char menu2_label[] PROGMEM = "Force Cloud";
prog_char menu3_label[] PROGMEM = "Clear ATO Timeout";
prog_char menu4_label[] PROGMEM = "About Me";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ForceCloud=true;
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.ATOClear();
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.DisplayVersion();
}
void setup()
{
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
ReefAngel.FeedingModePorts = B00110000;
ReefAngel.WaterChangePorts = B00110001;
ReefAngel.OverheatShutoffPorts = B00001101;
ReefAngel.LightsOnPorts = B00111101;
}
void loop()
{
// Specific functions
ReefAngel.StandardLights(Port2);
ReefAngel.StandardLights(Port3);
ReefAngel.StandardLights(Port4);
ReefAngel.Wavemaker1(Port5);
//Set Port6 to alternate with Port 6 in opposite cycle
if (bitRead(ReefAngel.Relay.RelayData,4))
ReefAngel.Relay.Off(Port6);
else
ReefAngel.Relay.On(Port6);
// Monnlight schedule
if (hour()<9 || hour()>=18)
{
// Set Moonlights to follow the moon cycle
ReefAngel.PWM.SetDaylight(MoonPhase());
ReefAngel.PWM.SetActinic(MoonPhase());
}
//*********************************************************************************************************************************
//Start of PWM Expansion Code for Slope
PWMChannel[LEDPWM0]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM3]);
// The lines above are what calculates the slope.
// You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
// The are as follow:
// 1st parameter: hour to start slope
// 2nd parameter: minute to start slope
// 3rd parameter: hour to end slope
// 4th parameter: minute to end slope
// 5th parameter: % of the PWM signal to start slope
// 6th parameter: % of the PWM signal to end slope
// 7th parameter: duration of slope in minutes
// 8th parameter: always the same as the variable before the PWMSlope() call
//PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);
// In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
// Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
// Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
CheckCloud();
ReefAngel.PWM.Expansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
ReefAngel.PWM.Expansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
ReefAngel.PWM.Expansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
ReefAngel.PWM.Expansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
//End of PWM Expansion Code for Slope
//*********************************************************************************************************************************
ReefAngel.ShowInterface();
}
//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{
// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect
// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur everyday
#define Clouds_Every_X_Days 1
// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening
#define Cloud_Chance_per_Day 100
// Minimum number of minutes for cloud duration. Don't use max duration of less than 6
#define Min_Cloud_Duration 7
// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255
#define Max_Cloud_Duration 15
// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 3
// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5
// Only start the cloud effect after this setting
// In this example, start could after 11:30am
#define Start_Cloud_After NumMins(9,0)
// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(18,0)
// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening
#define Lightning_Change_per_Cloud 100
// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for actinics
#define Actinic_Channels B001100
// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for daylights
#define Daylight_Channels B000011
// Note: Make sure to choose correct values that will work within your PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen resul could happen.
// Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can fit in that 510 minutes window.
// It's a tight fit, but it did.
//#define printdebug // Uncomment this for debug print on Serial Monitor window
#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.
// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here
static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;
#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day.
cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the effect
if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope
PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,180);
}
}
if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
for (int b=0;b<6;b++)
{
if (bitRead(Daylight_Channels,b)==1)
{
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) PWMChannel[b]=100;
else PWMChannel[b]=0;
//delay(10);
}
else
{
PWMChannel[b]=20;
}
}
}
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{
cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}
if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,5,120,"C");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,45,120,"L");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11; else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
if ((cloudstart%60)>=10) x=29; else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
}
}
}
byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 1:16 am
by Aricml
Roberto, thank you so much for the code, I really appreciate your willingness to help. I am having an error when I try to Upload the software of 'RETURN_MAIN_MODE' was not declared in this scope. I however did just update to the new 0.9 libraries which I'm feeling very well may be a cause of me not being able to upload the code you wrote.
I also wanted to ask you about the first smaller segment of code
Code: Select all
#ifndef __REEFANGEL_FEATURES_H__
#define __REEFANGEL_FEATURES_H__
#define VersionMenu
#define DisplayLEDPWM
#define wifi
#define WDT
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 5
#define PWMEXPANSION
#endif // __REEFANGEL_FEATURES_H__
Was I to insert this over the top of
Code: Select all
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
in the code that you generated for me? I am sorry for not understanding what to do with that. For what it's worth I did try compiling both ways and came up with the same error. Thank you again for your help, I really appreciate everything.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 6:05 am
by binder
This code:
Code: Select all
#ifndef __REEFANGEL_FEATURES_H__
#define __REEFANGEL_FEATURES_H__
#define VersionMenu
#define DisplayLEDPWM
#define wifi
#define WDT
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 5
#define PWMEXPANSION
#endif // __REEFANGEL_FEATURES_H__
should be placed inside the ReefAngel_Features/ReefAngel_Features.h file. It should replace its contents. It does not have to be put at the top of the PDE/INO file like you mentioned. The top part of the PDE/INO file is simply there for a reference to see what features were enabled when you used RAGen to create your PDE/INO file.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 9:40 am
by Aricml
Thank you very much Curt, I got that replaced right away. However I still get the error 'RETURN_MAIN_MODE' not declared in this scope.
I tried to find other people with similar issues and it seems like the code just doesn't know what RETURN_MAIN_MODE is referencing to, but I do not know how to fix that. Thank you so much for your help already and hopefully if you can help me one more time so I can get this to compile and upload I can make the controller work!
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 9:57 am
by binder
Aricml wrote:Thank you very much Curt, I got that replaced right away. However I still get the error 'RETURN_MAIN_MODE' not declared in this scope.
I tried to find other people with similar issues and it seems like the code just doesn't know what RETURN_MAIN_MODE is referencing to, but I do not know how to fix that. Thank you so much for your help already and hopefully if you can help me one more time so I can get this to compile and upload I can make the controller work!
I have not heard or am familiar with RETURN_MAIN_MODE. I'm going to do a quick search on the code and see what / where it's referenced and what could be going on.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 10:04 am
by binder
Ok, doing a quick search I found out the problem. I remember now what that is referencing and why it is used.
It should be inside your ReefAngel_Globals.h file. If you open up the ReefAngel_Globals/ReefAngel_Globals.h file, you should be able to locate this line:
If it is not there, then that means that you may have an old/outdated version of the libraries. Make sure you have 0.8.5.19 or later with the libraries. You need a minimum of 0.8.5.17 to use the Custom Menu as well.
Here's a link to the custom menu tutorial:
http://forum.reefangel.com/viewtopic.php?f=14&t=311
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 10:54 am
by rimai
I think it is due to the libraries header. He mentioned updating to 0.9.0
Can you post your code?
We need to modify the headers to work on v0.9.0
http://forum.reefangel.com/viewtopic.php?f=7&t=725
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 11:01 am
by Aricml
I did update to 0.90 libraries and I also think this is a cause for my confusion rimai. I referenced the thread in Development Libraries and compared the instructions to what I have and added in some headers that I thought would help, and they did to a degree. I no longer have trouble with 'RETURN_MAIN_MODE'. When I verify/compile it makes it all the way to the bottom where it errors with "class ReefAngelClass' has no member named 'LCD'. Here is my code, all the headers at the top are probably obviously what I clumsily tossed in there.
Code: Select all
#include <IO.h>
#include <Timer.h>
#include <ReefAngel.h>
#include <Phillips6610LCD.h>
#include <Memory.h>
#include <RA_PWM.h>
#include <Relay.h>
#include <RA_TempSensor.h>
#include <LED.h>
#include <RA_Joystick.h>
#include <RA_ATO.h>
#include <NokiaLCD.h>
#include <InternalEEPROM.h>
#include <RA_Wifi.h>
#include <Globals.h>
// Autogenerated file by RAGen (v1.0.4.92), (09/17/2011 15:54)
// RA_091711_1554.pde
//
// This version designed for v0.8.5 Beta 12 or later
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
//*********************************************************************************************************************************
//Start of PWM Expansion Code Header
// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5
// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};
//End of PWM Expansion Code Header
//*********************************************************************************************************************************
boolean ForceCloud=false;
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Water Change Mode";
prog_char menu2_label[] PROGMEM = "Force Cloud";
prog_char menu3_label[] PROGMEM = "Clear ATO Timeout";
prog_char menu4_label[] PROGMEM = "About Me";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ForceCloud=true;
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.ATOClear();
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.DisplayVersion();
}
void setup()
{
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
ReefAngel.FeedingModePorts = B00110000;
ReefAngel.WaterChangePorts = B00110001;
ReefAngel.OverheatShutoffPorts = B00001101;
ReefAngel.LightsOnPorts = B00111101;
}
void loop()
{
// Specific functions
ReefAngel.StandardLights(Port2);
ReefAngel.StandardLights(Port3);
ReefAngel.StandardLights(Port4);
ReefAngel.Wavemaker1(Port5);
//Set Port6 to alternate with Port 6 in opposite cycle
if (bitRead(ReefAngel.Relay.RelayData,4))
ReefAngel.Relay.Off(Port6);
else
ReefAngel.Relay.On(Port6);
// Monnlight schedule
if (hour()<9 || hour()>=18)
{
// Set Moonlights to follow the moon cycle
ReefAngel.PWM.SetDaylight(MoonPhase());
ReefAngel.PWM.SetActinic(MoonPhase());
}
//*********************************************************************************************************************************
//Start of PWM Expansion Code for Slope
PWMChannel[LEDPWM0]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM3]);
// The lines above are what calculates the slope.
// You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
// The are as follow:
// 1st parameter: hour to start slope
// 2nd parameter: minute to start slope
// 3rd parameter: hour to end slope
// 4th parameter: minute to end slope
// 5th parameter: % of the PWM signal to start slope
// 6th parameter: % of the PWM signal to end slope
// 7th parameter: duration of slope in minutes
// 8th parameter: always the same as the variable before the PWMSlope() call
//PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);
// In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
// Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
// Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
CheckCloud();
ReefAngel.PWM.Expansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
ReefAngel.PWM.Expansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
ReefAngel.PWM.Expansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
ReefAngel.PWM.Expansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
//End of PWM Expansion Code for Slope
//*********************************************************************************************************************************
ReefAngel.ShowInterface();
}
//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{
// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect
// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur everyday
#define Clouds_Every_X_Days 1
// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening
#define Cloud_Chance_per_Day 100
// Minimum number of minutes for cloud duration. Don't use max duration of less than 6
#define Min_Cloud_Duration 7
// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255
#define Max_Cloud_Duration 15
// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 3
// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5
// Only start the cloud effect after this setting
// In this example, start could after 11:30am
#define Start_Cloud_After NumMins(9,0)
// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(18,0)
// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening
#define Lightning_Change_per_Cloud 100
// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for actinics
#define Actinic_Channels B001100
// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for daylights
#define Daylight_Channels B000011
// Note: Make sure to choose correct values that will work within your PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen resul could happen.
// Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can fit in that 510 minutes window.
// It's a tight fit, but it did.
//#define printdebug // Uncomment this for debug print on Serial Monitor window
#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.
// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here
static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;
#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day.
cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the effect
if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope
PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,180);
}
}
if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
for (int b=0;b<6;b++)
{
if (bitRead(Daylight_Channels,b)==1)
{
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) PWMChannel[b]=100;
else PWMChannel[b]=0;
//delay(10);
}
else
{
PWMChannel[b]=20;
}
}
}
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{
cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}
if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,5,120,"C");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,45,120,"L");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11; else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
if ((cloudstart%60)>=10) x=29; else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
}
}
}
byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
Hopefully it is something simple to you that I messed up as I'm not sure what else I could do to make it recognize 'LCD' thank you both again for your help I appreciate it.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 11:13 am
by rimai
There is nothing wrong with the code.
Just the headers on the top of the code.
Replace all this:
Code: Select all
#include <IO.h>
#include <Timer.h>
#include <ReefAngel.h>
#include <Phillips6610LCD.h>
#include <Memory.h>
#include <RA_PWM.h>
#include <Relay.h>
#include <RA_TempSensor.h>
#include <LED.h>
#include <RA_Joystick.h>
#include <RA_ATO.h>
#include <NokiaLCD.h>
#include <InternalEEPROM.h>
#include <RA_Wifi.h>
#include <Globals.h>
// Autogenerated file by RAGen (v1.0.4.92), (09/17/2011 15:54)
// RA_091711_1554.pde
//
// This version designed for v0.8.5 Beta 12 or later
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
With this:
Code: Select all
#include <Salinity.h>
#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 <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <ReefAngel.h>
These are the new header files needed starting on v0.9.0
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 11:29 am
by Aricml
Ok I replaced it so this is the code I'm trying to compile
Code: Select all
// Autogenerated file by RAGen (v1.0.4.92), (09/17/2011 15:54)
// RA_091711_1554.pde
//
// This version designed for v0.8.5 Beta 12 or later
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
#include <Salinity.h>
#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 <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <ReefAngel.h>
//*********************************************************************************************************************************
//Start of PWM Expansion Code Header
// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5
// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};
//End of PWM Expansion Code Header
//*********************************************************************************************************************************
boolean ForceCloud=false;
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Water Change Mode";
prog_char menu2_label[] PROGMEM = "Force Cloud";
prog_char menu3_label[] PROGMEM = "Clear ATO Timeout";
prog_char menu4_label[] PROGMEM = "About Me";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ForceCloud=true;
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.ATOClear();
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.DisplayVersion();
}
void setup()
{
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
ReefAngel.FeedingModePorts = B00110000;
ReefAngel.WaterChangePorts = B00110001;
ReefAngel.OverheatShutoffPorts = B00001101;
ReefAngel.LightsOnPorts = B00111101;
}
void loop()
{
// Specific functions
ReefAngel.StandardLights(Port2);
ReefAngel.StandardLights(Port3);
ReefAngel.StandardLights(Port4);
ReefAngel.Wavemaker1(Port5);
//Set Port6 to alternate with Port 6 in opposite cycle
if (bitRead(ReefAngel.Relay.RelayData,4))
ReefAngel.Relay.Off(Port6);
else
ReefAngel.Relay.On(Port6);
// Monnlight schedule
if (hour()<9 || hour()>=18)
{
// Set Moonlights to follow the moon cycle
ReefAngel.PWM.SetDaylight(MoonPhase());
ReefAngel.PWM.SetActinic(MoonPhase());
}
//*********************************************************************************************************************************
//Start of PWM Expansion Code for Slope
PWMChannel[LEDPWM0]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM3]);
// The lines above are what calculates the slope.
// You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
// The are as follow:
// 1st parameter: hour to start slope
// 2nd parameter: minute to start slope
// 3rd parameter: hour to end slope
// 4th parameter: minute to end slope
// 5th parameter: % of the PWM signal to start slope
// 6th parameter: % of the PWM signal to end slope
// 7th parameter: duration of slope in minutes
// 8th parameter: always the same as the variable before the PWMSlope() call
//PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);
// In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
// Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
// Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
CheckCloud();
ReefAngel.PWM.Expansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
ReefAngel.PWM.Expansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
ReefAngel.PWM.Expansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
ReefAngel.PWM.Expansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
//End of PWM Expansion Code for Slope
//*********************************************************************************************************************************
ReefAngel.ShowInterface();
}
//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{
// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect
// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur everyday
#define Clouds_Every_X_Days 1
// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening
#define Cloud_Chance_per_Day 100
// Minimum number of minutes for cloud duration. Don't use max duration of less than 6
#define Min_Cloud_Duration 7
// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255
#define Max_Cloud_Duration 15
// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 3
// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5
// Only start the cloud effect after this setting
// In this example, start could after 11:30am
#define Start_Cloud_After NumMins(9,0)
// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(18,0)
// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening
#define Lightning_Change_per_Cloud 100
// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for actinics
#define Actinic_Channels B001100
// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for daylights
#define Daylight_Channels B000011
// Note: Make sure to choose correct values that will work within your PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen resul could happen.
// Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can fit in that 510 minutes window.
// It's a tight fit, but it did.
//#define printdebug // Uncomment this for debug print on Serial Monitor window
#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.
// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here
static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;
#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day.
cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the effect
if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope
PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,180);
}
}
if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
for (int b=0;b<6;b++)
{
if (bitRead(Daylight_Channels,b)==1)
{
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) PWMChannel[b]=100;
else PWMChannel[b]=0;
//delay(10);
}
else
{
PWMChannel[b]=20;
}
}
}
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{
cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}
if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,5,120,"C");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,45,120,"L");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11; else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
if ((cloudstart%60)>=10) x=29; else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
}
}
}
byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
And I'm still getting a non-specific error, the red bar just says "Error compiling."
The subtext of the error reads..
In file included from C:\Users\Ultra Peepi\Documents\Arduino\libraries\Salinity/Salinity.h:25,
from sketch_feb14a.cpp:15:
C:\Users\Ultra Peepi\Documents\Arduino\libraries\Globals/Globals.h:29:21: error: Arduino.h: No such file or directory
First, yes that is the silly user name on my PC, Second, I don't know where to look when the computer doesn't show me where the error is. I'm really sorry to be such a pain in the butt, I just can't seem to help it.. but thank you so much for trying to help me.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 11:36 am
by rimai
Oh, you can't just update the libraries.
You need to get the whole package.
I suggest you uninstall the previous installer and download the newer one that will come with updated libraries, updated RAGen and updated Arduino IDE.
Check out Curt's post:
http://forum.reefangel.com/viewtopic.php?f=7&t=725
Download new installer here:
http://www.reefangel.com/Download.ashx
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 12:11 pm
by Aricml
Everything is updated, I now have the Arduino 1.0, tossed in the above sketch, hit verify/compile and get the error message "sketch too big" Is there anything I can do about this by cutting something out?
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 12:16 pm
by rimai
Open RAGen
Go to features tab
Use the following:
- Wifi
- Watchdog timer
- Custom menu
- PWM Expansion
- Version Menu
- Display LED PWM
Click Save Button
RAGen is better than ever now!!!
You can use RAGen to enable and disable features without having to manually edit the features file
Try compiling again.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 1:01 pm
by Aricml
I did what you said and opened RAGen, which does look new and excellent by the way. I clocked features and had selected only what you told me to, hit 'Save', then 'Close' then I opened Arduino - Reef Angel Controller, tried to compile that same code and got;
C:\Users\Ultra Peepi\Documents\Arduino\libraries\Salinity\Salinity.cpp: In member function 'int SalinityClass::Read()':
C:\Users\Ultra Peepi\Documents\Arduino\libraries\Salinity\Salinity.cpp:37: error: 'class TwoWire' has no member named 'read'
C:\Users\Ultra Peepi\Documents\Arduino\libraries\Salinity\Salinity.cpp:39: error: 'class TwoWire' has no member named 'read'
I reupdated libraries just to be sure, tried again and got the same thing. I feel like I'm missing something that to you and Binder is super obvious, I just obviously don't know what..
Edit: I see how I can use RAGen to change those parameters but I'm not sure how to make that apply to the code you have written for me, since I would love to have the PWM functions you set up as well as the alternating wavemakers. Aside from not understanding, what am I doing wrong?
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 2:24 pm
by Aricml
One more thing if it helps anyone know what I'm messing up, even when I use the new RAGen, I get a similar error, which I'll display here.
C:\Users\Ultra Peepi\Documents\Arduino\libraries\DS1307RTC\DS1307RTC.cpp:71: error: 'class TwoWire' has no member named 'read'
C:\Users\Ultra Peepi\Documents\Arduino\libraries\DS1307RTC\DS1307RTC.cpp: In static member function 'static void DS1307RTC::write(tmElements_t&)':
C:\Users\Ultra Peepi\Documents\Arduino\libraries\DS1307RTC\DS1307RTC.cpp:87: error: 'class TwoWire' has no member named 'write'
This is pretty frustrating, I keep thinking I'll be able to upload this code each time you all help me and somehow I just can't seem to get it correct. I hope that what I've got going on makes some type of sense to you, thanks again
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 4:40 pm
by rimai
You are still using the same old Arduino.
When you open Arduino IDE, what do you see on the window title?
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 5:05 pm
by Aricml
I used to see Arduino alpha, but early today, after the advice to uninstall and reinstall everything I now just see Arduino with the infinity logo. And the banner on the program indicates Arduino 1.0.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 5:13 pm
by Aricml
Oh by the way I must have not hit post a while back, I had made a message indicating that I got the code to compile and load onto the RA by deleting my User/Arduino folder and reinstalling with the Library Update Tool. The problem now is that despite being able to load the code that you built for me, as well as RAGen code, my controller has a white screen that reads, No Internal Memory Found.
Also unfortunatly although I can use RAGen to build a new internal memory file, I cant seem to load it onto the unit as I get a long list of error messages that look like
error: 'class RA_NokiaLCD' has no member named 'lcd_draw_text'
Just for example, so I can't use my controller in any way at the moment.
I can't even upload ReefAngelSimple to put the unit back to stock code..
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 5:18 pm
by rimai
Ha...
I think you found the first bug of RAGen.
There is a bunch of example codes, that may have been put in the old forder that you renamed.
There is one that is called InitialInternalMemory.
That can be used instead.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 6:00 pm
by Aricml
Oh wow, using that memory file did indeed unstuck me. I was able to load that generic memory file and then load the code which I will copy here again
Code: Select all
// Autogenerated file by RAGen (v1.0.4.92), (09/17/2011 15:54)
// RA_091711_1554.pde
//
// This version designed for v0.8.5 Beta 12 or later
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
#include <Salinity.h>
#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 <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <ReefAngel.h>
//*********************************************************************************************************************************
//Start of PWM Expansion Code Header
// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5
// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};
//End of PWM Expansion Code Header
//*********************************************************************************************************************************
boolean ForceCloud=false;
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Water Change Mode";
prog_char menu2_label[] PROGMEM = "Force Cloud";
prog_char menu3_label[] PROGMEM = "Clear ATO Timeout";
prog_char menu4_label[] PROGMEM = "About Me";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ForceCloud=true;
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.ATOClear();
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.DisplayVersion();
}
void setup()
{
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
ReefAngel.FeedingModePorts = B00110000;
ReefAngel.WaterChangePorts = B00110001;
ReefAngel.OverheatShutoffPorts = B00001101;
ReefAngel.LightsOnPorts = B00111101;
}
void loop()
{
// Specific functions
ReefAngel.StandardLights(Port2);
ReefAngel.StandardLights(Port3);
ReefAngel.StandardLights(Port4);
ReefAngel.Wavemaker1(Port5);
//Set Port6 to alternate with Port 6 in opposite cycle
if (bitRead(ReefAngel.Relay.RelayData,4))
ReefAngel.Relay.Off(Port6);
else
ReefAngel.Relay.On(Port6);
// Monnlight schedule
if (hour()<9 || hour()>=18)
{
// Set Moonlights to follow the moon cycle
ReefAngel.PWM.SetDaylight(MoonPhase());
ReefAngel.PWM.SetActinic(MoonPhase());
}
//*********************************************************************************************************************************
//Start of PWM Expansion Code for Slope
PWMChannel[LEDPWM0]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM3]);
// The lines above are what calculates the slope.
// You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
// The are as follow:
// 1st parameter: hour to start slope
// 2nd parameter: minute to start slope
// 3rd parameter: hour to end slope
// 4th parameter: minute to end slope
// 5th parameter: % of the PWM signal to start slope
// 6th parameter: % of the PWM signal to end slope
// 7th parameter: duration of slope in minutes
// 8th parameter: always the same as the variable before the PWMSlope() call
//PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);
// In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
// Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
// Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
CheckCloud();
ReefAngel.PWM.Expansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
ReefAngel.PWM.Expansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
ReefAngel.PWM.Expansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
ReefAngel.PWM.Expansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
//End of PWM Expansion Code for Slope
//*********************************************************************************************************************************
ReefAngel.ShowInterface();
}
//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{
// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect
// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur everyday
#define Clouds_Every_X_Days 1
// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening
#define Cloud_Chance_per_Day 100
// Minimum number of minutes for cloud duration. Don't use max duration of less than 6
#define Min_Cloud_Duration 7
// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255
#define Max_Cloud_Duration 15
// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 3
// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5
// Only start the cloud effect after this setting
// In this example, start could after 11:30am
#define Start_Cloud_After NumMins(9,0)
// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(18,0)
// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening
#define Lightning_Change_per_Cloud 100
// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for actinics
#define Actinic_Channels B001100
// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for daylights
#define Daylight_Channels B000011
// Note: Make sure to choose correct values that will work within your PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen resul could happen.
// Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can fit in that 510 minutes window.
// It's a tight fit, but it did.
//#define printdebug // Uncomment this for debug print on Serial Monitor window
#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.
// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here
static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;
#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day.
cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the effect
if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope
PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,180);
}
}
if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
for (int b=0;b<6;b++)
{
if (bitRead(Daylight_Channels,b)==1)
{
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) PWMChannel[b]=100;
else PWMChannel[b]=0;
//delay(10);
}
else
{
PWMChannel[b]=20;
}
}
}
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{
cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}
if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,5,120,"C");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,45,120,"L");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11; else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
if ((cloudstart%60)>=10) x=29; else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
}
}
}
byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
I can even see my temperature and te graph, if only briefly. Now my controller is flashing on and off with about a second or so in between, if it matters, when the screen turns off the red status led flashes 3 times quickly. Ive tried reinstalling the generic internal memory code and the system code over again, yet I still get a flashing on and off main controller. Thanks for the help I feel like I'm closer to making this work, if only it would stay on!
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 6:08 pm
by rimai
That looks like the watchdog kicking in.
I tested this code and I don't get the same behavior.
Can you unplug the PWM expansion module?
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 6:23 pm
by Aricml
unplugging the pwm expansion module alone didnt solve the problem, I had to unplug the the Expansion Hub. I know it's silly to have the expansion hub with only 1 module plugged into it, when I bought it, I got the expansion hub to make it easy to add more things on later. When I unplugged the expansion module from the relay box, the controller stopped flashing on and off. I can even plug the PWM expansion port right into the relay box, however that turns my lights off.
When the PWM expansion port is plugged into power but either the expansion hub or no USB at all I get what looks like medium-power out of my LEDs, when the usb from the PWM expansion is plugged into the relay box, I get nothing out of my lights.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 6:32 pm
by rimai
Is this the newer model of expansion hub??
Was the PWM module working before or this is the first attempt to get them working?
Is it before 8pm where u are?
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 6:53 pm
by Aricml
Yes I just got this expansion hub a few days ago, the PWM module seemed to be working as my lights would come on, and I once had code on there that tried to simulate a cloud and while it wasn't a polished effect, things changed. Ive also had some stock code on where I could turn the lights on and off with the controller and choose between 0%, 50% and 100% brightness. So I assume the pieces are working and I'm mountain time so it is 6:52pm right now.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 7:02 pm
by rimai
Do you have a meter to test the power supply of the expansion hub?
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 7:19 pm
by Aricml
Well that was that problem, I put my multimeter to it and found it was just fine, I plugged it in and it worked, therefore I must assume I didn't have it plugged in all the way because how things are now theres only a few more tickles for me to take care of.
Controller thinks time is 11PM 1/1/00
Moonlights are on! Awesome!
Wavemaker is going good. I edited the times in the internal memory file and it is alternating well. Awesome!
My return pump, on port 8, is not on.
While I was writing this, my actinic channels came on.
So things are getting pretty close, I also do wonder it it's possible to override lights on/off or if that is a timer only function, not a big deal, but it would be nice and woudl also help me make sure everything is working.
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 7:39 pm
by Aricml
If you thought that there was a bug with RAGen, how would I go about making the time on my controller correct so I can see if it will be dimming in and out like it should?
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Tue Feb 14, 2012 8:10 pm
by rimai
RAGen only has a bug when generating internal memory files.
You can set the date-time on the features tab and load the template example code to change the time/date or use the client or smart phone app to update the time
Re: Dim LEDs with PWM expansion and alternate wavemaker
Posted: Wed Feb 15, 2012 12:53 pm
by Aricml
I have things working, aside from that I still have to figure out how to set the time correct in my phone. I just can't seem to install RA Client so I'm getting my Wifi Module setup so I can change it with my Android Phone..
That being said, I used RAGen to give me the Wifi authentication code and tossed it in, however I'm getting Sketch too Big. Can my current coed be reduced without losing any key functionality? Or am I overreaching?
Here's the code followed by the error message.
Code: Select all
// Autogenerated file by RAGen (v1.0.4.92), (09/17/2011 15:54)
// RA_091711_1554.pde
//
// This version designed for v0.8.5 Beta 12 or later
/* The following features are enabled for this PDE File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/
#include <Salinity.h>
#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 <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <ReefAngel.h>
//*********************************************************************************************************************************
//Start of PWM Expansion Code Header
// This is just how we are going to reference the PWM expansion ports within the code.
// You can change the labels if you would like, just as long as they are changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5
// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};
//End of PWM Expansion Code Header
//*********************************************************************************************************************************
boolean ForceCloud=false;
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Water Change Mode";
prog_char menu2_label[] PROGMEM = "Force Cloud";
prog_char menu3_label[] PROGMEM = "Clear ATO Timeout";
prog_char menu4_label[] PROGMEM = "About Me";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ForceCloud=true;
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.ATOClear();
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.DisplayVersion();
}
void setup()
{
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
ReefAngel.FeedingModePorts = B00110000;
ReefAngel.WaterChangePorts = B00110001;
ReefAngel.OverheatShutoffPorts = B00001101;
ReefAngel.LightsOnPorts = B00111101;
WifiAuthentication("Aric:greenbaypackers");
ReefAngel.Relay.On(Port8);
ReefAngel.Relay.On(Port1);
}
void loop()
{
// Specific functions
ReefAngel.StandardLights(Port2);
ReefAngel.StandardLights(Port3);
ReefAngel.StandardLights(Port4);
ReefAngel.Wavemaker1(Port5);
//Set Port6 to alternate with Port 6 in opposite cycle
if (bitRead(ReefAngel.Relay.RelayData,4))
ReefAngel.Relay.Off(Port6);
else
ReefAngel.Relay.On(Port6);
// Monnlight schedule
if (hour()<9 || hour()>=18)
{
// Set Moonlights to follow the moon cycle
ReefAngel.PWM.SetDaylight(MoonPhase());
ReefAngel.PWM.SetActinic(MoonPhase());
}
//*********************************************************************************************************************************
//Start of PWM Expansion Code for Slope
PWMChannel[LEDPWM0]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(9,0,18,00,10,75,60,PWMChannel[LEDPWM1]);
PWMChannel[LEDPWM2]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM2]);
PWMChannel[LEDPWM3]=PWMSlope(7,30,20,00,20,90,75,PWMChannel[LEDPWM3]);
// The lines above are what calculates the slope.
// You can change the schedule by changing the parameter inside the parenthesis of the PWMSlope() function
// The are as follow:
// 1st parameter: hour to start slope
// 2nd parameter: minute to start slope
// 3rd parameter: hour to end slope
// 4th parameter: minute to end slope
// 5th parameter: % of the PWM signal to start slope
// 6th parameter: % of the PWM signal to end slope
// 7th parameter: duration of slope in minutes
// 8th parameter: always the same as the variable before the PWMSlope() call
//PWMChannel[LEDPWM1]=PWMSlope(15,0,21,30,15,45,90,PWMChannel[LEDPWM1]);
// In the example above, we are starting the slope at 3:00pm with 15% and going up to 45% within 90 minutes, which would be 4:30pm.
// Then it would stay at 45% from 4:30 to 90 minutes prior to 9:30pm, which would be 8:00pm.
// Then from 8:00pm, it would start sloping down from 45% all the way back to 15% within 90 minutes, which would be 9:30pm.
CheckCloud();
ReefAngel.PWM.Expansion(LEDPWM0,int(2.55*PWMChannel[LEDPWM0]));
ReefAngel.PWM.Expansion(LEDPWM1,int(2.55*PWMChannel[LEDPWM1]));
ReefAngel.PWM.Expansion(LEDPWM2,int(2.55*PWMChannel[LEDPWM2]));
ReefAngel.PWM.Expansion(LEDPWM3,int(2.55*PWMChannel[LEDPWM3]));
//End of PWM Expansion Code for Slope
//*********************************************************************************************************************************
ReefAngel.ShowInterface();
}
//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{
// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect
// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur everyday
#define Clouds_Every_X_Days 1
// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening
#define Cloud_Chance_per_Day 100
// Minimum number of minutes for cloud duration. Don't use max duration of less than 6
#define Min_Cloud_Duration 7
// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255
#define Max_Cloud_Duration 15
// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 3
// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5
// Only start the cloud effect after this setting
// In this example, start could after 11:30am
#define Start_Cloud_After NumMins(9,0)
// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(18,0)
// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening
#define Lightning_Change_per_Cloud 100
// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for actinics
#define Actinic_Channels B001100
// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for daylights
#define Daylight_Channels B000011
// Note: Make sure to choose correct values that will work within your PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen resul could happen.
// Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can fit in that 510 minutes window.
// It's a tight fit, but it did.
//#define printdebug // Uncomment this for debug print on Serial Monitor window
#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.
// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here
static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;
#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day.
cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the effect
if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope
PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,180);
}
}
if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
for (int b=0;b<6;b++)
{
if (bitRead(Daylight_Channels,b)==1)
{
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) PWMChannel[b]=100;
else PWMChannel[b]=0;
//delay(10);
}
else
{
PWMChannel[b]=20;
}
}
}
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{
cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}
if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,5,120,"C");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,45,120,"L");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11; else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
if ((cloudstart%60)>=10) x=29; else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
}
}
}
byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
Binary sketch size: 32736 bytes (of a 32256 byte maximum)
processing.app.debug.RunnerException: Sketch too big; see
http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.
at processing.app.Sketch.size(Sketch.java:1651)
at processing.app.Sketch.build(Sketch.java:1570)
at processing.app.Sketch.build(Sketch.java:1546)
at processing.app.Editor$DefaultRunHandler.run(Editor.java:1845)
at java.lang.Thread.run(Thread.java:619)
Edit: Sorry I had posted the wrong code before, I fixed it now
I'd like to get this code working so I can use that wifi attach! Thanks again!