Page 1 of 2

Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Thu Oct 09, 2014 9:29 am
by dlplunkett44
I recently purchased the 16 channel PWM expansion, but I am having trouble understanding how to code for it. I would like to have clouds and lightning like the topic says. I will have reds, greens, UV, on their own channels, but I will have several channels for whites and blues, for different areas of the tank (east to west). I would like to have clouds come in and move from side to side with chances for lightning. I would also like to have a few channels for the moonlights so the moon can move from side to side as well, and simulate different moon stages. Finally, I would also like to have the option of manually starting a cloud with and without lightning manually.

I am not sure where to even begin though as I do not even know how to program for the 16 channel expansion at all. I would absolutely want to keep the 12 bit resolution that the expansion is capable of though too.
For people that have the 16 channel expansion, could you post some examples of how you have yours programmed?

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Fri Oct 10, 2014 7:58 am
by AlanM
Colin has cloud code that he has been working on at http://forum.reefangel.com/viewtopic.php?f=12&t=4783

I added some functions to the development branch to integrate the 16 channel PWM in to the libries and made sure that it was compatible with the cloud/lightning stuff that Colin was doing. Have you pulled down the development branch of the reefangel code and tried using that?

You'd go to

https://github.com/reefangel/Libraries/tree/dev

and click "Download Zip" and unzip that into your Libraries directory.

then go to

https://github.com/reefangel/FeaturesAndUpdateFiles

and get download the zip there as well and put the feature.txt file into the "update" folder of the Reef Angel arduino directory and you can start using the 16 channel dimming by adding the line:

ReefAngel.Add16ChPWM();

into your .ino file.

Once you have that, you can address those channels the same as the regular dimming ones. If you want to do some of the east to west stuff and the manual stuff you'll be doing some custom stuff so you'll likely need to understand what Colin's code is doing and how to change it to do what you want.

You can look at my .ino to see how I'm sending dimming levels to the 16 channel PWM using the dev version of the libraries here: http://forum.reefangel.com/viewtopic.php?f=11&t=4806

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Thu Oct 23, 2014 10:10 am
by dlplunkett44
I am working on adapting code for this but I have a question...

What would be the equivalent for this:

analogWrite(daylightPWMPin,random(DaylightPWMValue*2.55,255));

How do I "analogWrite to the pins on the 16 channel expansion?

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Thu Oct 23, 2014 12:04 pm
by rimai
This is how to talk to the chip directly:

Code: Select all

    int newdata=4095;
    byte channel=0;
    Wire.beginTransmission(0x41);
    Wire.write(0x8+(4*channel));
    Wire.write(newdata&0xff);
    Wire.write(newdata>>8);
    Wire.endTransmission();
newdata can be any 12bit value, which means from 0 to 4095.
channel can be any of the 16 channels from 0 to 15

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Fri Oct 24, 2014 6:12 am
by cosmith71
Without having a way to test it, I think something like this should work.

Replace this:

Code: Select all

    analogWrite(daylightPWMPin,random(DaylightPWMValue*2.55,255)); 
With this:

Code: Select all

int newdata=random(DaylightPWMValue*40.95, 4095);
    byte channel=0;
    Wire.beginTransmission(0x41);
    Wire.write(0x8+(4*channel));
    Wire.write(newdata&0xff);
    Wire.write(newdata>>8);
    Wire.endTransmission();
--Colin

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Fri Oct 24, 2014 11:28 am
by dlplunkett44
Ok, does this code seem ok? I still have several things I need to work out: clouds moving from side to side, moon phases and seasons. Other than those things, does this seem like it will work for generating clouds/lightning? THANKS!!

Code: Select all

#include <ReefAngel_Features.h>

#include <Globals.h>

#include <RA_Wifi.h>

#include <Wire.h>

#include <OneWire.h>

#include <Time.h>

#include <DS1307RTC.h>

#include <InternalEEPROM.h>

#include <RA_NokiaLCD.h>

#include <RA_ATO.h>

#include <RA_Joystick.h>

#include <LED.h>

#include <RA_TempSensor.h>

#include <Relay.h>

#include <RA_PWM.h>

#include <Timer.h>

#include <Memory.h>

#include <InternalEEPROM.h>

#include <RA_Colors.h>

#include <RA_CustomColors.h>

#include <Salinity.h>

#include <RF.h>

#include <IO.h>

#include <ORP.h>

#include <AI.h>

#include <PH.h>

#include <WaterLevel.h>

#include <Humidity.h>

#include <DCPump.h>

#include <ReefAngel.h>





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





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







void setup()

{
    



// This must be the first line
    
ReefAngel.Init();  
//Initialize controller
   

 ReefAngel.Use2014Screen();  
// Let's use 2014 Screen 
    

ReefAngel.AddPHExpansion();  
// pH Expansion Module
    

// Ports toggled in Feeding Mode
    
ReefAngel.FeedingModePorts = Port1Bit | Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port6Bit | Port8Bit;
    
ReefAngel.FeedingModePortsE[0] = Port1Bit;
    

// Ports toggled in Water Change Mode
    
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port6Bit | Port8Bit;
    
ReefAngel.WaterChangePortsE[0] = Port1Bit;
    

// Ports toggled when Lights On / Off menu entry selected
    
ReefAngel.LightsOnPorts = 0;
    
ReefAngel.LightsOnPortsE[0] = 0;
    

// Ports turned off when Overheat temperature exceeded
    
ReefAngel.OverheatShutoffPorts = Port2Bit | Port3Bit;
    
ReefAngel.OverheatShutoffPortsE[0] = 0;
    

// Use T1 probe as temperature and overheat functions
    
ReefAngel.TempProbe = T1_PROBE;
    
ReefAngel.OverheatProbe = T1_PROBE;
    

// Set the Overheat temperature setting
    
InternalMemory.OverheatTemp_write( 869 );


    

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

  
  


// Add support for 16 channel PWM board
ReefAngel.Add16ChPWM();









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

    


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




}








void loop()

