led dimming on and off without delay - need your help

does any one have a led dimmer set on a timer sketch they like to share...?

i cant seem to figure out how to code this...

timer set for on and off time - set by the user

what i like it to do is dim the led at the on set time, When time reach the half way mark from the set timer on to the set timer off,it will be max at 255 value and start to dim the LED down from that half way mark to the set timer off... Ending the "dimMoonLight" value at 0.

any idea on how to do this?

this is what i did but it didnt seem to work out at all..

//dimMoonLight for map vaule 
//timeHour for RTC reading Hours
//t.min for RTC reading Mins
//t.sec for RTC reading Sec
//ledMoonLightsT1OnH  for user set timer hours on
//ledMoonLightsT1OnM for user set timer mins on
//ledMoonLightsT1OnS for user set timer secs on

//ledMoonLightsT1OffH  for user set timer hours off
//ledMoonLightsT1OffM for user set timer mins off
//ledMoonLightsT1OffS for user set timer secs off

if (timeHour>=ledMoonLightsT1OnH  && t.min>=ledMoonLightsT1OnM && t.sec>=ledMoonLightsT1OnS 
    && timeHour<=ledMoonLightsT1OffH  && t.min<=ledMoonLightsT1OffM && t.sec<=ledMoonLightsT1OffS)
 {
    dimMoonLight = map((timeHour && t.min && t.sec), (ledMoonLightsT1OnH && ledMoonLightsT1OnM && ledMoonLightsT1OnS), (ledMoonLightsT1OffH && ledMoonLightsT1OffM &&       ledMoonLightsT1OffS), 35, 255); //Dimer Value starts at 35 when RTC time equals to User set timer H:M:S on & max out at 255 when RTC time equals to User set timer H:M:S off
    analogWrite(ledMoonlightsPin, dimMoonLight); //ledMoonlightsPin assign to pwm pin 7 on arduino mega 2560 & "dimMoonLight" for map vaule
 }

by doing this... i get the led to turn on at the vaule of 34-35 but it never change at all from the time it starts to the time it ends...
this code that i wrote only dims the led from the set timer on at 35 and ends it at the set timer off at 255, this was a test to see if it works which it didnt so any help would be great.

It might be easier to do the calculations if you convert from HH:MM:SS to a single value in seconds. Then you can do comparisons and subtractions much more easily.

timeHour>=ledMoonLightsT1OnH  && t.min>=ledMoonLightsT1OnM && t.sec>=ledMoonLightsT1OnS

This won't work because if the hour is greater but the minutes are less the result is FALSE even though the hour being greater is enough to make the time greater. To get it to work you need something more complicated like:

timeHour>ledMoonLightsT1OnH  || 
(timeHour==ledMoonLightsT1OnH && t.min>ledMoonLightsT1OnM) || 
(timeHour==ledMoonLightsT1OnH && t.min==ledMoonLightsT1OnM && t.sec>=ledMoonLightsT1OnS)

what about the mapping part ?

dimMoonLight = map((timeHour && t.min && t.sec), (ledMoonLightsT1OnH && ledMoonLightsT1OnM && ledMoonLightsT1OnS), (ledMoonLightsT1OffH && ledMoonLightsT1OffM &&       ledMoonLightsT1OffS), 35, 255);

it seems as if the value doesnt change when time is greater then the "set timer on" from the mapping part... even if i remove the if statement, the vaule doesnt seem to change in the map section

This is an application where Finite State Machine programming would work well.

While you are waiting for the 'time' to do something (ie, dim the leds) you are in one state where all you do is wait for the time. Once that time happens, you change to another state where you are just worried about dimming the LED. Because you go to this state by the time expiring, you can stop checking the time. This should simplify your logic for the sake of at least one extra variable.

i'm thinking of just doing mins for dimming... 0-255 within 1 hour or 59 mins...

just not sure how to do the math say if someone sets the timer to 10:40:00 Pm ...

so i would need to do something like 40min+59min but when i do this... rtc gives me 99mins as the value and doesnt roll over to 11:39...

so what math can i do to get it to roll over?

would i have to do something like

addmins = (40+59);
if (addmins>59)
{
addmins-60;}

will something like this work for rtc mins?

unsigned long OnTime= ledMoonLightsT1OnH * 3600UL + ledMoonLightsT1OnM * 60UL + ledMoonLightsT1OnS;
unsigned long OffTime = ledMoonLightsT1OffH * 3600UL + ledMoonLightsT1OffM * 60UL + ledMoonLightsT1OffS;
unsigned long MidTime = (OnTime + OffTime) / 2;

void loop() {
  unsigned long CurrentTime;
  int brightness;


  // Read the RTC!
  CurrentTime = timeHour * 3600UL + t.min * 60UL + t.sec;
  if (CurrentTime < OnTime || CurrentTime > OffTime)
    return;  // Nothing to do outside the time range

  if (CurrentTime < MidTime) // Fading up
    brightness = map(CurrentTime,OnTime,MidTime,0,255);
  else // Fading down
    brightness = map(CurrentTime,MidTime,OffTime,255,0);

  analogWrite(LEDPin, brightness);
}

john your a life saver... ever though of being a life guard? lol

