PDA

View Full Version : Have a headache - need some suggestions with code logic



Scampy
- 20th October 2013, 00:27
Hi Guys,

I'm in the process of working out some logic for a project which uses PWM to control some power LEDs. My current version which was adapted from a friends basic code works OK when programmed, but has a few bugs, so I'm starting with a clean sheet and aim for something more flexible.

I'm using a DS1307 and have the hours and minutes converted from BDC to give two variables TimeH and TimeM. I then want to set five user programmable timing points where the programmable brightness of the LEDs can be set, and the code either ramps up or down to these values as it passes the points. For example, assuming the first point is set to 14:00, and the second is 14:30. The value for the first point is 0 and 128 for the second. So when the time equals point 1 the LEDs will fade up to a 128 (or 50:50) duty cycle by the time it reaches the second set point time. If the third point is set to 18:00 say, and a value of 254, then the LEDs would continue to increase from 128 to 254 over the course of three and a half hours. The next point could be say 20:00 and a value of 64 so the LEDs dim from 254 to 64 over two hours, and finally the last point at 21:00 means the LEDs dim from 64 to 0 over the last hour.

I was proposing to do an if point1 hour = TimeH and point1 min = TimeM then case=1 type statement, and then in the case section do some form of calculation to give the seconds between the point 1 time and point 2 time and then divide this by the value for the second point to give the duration between increments for the PWM. Whilst this is OK for the first section where the PWM is increasing, it raises an issue for subsequent sections as the duty cycle could decrease or increase (say if we wanted to go to full brightness between point 1 and point 2 and then slowly fade down to point 3 with a rapid fade down between 4 and 5). This is problem 1

The second problem is that I need some form of time check so in the event of a power cut, the unit can work out where in the cycle it should be when the power returns, and fade the LEDs up to the corresponding value if power is restored at a time when the LEDs should be on. For example if the power came back on at 14:15 the code would work out its midway between point 1 and 2 and then ramp up the LEDs to a value of 128 over 15 minutes, so it then matches the programmed value at the programmed time. If the power cut was in the middle of the night then it would know that let value would be zero and thus the lights would stay off.

My existing project simply allows you to set an on time, fade in duration in hours and minutes to reach the set brightness, then an off time and fade out duration, but has no power cut option and sometimes if changes to the values are made from the push buttons it falls over and sometimes starts turning then LEDs back on after the off time has passed, or the brightness value gets corrupted and the LEDs don't reach the desired setting. Flash the chip again with the presets and it works fine !

The PIC is an 18F4520, and will use the hardware PWM pins for the LEDs.

Any suggestions or assistance would be welcome.

aerostar
- 20th October 2013, 07:53
The Ds1307 has onboard user memory - if you run the IC battery backed, you will have the current time when power is restored. Also you could store your PWM variables there as well, and be resilient to power cut corruption.

I would suggest that it may be easier to use minutes (word Var) for your calcs internally, 1440 minutes per day, 3600 secs per hour.

So for your first 14:00 - 14:30 that would be start at 840 minutes and end at 870 minutes, difference being 30mins = 1800 secs - divide that by 128 which gives 1 per 14secs approx increase of PWM value.

Amoque
- 20th October 2013, 12:31
I cannot offer you a programming example, but some thoughts do come to mind...

It is obvious to you as well that in order to save state, the time values will be written to eeprom, then each "next endpoint" fetched as the current is reached? Have I understood your intent so far? If so, in my mind, I think of the time as distance... and think the absolute difference between now and endpoint will provide either seconds or minutes number until next endpoint (I imagine minutes is resolution enough).

Now, knowing the difference between PWM now and PWMgoal you have like units and can determine the PWM step/ unit of time by division. If the PWMgoal is less than the current value, well... multiply by -1 then add to the current PWM as you would if PWMgoal was higher than current value.

I do not believe the power cut issue should be too hard; again, I hope to interpret your post correctly. The DS1307 has a flag set on power interrupt (and the PIC may set a flag similarly) to indicate this interruption. By reading the previous endpoint in this case (from eeprom) rather than the current time , to duplicate the PWMstep value is easy, then to multiply by the difference between the "then" and current time will put you back in place. Or, it may be you write the step value to eeprom and fetch it from there as needed - even every period, second or minute, is not to often to read the value. OOPS! Rereading your post, this is not necessary - just recalculate step value from current time to endpoint would change the ramp value and end at correct time.

Here is an example of my thinking...

From 1:00 to 2:00 is 60 minutes (current time to next eeprom value). If the ramp to value is 128 and current value is 64, then the step value is 64 divided by 60 or 1,06 units PWM added every minute.
From 2:00 to 3:15 is 75 minutes. If the ramp to value is 50 and current value 200, then the step will be 150 divided by 75 or 2, multiplied by -1 for correct direction.

Using the previous, if the time fails at 2:15, then only recalculate the steps (now 60) into the ramp value (150) and get the new value of -2,5 to reach goal in the time remaining.

HTH-

Demon
- 20th October 2013, 15:45
I would use Darrel's interrupts to measure time.

http://www.picbasic.co.uk/forum/showthread.php?t=3251

Robert