{
    


ReefAngel.SingleATO( true,Port1,90,0 );
    
ReefAngel.StandardHeater( Port2,820,825 );
    
ReefAngel.StandardHeater( Port3,815,823 );
    
ReefAngel.WavemakerRandom( Port5,25,45 );
    
ReefAngel.WavemakerRandom( Port6,25,45 );
    
ReefAngel.StandardLights( Port7,21,0,7,0 );
    
ReefAngel.CO2Control( Port8,670,675 );
    
ReefAngel.DosingPumpRepeat( Box1_Port1,0,60,10 );
    



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

    


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

    


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\



//0 = White Far East
PWMChannel[0]=PWMParabola(8,0,20,30,0,80,0);
//1 = White Near East
PWMChannel[1]=PWMParabola(8,5,20,35,0,80,0);
//2 = White Near West
PWMChannel[2]=PWMParabola(8,10,20,40,0,80,0);
//3 = White Far West
PWMChannel[3]=PWMParabola(8,15,20,45,0,80,0);
//4 = Blue Far East
PWMChannel[4]=PWMParabola(7,15,21,15,0,80,0);
//5 = Blue Near East
PWMChannel[5]=PWMParabola(7,20,21,20,0,80,0);
//6 = Blue Near West
PWMChannel[6]=PWMParabola(7,25,21,25,0,80,0);
//7 = Blue Far West
PWMChannel[7]=PWMParabola(7,30,21,30,0,80,0);
//8 = OCW Far East
PWMChannel[8]=PWMParabola(8,15,20,15,0,60,0);
//9 = OCW Near East
PWMChannel[9]=PWMParabola(8,20,20,20,0,60,0);
//10 = OCW Near West
PWMChannel[10]=PWMParabola(8,25,20,25,0,60,0);
//11 = OCW Far West
PWMChannel[11]=PWMParabola(8,30,20,30,0,60,0);
//12 = Violets
PWMChannel[12]=PWMParabola(8,15,20,30,0,65,0);
//13 = Moonlight Far East
PWMChannel[13]=PWMParabola(20,15,8,30,0,15,0);
//14 = Moonlight Near East and West
PWMChannel[14]=PWMParabola(20,20,8,35,0,15,0);
//15 = Moonlight Far West
PWMChannel[15]=PWMParabola(20,25,8,40,0,15,0);



    
CheckCloud();

ReefAngel.PWM.SetChannel(0,PWMChannel[0]);
ReefAngel.PWM.SetChannel(1,PWMChannel[1]);
ReefAngel.PWM.SetChannel(2,PWMChannel[2]);
ReefAngel.PWM.SetChannel(3,PWMChannel[3]);
ReefAngel.PWM.SetChannel(3,PWMChannel[4]);
ReefAngel.PWM.SetChannel(3,PWMChannel[5]);
ReefAngel.PWM.SetChannel(3,PWMChannel[6]);
ReefAngel.PWM.SetChannel(3,PWMChannel[7]);
ReefAngel.PWM.SetChannel(3,PWMChannel[8]);
ReefAngel.PWM.SetChannel(3,PWMChannel[9]);
ReefAngel.PWM.SetChannel(3,PWMChannel[10]);
ReefAngel.PWM.SetChannel(3,PWMChannel[11]);
ReefAngel.PWM.SetChannel(3,PWMChannel[12]);
ReefAngel.PWM.SetChannel(3,PWMChannel[13]);
ReefAngel.PWM.SetChannel(3,PWMChannel[14]);
ReefAngel.PWM.SetChannel(3,PWMChannel[15]);





\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\



// This should always be the last line
    
ReefAngel.AddWifi();
    
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 min 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 1

 // Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 7

 // Only start the cloud effect after this setting
 // In this example, start could after 8:30am
#define Start_Cloud_After NumMins(08,30)

 // Always end the cloud effect before this setting
 // In this example, end could before 7:00pm
#define End_Cloud_Before NumMins(19,00)

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

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

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

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


    // Add Random Lightning modes
#define Calm 0    // No lightning
#define Slow 1    // 5 seconds of slow lightning in the middle of a cloud for ELN style (slow response) drivers
#define Fast 2    // 5 seconds of fast lightning in the middle of a cloud for LDD style (fast response) drivers
#define Mega 3    // Lightning throughout the cloud, higher chance as it gets darker
#define Mega2 4   // Like Mega, but with more lightning
  // Set which modes you want to use
  // Example:  { Slow, Fast, Mega, Mega2 } to randomize all four modes.  
  // { Mega2 } for just Mega2.  { Mega, Mega, Fast} for Mega and Fast, with twice the chance of Mega.
  byte LightningModes[] = { Mega, Mega, Mega2, Calm, Calm, Fast };


 // 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;
 static byte lightningMode=0;
 static boolean chooseLightning=true;

 static time_t DelayCounter=millis();    // Variable for lightning timing.  
 static int DelayTime=random(1000);      // Variable for lightning timimg.

 // 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
 {
 randomSeed(millis());    // Seed the random number generator
 //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 (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<16;a++)
 		{
 			if (bitRead(Actinic_Channels,a)==0)
 			{
 				// this will slope down the DAYLIGHT channels from the current PWM to 0 within 3 minutes.
 				// 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);
 			}
 		}




int newdata=4095;
byte channel=0;
      
if (chooseLightning) 
      { 
        lightningMode=LightningModes[random(100)%sizeof(LightningModes)]; 
        chooseLightning=false; 
      } 

      switch (lightningMode) 
      {
      case Calm:
        break;
      case Mega:
        // Lightning chance from beginning of cloud through the end.  Chance increases with darkness of cloud.
        if (lightningchance && random(ReversePWMSlope(cloudstart,cloudstart+cloudduration,100,0,180))<1 && (millis()-DelayCounter)>DelayTime)
        {
          int a=random(1,5);    // Pick a number of consecutive flashes from 1 to 4.  
          for (int i=0; i<a; i++)
          {
            
		for (int g=0;g<16;g++)
 		{
		
		if (bitRead(Daylight_Channels,g)==1)
 		{
		newdata=random(DaylightPWMValue*40.95, 4095);
    		channel=g;
    		Wire.beginTransmission(0x41);
    		Wire.write(0x8+(4*channel));
    		Wire.write(newdata&0xff);
    		Wire.write(newdata>>8);
    		Wire.endTransmission();
		}
		}

            int randy=random(20,80);    // Random number for a delay
            if (randy>71) randy=((randy-70)/2)*100;    // Small chance of a longer delay
            delay(randy);                // Wait from 20 to 69 ms, or 100-400 ms
        
 		for (int h=0;h<16;h++)
 		{
		
		if (bitRead(Daylight_Channels,h)==1)
 		{
		newdata=DaylightPWMValue*40.95;
    		channel=h;
    		Wire.beginTransmission(0x41);
    		Wire.write(0x8+(4*channel));
    		Wire.write(newdata&0xff);
    		Wire.write(newdata>>8);
    		Wire.endTransmission();
		}
		}

            delay(random(30,50));                // Wait from 30 to 49 ms 
            wdt_reset();
          }
          DelayCounter=millis();    // If we just had a round of flashes, then lets put in a longer delay
          DelayTime=random(1000);   // of up to a second for dramatic effect before we do another round. 
        }
        break;
      case Mega2:
        // Higher lightning chance from beginning of cloud through the end.  Chance increases with darkness of cloud.
        if (lightningchance && random(ReversePWMSlope(cloudstart,cloudstart+cloudduration,100,0,180))<2 && (millis()-DelayCounter)>DelayTime)
        {
          int a=random(1,5);    // Pick a number of consecutive flashes from 1 to 4.  
          for (int i=0; i<a; i++)
          {


		for (int k=0;k<16;k++)
 		{
		
		if (bitRead(Daylight_Channels,k)==1)
 		{
		newdata=random(DaylightPWMValue*40.95, 4095);
    		channel=k;
    		Wire.beginTransmission(0x41);
    		Wire.write(0x8+(4*channel));
    		Wire.write(newdata&0xff);
    		Wire.write(newdata>>8);
    		Wire.endTransmission();
		}

            int randy=random(20,80);    // Random number for a delay
            if (randy>71) randy=((randy-70)/2)*100;    // Small chance of a longer delay
            delay(randy);                // Wait from 20 to 69 ms, or 100-400 ms

		for (int l=0;l<16;l++)
 		{
		
		if (bitRead(Daylight_Channels,l)==1)
 		{
		newdata=DaylightPWMValue*40.95;
    		channel=l;
    		Wire.beginTransmission(0x41);
    		Wire.write(0x8+(4*channel));
    		Wire.write(newdata&0xff);
    		Wire.write(newdata>>8);
    		Wire.endTransmission();
		}
		}

            delay(random(30,50));                // Wait from 30 to 49 ms 
            wdt_reset();
          }
          DelayCounter=millis();    // If we just had a round of flashes, then lets put in a longer delay
          DelayTime=random(1000);   // of up to a second for dramatic effect before we do another round. 
        }
        break;
      case Fast:
        // 5 seconds of lightning in the middle of the cloud
        if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5 && (millis()-DelayCounter)>DelayTime)
        {
          int a=random(1,5);    // Pick a number of consecutive flashes from 1 to 4.  
          for (int i=0; i<a; i++)
          {

            for (int e=0;e<16;e++)
 		{
		
		if (bitRead(Daylight_Channels,e)==1)
 		{
		newdata=random(DaylightPWMValue*40.95, 4095);
    		channel=e;
    		Wire.beginTransmission(0x41);
    		Wire.write(0x8+(4*channel));
    		Wire.write(newdata&0xff);
    		Wire.write(newdata>>8);
    		Wire.endTransmission();
		}
		}
	    int randy=random(20,80);    // Random number for a delay
            if (randy>71) randy=((randy-70)/2)*100;    // Small chance of a longer delay
            delay(randy);                // Wait from 20 to 69 ms, or 100-400 ms
            
	    for (int f=0;f<16;f++)
 		{
		
		if (bitRead(Daylight_Channels,f)==1)
 		{
		newdata=DaylightPWMValue*40.95;
    		channel=f;
    		Wire.beginTransmission(0x41);
    		Wire.write(0x8+(4*channel));
    		Wire.write(newdata&0xff);
    		Wire.write(newdata>>8);
    		Wire.endTransmission();
		}
		}

            delay(random(30,50));                // Wait from 30 to 49 ms 
            wdt_reset();
          }
          DelayCounter=millis();    // If we just had a round of flashes, then lets put in a longer delay
          DelayTime=random(1000);   // of up to a second for dramatic effect before we do another round. 
        }
        break;
      case Slow:
        // Slow lightning for 5 seconds in the middle of the cloud.  Suitable for slower ELN style drivers
        if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5) 
        {
          if (random(100)<20) lightningstatus=1; 
          else lightningstatus=0;
          if (lightningstatus)
          {
            newdata=4095;
		for (int c=0;c<16;c++)
 		{
		if (bitRead(Daylight_Channels,c)==1)
 			{
			channel=c;
    			Wire.beginTransmission(0x41);
    			Wire.write(0x8+(4*channel));
    			Wire.write(newdata&0xff);
    			Wire.write(newdata>>8);
    			Wire.endTransmission();	
			}	
		}
		
          }
          else 
          {
           
		newdata=0;
		for (int d=0;d<16;d++)
 		{
		if (bitRead(Daylight_Channels,d)==1)
 			{
			channel=d;
    			Wire.beginTransmission(0x41);
    			Wire.write(0x8+(4*channel));
    			Wire.write(newdata&0xff);
    			Wire.write(newdata>>8);
    			Wire.endTransmission();	
			}	
		}

          }
          delay(1);
        }
        break;
      default:
        break;
      }
    } 
    else 
    {
      chooseLightning=true; // Reset the flag to choose a new lightning type
    }



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

 


  // Write the times of the next cloud, next lightning, and cloud duration to the screen.
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: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Sat Oct 25, 2014 9:15 am
by rimai
I think it looks good.
Did you try it out? :)

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Sun Oct 26, 2014 5:32 am
by dlplunkett44
So it won't compile. These are the errors that it gives me:

