-
Posts: 201 Joined: Sat Oct 10, 2015 9:17 pm
|
 Posted: Wed Nov 23, 2016 12:49 pm
any idea on how to not allow the lights to dim to X amount during cloud/strike? i got my fuge light on oppisite of daylights and daylights are off when dimming is 1% or less and storm code is causing daylights to dim below that level from time to time when actived i use update led set to Mem_B_LightsOffPerc,1 - Code: Select all
void UpdateLED() { ReefAngel.PWM.SetChannelRaw(0,DaylightPWMValue0); ReefAngel.PWM.SetChannelRaw(1,ActinicPWMValue1); ReefAngel.PWM.SetChannelRaw(2,DaylightPWMValue2); ReefAngel.PWM.SetChannelRaw(3,ActinicPWMValue3); ReefAngel.PWM.SetDaylightRaw(DaylightPWMValue); ReefAngel.PWM.SetActinicRaw(ActinicPWMValue);
byte LightsOffPerc=40.95*InternalMemory.read(Mem_B_LightsOffPerc); if (ReefAngel.PWM.GetChannelValueRaw(0)>=LightsOffPerc) ReefAngel.Relay.On(WhiteLeft); else ReefAngel.Relay.Off(WhiteLeft); if (ReefAngel.PWM.GetChannelValueRaw(1)>=LightsOffPerc) ReefAngel.Relay.On(BlueLeft); else ReefAngel.Relay.Off(BlueLeft); }
here is my store code - Code: Select all
// ------------------------------------------------------------ // 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 InternalMemory.read(Mem_B_CloudsEveryXDays)
// 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 InternalMemory.read(Mem_B_CloudChancePerDay)
// Minimum number of minutes for cloud duration. Don't use min duration of less than 6 #define Min_Cloud_Duration InternalMemory.read(Mem_B_MinCloudDuration)
// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255 #define Max_Cloud_Duration InternalMemory.read(Mem_B_MaxCloudDuration)
// Minimum number of clouds that can happen per day #define Min_Clouds_per_Day InternalMemory.read(Mem_B_MinCloudsPerDay)
// Maximum number of clouds that can happen per day #define Max_Clouds_per_Day InternalMemory.read(Mem_B_MaxCloudsPerDay)
// Only start the cloud effect after this setting // In this example, start cloud after noon #define Start_Cloud_After NumMins(InternalMemory.read(Mem_B_StartCloudAfterHour),InternalMemory.read(Mem_B_StartCloudAfterMin))
// Always end the cloud effect before this setting // In this example, end cloud before 9:00pm #define End_Cloud_Before NumMins(InternalMemory.read(Mem_B_EndCloudBeforeHour),InternalMemory.read(Mem_B_EndCloudBeforeMin))
// 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_Chance_per_Cloud InternalMemory.read(Mem_B_LightningChance)
// 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 result 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 // ------------------------------------------------------------ // 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 byte lightningMode=0; static boolean chooseLightning=true;
void CheckCloud() { // Set which modes you want to use // Example: { Calm, 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[] = {Slow};
// Change the values above to customize your cloud/storm effect
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 { // Commenting out to see if it's interfering with our other seed. // 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_Chance_per_Cloud, we will not have lightning today if (lightningchance>Lightning_Chance_per_Cloud) lightningchance=0; } } // Now that we have all the parameters for the cloud, let's create the effect
if (ReefAngel.Relay.isMaskOn(LED_STORM)) { InternalMemory.write(Mem_B_EnableStorm,false); } if (ReefAngel.Relay.isMaskOff(LED_STORM)) { InternalMemory.write(Mem_B_EnableStorm,true); }
if (InternalMemory.read(Mem_B_EnableStorm)) return; if (cloudchance) { if (ReefAngel.Relay.isMaskOff(TRIGGER_STORM)) // Change this to whatever port you want to use as a trigger. { cloudstart = NumMins(hour(), minute()); ReefAngel.Relay.Auto(TRIGGER_STORM); // Here, too. } //is it time for cloud yet? if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration)) { // Increase Blue channel first for better effect and to compensate for drop in Whites ActinicPWMValue1=ReversePWMSlopeHighRes(cloudstart,cloudstart+cloudduration,ActinicPWMValue1,ActinicPWMValue1+DaylightPWMValue0,180); ActinicPWMValue3=ReversePWMSlopeHighRes(cloudstart,cloudstart+cloudduration,ActinicPWMValue3,ActinicPWMValue3+DaylightPWMValue2,180); DaylightPWMValue0=ReversePWMSlopeHighRes(cloudstart,cloudstart+cloudduration,DaylightPWMValue0,0,180); DaylightPWMValue2=ReversePWMSlopeHighRes(cloudstart,cloudstart+cloudduration,DaylightPWMValue2,0,180); 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) { // Send the trigger Strike(); 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) { Strike(); } 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) { Strike();
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 && second()%40<8) { SlowStrike(); } 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_Chance_per_Cloud, we will not have lightning today if (lightningchance>Lightning_Chance_per_Cloud) lightningchance=0; } } } // Cloud ON option - Clouds every minute if (ReefAngel.Relay.isMaskOn(TRIGGER_STORM) && now()%60<10) { SlowStrike(); } }
void SlowStrike() { int r = random(100); if (r<20) lightningstatus=1; else lightningstatus=0; if (lightningstatus) { // Let's separate left and right both. if (r<14) { DaylightPWMValue0=4095; DaylightPWMValue2=4095; ActinicPWMValue1=4095; ActinicPWMValue3=4095; } else if (r<17) { DaylightPWMValue0=100; DaylightPWMValue2=4095; ActinicPWMValue3=4095; } else { DaylightPWMValue0=4095; ActinicPWMValue1=4095; DaylightPWMValue2=100; } } else { DaylightPWMValue0=100; DaylightPWMValue2=100; } delay(1); }
void DrawClouds(int x, int y) { // Write the times of the next cloud, next lightning, and cloud duration to the screen and into some customvars for the Portal. ReefAngel.LCD.DrawText(0,255,x,y,"C"); x+=6; ReefAngel.LCD.DrawText(0,255,x,y,"00:00"); x+=34; ReefAngel.LCD.DrawText(0,255,x,y,"L"); x+=6; ReefAngel.LCD.DrawText(0,255,x,y,"00:00"); x=5; if (cloudchance && (NumMins(hour(),minute())<cloudstart)) { int x=0; if ((cloudstart/60)>=10) x=11; else x=17; ReefAngel.LCD.DrawText(0,255,x,y,(cloudstart/60)); ReefAngel.CustomVar[0]=cloudstart/60; // Write the hour of the next cloud to custom variable for Portal reporting if ((cloudstart%60)>=10) x=29; else x=35; ReefAngel.LCD.DrawText(0,255,x,y,(cloudstart%60)); ReefAngel.CustomVar[1]=cloudstart%60; // Write the minute of the next cloud to custom variable for Portal reporting
} ReefAngel.LCD.DrawText(0,255,x+85,y,cloudduration); ReefAngel.CustomVar[2]=(cloudduration); // Put the duration of the next cloud in a custom var for the portal if (lightningchance) { int x=0; if (((cloudstart+(cloudduration/3))/60)>=10) x=51; else x=57; ReefAngel.LCD.DrawText(0,255,x,y,((cloudstart+(cloudduration/3))/60)); ReefAngel.CustomVar[6]=(cloudstart+(cloudduration/2))/60; // Write the hour of the next lightning to a custom variable for the Portal if (((cloudstart+(cloudduration/3))%60)>=10) x=69; else x=75; ReefAngel.LCD.DrawText(0,255,x,y,((cloudstart+(cloudduration/3))%60)); // Write the minute of the next lightning to a custom variable for the Portal ReefAngel.CustomVar[7]=(cloudstart+(cloudduration/2))%60; } }
void Strike() { int a=random(1,5); // Pick a number of consecutive flashes from 1 to 4. for (int i=0; i<a; i++) { // Flash on int newdata=4095; Wire.beginTransmission(0x40); // Address of the dimming expansion module Wire.write(0x8+(4*0)); // 0x8 is channel 0, 0x12 is channel 1, etc. This is channel 0. Wire.write(newdata&0xff); // Send the data 8 bits at a time. This sends the LSB Wire.write(newdata>>8); // This sends the MSB Wire.endTransmission(); Wire.beginTransmission(0x40); // Address of the dimming expansion module Wire.write(0x8+(4*2)); // 0x8 is channel 0, 0x12 is channel 1, etc. This is channel 2. Wire.write(newdata&0xff); // Send the data 8 bits at a time. This sends the LSB Wire.write(newdata>>8); // This sends the MSB 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 // Flash off. Return to baseline. newdata=ReefAngel.PWM.GetChannelValueRaw(0); // Use the channel number you're flashing here Wire.beginTransmission(0x40); // Same as above Wire.write(0x8+(4*0)); Wire.write(newdata&0xff); Wire.write(newdata>>8); Wire.endTransmission(); newdata=ReefAngel.PWM.GetChannelValueRaw(2); // Use the channel number you're flashing here Wire.beginTransmission(0x40); // Same as above Wire.write(0x8+(4*2)); Wire.write(newdata&0xff); Wire.write(newdata>>8); Wire.endTransmission(); delay(random(30,50)); // Wait from 30 to 49 ms wdt_reset(); // Reset watchdog timer to avoid re-boots } }
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 (int) PWMStart; }
int ReversePWMSlopeHighRes(long cstart,long cend,int PWMStart,int 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 (int) PWMStart; }

|