but i just wanted to know what these do so i can understand and learn from them...

unsigned long OnTime= ledMoonLightsT1OnH * 3600UL + ledMoonLightsT1OnM * 60UL + ledMoonLightsT1OnS;

so what does the "* 3600UL" mean for the hours on... and what does the "UL" mean and does it need to be there?
same goes with mins...

and why doesnt the secs need or have one?

P.S. i think i figured it out... 3600sec in 1 hr and mins is 60 sec per min.. and for sec 60 secs is 60 secs lol

so what about the "UL" i believe it stands for unsigned long but does it need to be added after number? if so why?

bryanmc1988:
so what about the "UL" i believe it stands for unsigned long but does it need to be added after number? if so why?

Yes, it means 'unsigned long'. Without it you might multiply an 'int' number of hours by an 'int' constant 3600 and get a value larger than 32767 which is the largest positive number a 16-bit 'int' can hold. Your number would have the high-order bit set indicating NEGATIVE number.
12 hours * 3600 seconds per hour = 43200 seconds (0xA8C0)
0xA8C0 as a signed integer is -22336
By using unsigned long math you avoid the overflow.
In this case 'unsigned' would work but since the result is being stored in an 'unsigned long' it makes sense to do the math that way.

i have a question but wouldn't the time be conflicted if say its set on at hour 23 and off hour at 8? then the statement for fade on and off would be wrong wont it?

i also have a question....

on this: unsigned long MidTime = (OnTime + OffTime) / 2;

i know it takes the set timer on and set timer off and divide it in hald and thats where the half way mark is that was said i wanted...

but now to think of it... its a LOOOOONNNNNNGGGGG time before it gets fully turn on... so want i decided to do was somehow get it to turn on fully say within the first 10% from the on time?

how would i go about doing this? would it be like : unsigned long tenPercent = (OnTime + OffTime) / 10 + OnTime; ? would this give me that 10%? within the OnTime, and how would i calculate it to start fading off 10% before it fades to 0?

not really smart with math here lol so any help would be great...

bryanmc1988:
Wouldn't the time be conflicted if say its set on at hour 23 and off hour at 8? then the statement for fade on and off would be wrong wont it?

If you only calculate with hours, minutes, and seconds there are no "days". If you want it to work across a day boundary the first step is to add:

    if (OnTime > OffTime)
        OffTime += 24UL*3600UL;  // Add 24 hours to OffTime if it is in the next day

This will give you an OffTime that is greater than the OnTime. Unfortunately CurrentTime still wraps at midnight so it will never reach OffTime. You can add 24 hours to CurrentTime, but when? It can't be based on time of day since we don't know which day that is. You should keep a "PreviousCurrentTime" and when CurrentTime < PreviousCurrentTime you increment a day counter. Then add 24-hours times the day counter to CurrentTime.
But then what happens the next day? CurrentTime is already past OffTime so the cycle won't repeat. After OffTime you have to reset the day counter.
It gets complicated.

Ohic... It might be to much with the whole day thinks I guess I'll have to figure something out to avoid that...

Any idea how I can do the 10% thing for fade on and off? More info in my top post just above ur last post...

For a 10% ramp calculate OffTime-OnTime (the number of seconds the light will be on) and divide that by 10. Use that number to add to OnTime to get FullOnTime and subtract from OffTime to get DimStartTime. Check for times between OnTime and FullOnTime for the dim up. Check for times between DimStartTime and OffTime for the dim down.

do do you mean something like this?

tenPercentOn = (OnTime + ((OffTime - OnTime) / 10));
tenPercentOff = (OffTime - ((OffTime - OnTime) / 10));

bryanmc1988:
do do you mean something like this?
tenPercentOn = (OnTime + ((OffTime - OnTime) / 10));
tenPercentOff = (OffTime - ((OffTime - OnTime) / 10));

Yes, like that.
The variable names are starting to make less and less logical sense. Perhaps you should switch to:
DimUpStartTime, DimUpEndTime, DimDownStartTime, and DimDownEndTime.

Bryan, Arduino has millis() that returns unsigned long milliseconds since startup.
That is enough to cover intervals up to 49.7... days.

It's far easier to code to millis than hour, minute, whatever. If you want a led to change from 0 to full in 256 steps in 60 seconds then each step is at ( 60000UL x unsigned long step# / 256UL, note the multiply before the divide ). I get 23.47... millis per step up for a 60 second ramp-up.

If exact time isn't necessary then perhaps go 24ms each step?

I expect you're running the led on PWM to control brightness? Up the analogWrite at each step?

With millis you can tell how long two times are apart up to the size of the variables you keep time in. For you for now, that's 49.7 days using unsigned longs.

How to tell the difference is to subtract the earlier time from the later time. Even if the earlier time is before the rollover and the later time is after, the difference will come out right because unsigned math is like a clock, the numbers go in a circle and the result is always positive.

So given a start time and a wait time, you can tell if "now" is before or after the wait by getting millis, subtracting the start time and seeing of it is >= wait time then act on that or keep waiting. And you can do this many times per millisecond.

If you want the user dealing in days, hours, minutes, seconds then interface to that but turn it all into millis or micros to run your code by and turn it back to make user-read output.