It stops on 'class ReefAngelClass' has no member named 'Add16ChPWM'

Then these are the errors below:




The following features were automatically added:
Watchdog Timer
Version Menu

The following features were detected:
16 Channel Dimming Expansion Module
Dimming Signal
Wifi Attachment
Relay Expansion Module
2014 Main Screen
Extra Font - Medium Size (8x8 pixels)
pH Expansion Module
Number of Relay Expansion Modules: 1
Simple Menu
In_Progress.cpp:422:20: error: invalid digit "8" in octal constant
In_Progress.cpp:422:38: error: invalid digit "8" in octal constant
In_Progress.cpp:422:75: error: invalid digit "8" in octal constant
In_Progress.cpp:676:29: error: invalid digit "8" in octal constant
In_Progress.cpp:676:67: error: invalid digit "8" in octal constant
In_Progress.cpp:676:116: error: invalid digit "8" in octal constant
In_Progress.cpp:676:154: error: invalid digit "8" in octal constant
In_Progress.cpp:676:222: error: invalid digit "8" in octal constant
In_Progress.cpp: In function 'void setup()':
In_Progress:150: error: 'class ReefAngelClass' has no member named 'Add16ChPWM'
In_Progress.cpp: In function 'void loop()':
In_Progress:221: error: 'PWMChannel' was not declared in this scope
In_Progress:258: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:259: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:260: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:261: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:262: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:263: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:264: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:265: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:266: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:267: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:268: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:269: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:270: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:271: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:272: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:273: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress.cpp: In function 'void CheckCloud()':
In_Progress:437: error: 'B0000010000000000' was not declared in this scope
In_Progress:443: error: 'PWMChannel' was not declared in this scope
In_Progress:474: error: 'B0000100000000000' was not declared in this scope
In_Progress:476: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:493: error: 'B0000100000000000' was not declared in this scope
In_Progress:495: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:524: error: 'B0000100000000000' was not declared in this scope
In_Progress:526: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:542: error: 'B0000100000000000' was not declared in this scope
In_Progress:544: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:561: error: jump to case label
In_Progress:516: error: crosses initialization of 'int a'
In_Progress:572: error: 'B0000100000000000' was not declared in this scope
In_Progress:574: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:590: error: 'B0000100000000000' was not declared in this scope
In_Progress:592: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:609: error: jump to case label
In_Progress:516: error: crosses initialization of 'int a'
In_Progress:620: error: 'B0000100000000000' was not declared in this scope
In_Progress:638: error: 'B0000100000000000' was not declared in this scope
In_Progress:653: error: jump to case label
In_Progress:516: error: crosses initialization of 'int a'
In_Progress:657: error: expected `}' before 'else'
Reef Angel Libraries Found: Development
Reef Angel Libraries Version: 1.1.0

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Sun Oct 26, 2014 12:08 pm
by lnevo
Did you download the latest dev libraries?

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Sun Oct 26, 2014 5:16 pm
by dlplunkett44
Yes, I put the dev libraries in the libraries folder, but I had to rename the folder from "Libraries-dev" to Librariesdev. Arduino didn't like the "-" I guess. I also put the feature and source files in the update folder, overwriting the old version.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Sun Oct 26, 2014 5:59 pm
by rimai
Ok, so I know that this is wrong 'B0000010000000000'
You need to convert that to decimal. Arduino doesn't have that declared internally.
So, binary 0000010000000000 = decimal 1024
Also, you should actually rename your original libraries folder to something like libraries-original and you need to rename the libraries-dev to libraries.
The contents of libraries is what Arduino will be looking at.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 2:32 am
by dlplunkett44
Ok, so I renamed my original library to librariesoriginal and the dev libraries to "libraries". I'm still getting the same errors. Also, the binary numbers were copied from someone else's lightning code that I've been using for quite a while. It was for the 6 channel PWM expansion, so I added 10 digits. Could this be why? How could I get the binary number to work? The code does a bit read to determine if a particular channel is to be flashed or not.
Thanks!

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 2:40 am
by dlplunkett44
I got rid of the binary problem by adding word in front of the number so

#define Actinic_Channels B0000010000000000

became

#define word Actinic_Channels B0000010000000000

This is now my error log:



The following features were automatically added:
Watchdog Timer
Version Menu

The following features were detected:
16 Channel Dimming Expansion Module
Dimming Signal
Wifi Attachment
Relay Expansion Module
2014 Main Screen
Extra Font - Medium Size (8x8 pixels)
pH Expansion Module
Number of Relay Expansion Modules: 1
Simple Menu
In_Progress.cpp: In function 'void setup()':
In_Progress:147: error: 'class ReefAngelClass' has no member named 'Add16ChPWM'
In_Progress.cpp: In function 'void loop()':
In_Progress:196: error: 'PWMChannel' was not declared in this scope
In_Progress:233: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:234: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:235: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:236: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:237: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:238: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:239: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:240: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:241: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:242: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:243: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:244: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:245: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:246: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:247: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:248: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress.cpp: In function 'void CheckCloud()':
In_Progress:412: error: 'Actinic_Channels' was not declared in this scope
In_Progress:418: error: 'PWMChannel' was not declared in this scope
In_Progress:449: error: 'Daylight_Channels' was not declared in this scope
In_Progress:451: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:453: error: 'Wire' was not declared in this scope
In_Progress:468: error: 'Daylight_Channels' was not declared in this scope
In_Progress:470: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:472: error: 'Wire' was not declared in this scope
In_Progress:499: error: 'Daylight_Channels' was not declared in this scope
In_Progress:501: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:503: error: 'Wire' was not declared in this scope
In_Progress:517: error: 'Daylight_Channels' was not declared in this scope
In_Progress:519: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:521: error: 'Wire' was not declared in this scope
In_Progress:536: error: jump to case label
In_Progress:491: error: crosses initialization of 'int a'
In_Progress:547: error: 'Daylight_Channels' was not declared in this scope
In_Progress:549: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:551: error: 'Wire' was not declared in this scope
In_Progress:565: error: 'Daylight_Channels' was not declared in this scope
In_Progress:567: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:569: error: 'Wire' was not declared in this scope
In_Progress:584: error: jump to case label
In_Progress:491: error: crosses initialization of 'int a'
In_Progress:595: error: 'Daylight_Channels' was not declared in this scope
In_Progress:598: error: 'Wire' was not declared in this scope
In_Progress:613: error: 'Daylight_Channels' was not declared in this scope
In_Progress:616: error: 'Wire' was not declared in this scope
In_Progress:628: error: jump to case label
In_Progress:491: error: crosses initialization of 'int a'
In_Progress:632: error: expected `}' before 'else'


Thanks again.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 8:38 am
by rimai
There are several things I found wrong:
You must declare variables you are using above loop.

Code: Select all

int PWMChannel[16];
int DaylightPWMValue;
You can't use this:

Code: Select all

#define Start_Cloud_After NumMins(08,30)
#define End_Cloud_Before NumMins(19,00)
You must enter the number of minutes yourself instead of a formula. 510 and 1140 respectively.
We are using a define statement instead of a variable.
If you declare that as a variable above setup(), you could use a formula, but that just complicates everything. Just use the numbers.
The 16 channel uses a different function.
Change SetChannel to Set16Channel.

There is something wrong with the Mega2 section of your code. I removed it and was able to compile. I think there is an extra or missing bracket somewhere.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 8:41 am
by rimai
Ahh.. The binary can't be used like that.
You must represent it as a decimal or hex number.
Just use a calculator to convert. I already showed the conversion to decimal of one of them in the previous post.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 4:13 pm
by dlplunkett44
I'm still getting all the same errors. I think its not taking the dev libraries correctly.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 5:21 pm
by dlplunkett44
OK, so I uninstalled reefangel, reinstalled, and redid the dev libraries and these are the errors I'm getting now:



The following features were automatically added:
Watchdog Timer
Version Menu

The following features were detected:
16 Channel Dimming Expansion Module
Dimming Signal
Wifi Attachment
Relay Expansion Module
2014 Main Screen
Extra Font - Medium Size (8x8 pixels)
pH Expansion Module
Number of Relay Expansion Modules: 1
Simple Menu
In_Progress.cpp:400:20: error: invalid digit "8" in octal constant
In_Progress.cpp:400:38: error: invalid digit "8" in octal constant
In_Progress.cpp:400:75: error: invalid digit "8" in octal constant
In_Progress.cpp:654:29: error: invalid digit "8" in octal constant
In_Progress.cpp:654:67: error: invalid digit "8" in octal constant
In_Progress.cpp:654:116: error: invalid digit "8" in octal constant
In_Progress.cpp:654:154: error: invalid digit "8" in octal constant
In_Progress.cpp:654:222: error: invalid digit "8" in octal constant
In_Progress.cpp: In function 'void loop()':
In_Progress:199: error: 'PWMChannel' was not declared in this scope
In_Progress:236: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:237: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:238: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:239: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:240: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:241: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:242: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:243: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:244: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:245: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:246: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:247: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:248: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:249: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:250: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress:251: error: 'class RA_PWMClass' has no member named 'SetChannel'
In_Progress.cpp: In function 'void CheckCloud()':
In_Progress:322: error: expected initializer before numeric constant
In_Progress:415: error: 'Actinic_Channels' was not declared in this scope
In_Progress:421: error: 'PWMChannel' was not declared in this scope
In_Progress:433: error: 'LightningModes' was not declared in this scope
In_Progress:452: error: 'Daylight_Channels' was not declared in this scope
In_Progress:454: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:456: error: 'Wire' was not declared in this scope
In_Progress:471: error: 'Daylight_Channels' was not declared in this scope
In_Progress:473: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:475: error: 'Wire' was not declared in this scope
In_Progress:502: error: 'Daylight_Channels' was not declared in this scope
In_Progress:504: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:506: error: 'Wire' was not declared in this scope
In_Progress:520: error: 'Daylight_Channels' was not declared in this scope
In_Progress:522: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:524: error: 'Wire' was not declared in this scope
In_Progress:539: error: jump to case label
In_Progress:494: error: crosses initialization of 'int a'
In_Progress:550: error: 'Daylight_Channels' was not declared in this scope
In_Progress:552: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:554: error: 'Wire' was not declared in this scope
In_Progress:568: error: 'Daylight_Channels' was not declared in this scope
In_Progress:570: error: 'DaylightPWMValue' was not declared in this scope
In_Progress:572: error: 'Wire' was not declared in this scope
In_Progress:587: error: jump to case label
In_Progress:494: error: crosses initialization of 'int a'
In_Progress:598: error: 'Daylight_Channels' was not declared in this scope
In_Progress:601: error: 'Wire' was not declared in this scope
In_Progress:616: error: 'Daylight_Channels' was not declared in this scope
In_Progress:619: error: 'Wire' was not declared in this scope
In_Progress:631: error: jump to case label
In_Progress:494: error: crosses initialization of 'int a'
In_Progress:635: error: expected `}' before 'else'





Were you not getting these errors when you compiled?

Thanks again.


Code: Select all


#include <ReefAngel_Features.h>

#include <Globals.h>

#include <RA_Wifi.h>

#include <Wire.h>

#include <OneWire.h>

#include <Time.h>

#include <DS1307RTC.h>

#include <InternalEEPROM.h>

#include <RA_NokiaLCD.h>

#include <RA_ATO.h>

#include <RA_Joystick.h>

#include <LED.h>

#include <RA_TempSensor.h>

#include <Relay.h>

#include <RA_PWM.h>

#include <Timer.h>

#include <Memory.h>

#include <InternalEEPROM.h>

#include <RA_Colors.h>

#include <RA_CustomColors.h>

#include <Salinity.h>

#include <RF.h>

#include <IO.h>

#include <ORP.h>

#include <AI.h>

#include <PH.h>

#include <WaterLevel.h>

#include <Humidity.h>

#include <DCPump.h>

#include <ReefAngel.h>





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





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







void setup()

{
    



// This must be the first line
    
ReefAngel.Init();  
//Initialize controller
   

 ReefAngel.Use2014Screen();  
// Let's use 2014 Screen 
    

ReefAngel.AddPHExpansion();  
// pH Expansion Module
    

// Ports toggled in Feeding Mode
    
ReefAngel.FeedingModePorts = Port1Bit | Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port6Bit | Port8Bit;
    
ReefAngel.FeedingModePortsE[0] = Port1Bit;
    

// Ports toggled in Water Change Mode
    
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port6Bit | Port8Bit;
    
ReefAngel.WaterChangePortsE[0] = Port1Bit;
    

// Ports toggled when Lights On / Off menu entry selected
    
ReefAngel.LightsOnPorts = 0;
    
ReefAngel.LightsOnPortsE[0] = 0;
    

// Ports turned off when Overheat temperature exceeded
    
ReefAngel.OverheatShutoffPorts = Port2Bit | Port3Bit;
    
ReefAngel.OverheatShutoffPortsE[0] = 0;
    

// Use T1 probe as temperature and overheat functions
    
ReefAngel.TempProbe = T1_PROBE;
    
ReefAngel.OverheatProbe = T1_PROBE;
    

// Set the Overheat temperature setting
    
InternalMemory.OverheatTemp_write( 869 );


    

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


// Add support for 16 channel PWM board
ReefAngel.Add16ChPWM();


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

int PWMChannel[16];
int DaylightPWMValue;
////// Place additional initialization code above here

}

void loop()

{

ReefAngel.SingleATO( true,Port1,90,0 );
    
ReefAngel.StandardHeater( Port2,820,825 );
    
ReefAngel.StandardHeater( Port3,815,823 );
    
ReefAngel.WavemakerRandom( Port5,25,45 );
    
ReefAngel.WavemakerRandom( Port6,25,45 );
    
ReefAngel.StandardLights( Port7,21,0,7,0 );
    
ReefAngel.CO2Control( Port8,670,675 );
    
ReefAngel.DosingPumpRepeat( Box1_Port1,0,60,10 );
    



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

    


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

    






//0 = White Far East
PWMChannel[0]=PWMParabola(8,0,20,30,0,80,0);
//1 = White Near East
PWMChannel[1]=PWMParabola(8,5,20,35,0,80,0);
//2 = White Near West
PWMChannel[2]=PWMParabola(8,10,20,40,0,80,0);
//3 = White Far West
PWMChannel[3]=PWMParabola(8,15,20,45,0,80,0);
//4 = Blue Far East
PWMChannel[4]=PWMParabola(7,15,21,15,0,80,0);
//5 = Blue Near East
PWMChannel[5]=PWMParabola(7,20,21,20,0,80,0);
//6 = Blue Near West
PWMChannel[6]=PWMParabola(7,25,21,25,0,80,0);
//7 = Blue Far West
PWMChannel[7]=PWMParabola(7,30,21,30,0,80,0);
//8 = OCW Far East
PWMChannel[8]=PWMParabola(8,15,20,15,0,60,0);
//9 = OCW Near East
PWMChannel[9]=PWMParabola(8,20,20,20,0,60,0);
//10 = OCW Near West
PWMChannel[10]=PWMParabola(8,25,20,25,0,60,0);
//11 = OCW Far West
PWMChannel[11]=PWMParabola(8,30,20,30,0,60,0);
//12 = Violets
PWMChannel[12]=PWMParabola(8,15,20,30,0,65,0);
//13 = Moonlight Far East
PWMChannel[13]=PWMParabola(20,15,8,30,0,15,0);
//14 = Moonlight Near East and West
PWMChannel[14]=PWMParabola(20,20,8,35,0,15,0);
//15 = Moonlight Far West
PWMChannel[15]=PWMParabola(20,25,8,40,0,15,0);



    
CheckCloud();

ReefAngel.PWM.SetChannel(0,PWMChannel[0]);
ReefAngel.PWM.SetChannel(1,PWMChannel[1]);
ReefAngel.PWM.SetChannel(2,PWMChannel[2]);
ReefAngel.PWM.SetChannel(3,PWMChannel[3]);
ReefAngel.PWM.SetChannel(3,PWMChannel[4]);
ReefAngel.PWM.SetChannel(3,PWMChannel[5]);
ReefAngel.PWM.SetChannel(3,PWMChannel[6]);
ReefAngel.PWM.SetChannel(3,PWMChannel[7]);
ReefAngel.PWM.SetChannel(3,PWMChannel[8]);
ReefAngel.PWM.SetChannel(3,PWMChannel[9]);
ReefAngel.PWM.SetChannel(3,PWMChannel[10]);
ReefAngel.PWM.SetChannel(3,PWMChannel[11]);
ReefAngel.PWM.SetChannel(3,PWMChannel[12]);
ReefAngel.PWM.SetChannel(3,PWMChannel[13]);
ReefAngel.PWM.SetChannel(3,PWMChannel[14]);
ReefAngel.PWM.SetChannel(3,PWMChannel[15]);









// This should always be the last line
    
ReefAngel.AddWifi();
    
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 min 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 1

 // Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 7

 // Only start the cloud effect after this setting
 // In this example, start could after 8:30am
#define Start_Cloud_After NumMins(08,30)

 // Always end the cloud effect before this setting
 // In this example, end could before 7:00pm
#define End_Cloud_Before NumMins(19,00)

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

 // 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
int Actinic_Channels 0b0000010000000000

 // 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
int Daylight_Channels 0b0000100000000000

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


    // Add Random Lightning modes
#define Calm 0    // No lightning
#define Slow 1    // 5 seconds of slow lightning in the middle of a cloud for ELN style (slow response) drivers
#define Fast 2    // 5 seconds of fast lightning in the middle of a cloud for LDD style (fast response) drivers
#define Mega 3    // Lightning throughout the cloud, higher chance as it gets darker
#define Mega2 4   // Like Mega, but with more lightning
  // Set which modes you want to use
  // Example:  { Slow, Fast, Mega, Mega2 } to randomize all four modes.  
  // { Mega2 } for just Mega2.  { Mega, Mega, Fast} for Mega and Fast, with twice the chance of Mega.
  byte LightningModes[] = { Mega, Mega, Mega2, Calm, Calm, Fast };


 // 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;
 static byte lightningMode=0;
 static boolean chooseLightning=true;

 static time_t DelayCounter=millis();    // Variable for lightning timing.  
 static int DelayTime=random(1000);      // Variable for lightning timimg.

 // 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
 {
 randomSeed(millis());    // Seed the random number generator
 //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 (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<16;a++)
       {
          if (bitRead(Actinic_Channels,a)==0)
          {
             // this will slope down the DAYLIGHT channels from the current PWM to 0 within 3 minutes.
             // 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);
          }
       }




int newdata=4095;
byte channel=0;
      
if (chooseLightning) 
      { 
        lightningMode=LightningModes[random(100)%sizeof(LightningModes)]; 
        chooseLightning=false; 
      } 

      switch (lightningMode) 
      {
      case Calm:
        break;
      case Mega:
        // Lightning chance from beginning of cloud through the end.  Chance increases with darkness of cloud.
        if (lightningchance && random(ReversePWMSlope(cloudstart,cloudstart+cloudduration,100,0,180))<1 && (millis()-DelayCounter)>DelayTime)
        {
          int a=random(1,5);    // Pick a number of consecutive flashes from 1 to 4.  
          for (int i=0; i<a; i++)
          {
            
      for (int g=0;g<16;g++)
       {
      
      if (bitRead(Daylight_Channels,g)==1)
       {
      newdata=random(DaylightPWMValue*40.95, 4095);
          channel=g;
          Wire.beginTransmission(0x41);
          Wire.write(0x8+(4*channel));
          Wire.write(newdata&0xff);
          Wire.write(newdata>>8);
          Wire.endTransmission();
      }
      }

            int randy=random(20,80);    // Random number for a delay
            if (randy>71) randy=((randy-70)/2)*100;    // Small chance of a longer delay
            delay(randy);                // Wait from 20 to 69 ms, or 100-400 ms
        
       for (int h=0;h<16;h++)
       {
      
      if (bitRead(Daylight_Channels,h)==1)
       {
      newdata=DaylightPWMValue*40.95;
          channel=h;
          Wire.beginTransmission(0x41);
          Wire.write(0x8+(4*channel));
          Wire.write(newdata&0xff);
          Wire.write(newdata>>8);
          Wire.endTransmission();
      }
      }

            delay(random(30,50));                // Wait from 30 to 49 ms 
            wdt_reset();
          }
          DelayCounter=millis();    // If we just had a round of flashes, then lets put in a longer delay
          DelayTime=random(1000);   // of up to a second for dramatic effect before we do another round. 
        }
        break;
      case Mega2:
        // Higher lightning chance from beginning of cloud through the end.  Chance increases with darkness of cloud.
        if (lightningchance && random(ReversePWMSlope(cloudstart,cloudstart+cloudduration,100,0,180))<2 && (millis()-DelayCounter)>DelayTime)
        {
          int a=random(1,5);    // Pick a number of consecutive flashes from 1 to 4.  
          for (int i=0; i<a; i++)
          {


      for (int k=0;k<16;k++)
       {
      
      if (bitRead(Daylight_Channels,k)==1)
       {
      newdata=random(DaylightPWMValue*40.95, 4095);
          channel=k;
          Wire.beginTransmission(0x41);
          Wire.write(0x8+(4*channel));
          Wire.write(newdata&0xff);
          Wire.write(newdata>>8);
          Wire.endTransmission();
      }

            int randy=random(20,80);    // Random number for a delay
            if (randy>71) randy=((randy-70)/2)*100;    // Small chance of a longer delay
            delay(randy);                // Wait from 20 to 69 ms, or 100-400 ms

      for (int l=0;l<16;l++)
       {
      
      if (bitRead(Daylight_Channels,l)==1)
       {
      newdata=DaylightPWMValue*40.95;
          channel=l;
          Wire.beginTransmission(0x41);
          Wire.write(0x8+(4*channel));
          Wire.write(newdata&0xff);
          Wire.write(newdata>>8);
          Wire.endTransmission();
      }
      }

            delay(random(30,50));                // Wait from 30 to 49 ms 
            wdt_reset();
          }
          DelayCounter=millis();    // If we just had a round of flashes, then lets put in a longer delay
          DelayTime=random(1000);   // of up to a second for dramatic effect before we do another round. 
        }
        break;
      case Fast:
        // 5 seconds of lightning in the middle of the cloud
        if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5 && (millis()-DelayCounter)>DelayTime)
        {
          int a=random(1,5);    // Pick a number of consecutive flashes from 1 to 4.  
          for (int i=0; i<a; i++)
          {

            for (int e=0;e<16;e++)
       {
      
      if (bitRead(Daylight_Channels,e)==1)
       {
      newdata=random(DaylightPWMValue*40.95, 4095);
          channel=e;
          Wire.beginTransmission(0x41);
          Wire.write(0x8+(4*channel));
          Wire.write(newdata&0xff);
          Wire.write(newdata>>8);
          Wire.endTransmission();
      }
      }
       int randy=random(20,80);    // Random number for a delay
            if (randy>71) randy=((randy-70)/2)*100;    // Small chance of a longer delay
            delay(randy);                // Wait from 20 to 69 ms, or 100-400 ms
            
       for (int f=0;f<16;f++)
       {
      
      if (bitRead(Daylight_Channels,f)==1)
       {
      newdata=DaylightPWMValue*40.95;
          channel=f;
          Wire.beginTransmission(0x41);
          Wire.write(0x8+(4*channel));
          Wire.write(newdata&0xff);
          Wire.write(newdata>>8);
          Wire.endTransmission();
      }
      }

            delay(random(30,50));                // Wait from 30 to 49 ms 
            wdt_reset();
          }
          DelayCounter=millis();    // If we just had a round of flashes, then lets put in a longer delay
          DelayTime=random(1000);   // of up to a second for dramatic effect before we do another round. 
        }
        break;
      case Slow:
        // Slow lightning for 5 seconds in the middle of the cloud.  Suitable for slower ELN style drivers
        if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5) 
        {
          if (random(100)<20) lightningstatus=1; 
          else lightningstatus=0;
          if (lightningstatus)
          {
            newdata=4095;
      for (int c=0;c<16;c++)
       {
      if (bitRead(Daylight_Channels,c)==1)
          {
         channel=c;
             Wire.beginTransmission(0x41);
             Wire.write(0x8+(4*channel));
             Wire.write(newdata&0xff);
             Wire.write(newdata>>8);
             Wire.endTransmission();   
         }   
      }
      
          }
          else 
          {
           
      newdata=0;
      for (int d=0;d<16;d++)
       {
      if (bitRead(Daylight_Channels,d)==1)
          {
         channel=d;
             Wire.beginTransmission(0x41);
             Wire.write(0x8+(4*channel));
             Wire.write(newdata&0xff);
             Wire.write(newdata>>8);
             Wire.endTransmission();   
         }   
      }

          }
          delay(1);
        }
        break;
      default:
        break;
      }
    } 
    else 
    {
      chooseLightning=true; // Reset the flag to choose a new lightning type
    }



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

 


  // Write the times of the next cloud, next lightning, and cloud duration to the screen.
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: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 5:33 pm
by lnevo
Which libraries folder are you replacing? What is the full path?

There's one thats for the arduino app/executables and another for the ra libraries.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 5:46 pm
by rimai
I was, but I mentioned already what I did to fix the problem a couple posts above.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 5:59 pm
by dlplunkett44
I replaced the libraries folder in my documents and in program files/reefangel.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 6:04 pm
by rimai
Not that.
You need to declare the undeclared variables, you need to change the 16 bit binary number to a decimal and several other things I already mentioned throughout the post.
Please read back the previous posts and make those changes.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 6:17 pm
by dlplunkett44
I did the undeclared variables (unless I put them in the wrong place) as for the decimal thing I'm not understanding. Is that because it is 16 bits? The original code was written that way. You can see my updated code a couple posts back.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 6:20 pm
by rimai
Arduino libraries only have declarations for 8 bit binary numbers.
So, if you are trying to use 16bit, you must declare it as decimal or hexadecimal instead of binary.
Just use a calculator or online conversion like this: http://acc6.its.brooklyn.cuny.edu/~gurw ... 2tool.html

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 6:31 pm
by dlplunkett44
Ok, I understand why now.

I am still getting all the same errors though.

I changed the

#define Actinic_Channels B0000111100000000
and
#define Daylight_Channels B1111000000000000


to

#define Actinic_Channels 384
and
#define Daylight_Channels 61440

I also have

int PWMChannel[16];
int DaylightPWMValue;

in void setup


Could you explain the NumMins thing? That also was copied from the original code. Sorry, it just helps me to understand why things are being done and what they're doing.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Mon Oct 27, 2014 6:56 pm
by rimai
The variable declarations can't be in setup()
It has to be above it or it will only be usable inside setup()
Since you are using them globally, you must declare them globally, which is above setup()

You can't use a function when you are declaring something as a #declare.
#declare is nothing more than an alias.
The compiler goes and changes every reference you have of the #declare to the number you declared. So, you can't use a function.
The exception is if you #declare it as a function too.
So, you either have to use this:

Code: Select all

#declare Start_Cloud_After 510
Or like this:

Code: Select all

#define Start_Cloud_After(h,m) NumMins(h,m)
And when you call it, you must call it like this:

Code: Select all

Start_Cloud_After(8,30)
Which just complicates things to read. Just use the first option. Much easier to read. Why complicate when it is so simple, right?

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Tue Oct 28, 2014 2:40 am
by dlplunkett44
OK, thanks for all your help! I got it to finally compile. Now its time to work on the other features.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Thu Oct 30, 2014 2:53 am
by dlplunkett44
So now I'm trying to make the clouds start in the east and move to the west. I think I have it set up right. It compiles ok, but does this look like it will do what I'm trying to get it to do?

If this looks good, then I'm going to have it randomly choose to start in the east or west.

This is just the section I changed. I also of course declared my variables above like this:

static time_t DelayCount=millis();
static int DelayTiming1=2000;
static int DelayTiming2=4000;
static int DelayTiming3=6000;


Code: Select all

        //dim down the far east channels
        PWMChannel[0]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[0],0,60);      
        PWMChannel[8]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[8],0,60); 
    
        //delay 2 seconds before starting next dimming
        DelayCount=millis();
        DelayTiming1=2000;
        
        if((millis()-DelayCount)>DelayTiming1)
        {
        //dim down the near east channels
        PWMChannel[1]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming1,PWMChannel[1],0,60);     
        PWMChannel[9]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming1,PWMChannel[9],0,60); 
        }
       
        DelayTiming2=4000;
        
        if((millis()-DelayCount)>DelayTiming2)
        {
        //dim down the near west channels
        PWMChannel[2]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming2,PWMChannel[2],0,60);     
        PWMChannel[10]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming2,PWMChannel[10],0,60);
        }
        
        DelayTiming3=6000;
        
        if((millis()-DelayCount)>DelayTiming3)
        {
        //dim down the far west channels
        PWMChannel[3]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming3,PWMChannel[3],0,60);     
        PWMChannel[11]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming3,PWMChannel[11],0,60);        
        }
      
     // let's go through all channels to pick which ones will be dimmed
      
/////////////////////////////////////////////////////////////////////////////////////////// 
/* 
      
////////                          replacing this with above                         ////////
     
       for (int a=0;a<16;a++)
       {
          if (bitRead(Actinic_Channels,a)==0)
          {
             // this will slope down the DAYLIGHT channels from the current PWM to 0 within 1 minutes.
             // then it will stay at 0 for the duration of the cycle
             // and finally slope up from 0 to PWM value within 1 minutes
             // it is basically an inversed slope
             PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,60);
          }
       }

*/
///////////////////////////////////////////////////////////////////////////////////////////////


Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Thu Oct 30, 2014 2:25 pm
by rimai
This will never work:

Code: Select all

        DelayCount=millis();
        if((millis()-DelayCount)>DelayTiming1)
You are basically assigning DelayCount=millis(); and right after you are checking if the difference in time is > than your DelayTiming1. It will never happen.
You have to assign DelayCount when the cloud starts and not all the time.

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Thu Oct 30, 2014 6:02 pm
by dlplunkett44
Oh yeah, I see that now, but I'm not sure exactly where to place it... Would this be right?

Code: Select all

 if (cloudchance)
 {
    //is it time for cloud yet?
    if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
    {
        DelayCount=millis();
      
        //dim down the far east channels
        PWMChannel[0]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[0],0,60);      
        PWMChannel[8]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[8],0,60); 
               
        if((millis()-DelayCount)>DelayTiming1)
        {
        //dim down the near east channels
        PWMChannel[1]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming1,PWMChannel[1],0,60);     
        PWMChannel[9]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming1,PWMChannel[9],0,60); 
        }
             
        if((millis()-DelayCount)>DelayTiming2)
        {
        //dim down the near west channels
        PWMChannel[2]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming2,PWMChannel[2],0,60);     
        PWMChannel[10]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming2,PWMChannel[10],0,60);
        }
        
        if((millis()-DelayCount)>DelayTiming3)
        {
        //dim down the far west channels
        PWMChannel[3]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming3,PWMChannel[3],0,60);     
        PWMChannel[11]=ReversePWMSlope(cloudstart,cloudstart+cloudduration+DelayTiming3,PWMChannel[11],0,60);        
        }
      

Re: Clouds/Lightning/Storms for 16 Channel PWM Expansion

Posted: Fri Oct 31, 2014 2:41 am
by dlplunkett44
...or maybe its not needed there at all. I have it declared above at the beginning of checkcloud():

static time_t DelayCount=millis();
static int DelayTiming1=2000;
static int DelayTiming2=4000;
static int DelayTiming3=6000;