I'm trying to do a sunrise / sunset sketch which works fine actally, but i'm stuck right now.
I have attached the part of my sketch.
SO i'm driving an led that can be:
Manual ON
Manual OFF
Dimmed ON by the sunrise time trigger
Dimmed OFF by the sunset time trigger
IF there is for example a power outage during the sunrise/sunset cycle and power returns, i don't want the led to restart this cycle, but just turn on/off.
That is why i have the +10 in the if statements. For testing i want the led to start dimming on, but if power returns when time >10mins + sunrise time, the led should just be ON.
My problem with how i implemented this is that the dimming cycle can now never be longer then 10mins. It just turns ON after these 10mins.
How can i do this better?
I hope i'm explaining this problem good enough.
Ok sorry, i understand that.
I have cleared most irrelevant code.
The important piece where my problem lies is the one i quoted in the opening post.
minOfDay is the minutes since midnight
mSunrise is sunrise time in minutes
mSunset is sunset time in minutes.
I want to start the fade on when the mindofday > msunrise. But when there is a power outage during the dimming i want the led to be on immediately and not start the fade again.
Same for sunset.
All this should be overruled by the ManualLEDoff and ManualLEDon variables.
I hope this is a bit more clear.
Thx
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLord.h>
#include <TimeLib.h>
#include <SimpleTimer.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <Wire.h>
#include <PCA9685.h>
#define ONE_WIRE_BUS D3 // Pin for the one-wire temperature sensors
PCA9685 whiteDrv(0x40); // PWM breakout board i2c address
String realtime;
unsigned long epochtime;
float minOfDay;
unsigned long currentMillis;
unsigned long previousMillis = 0;
unsigned long lastUpdate = 0;
byte manualLEDon = 0;
byte manualLEDoff = 0;
int OffsetsunRise = 0;
int OffsetsunSet = 0;
int sunsethour;
int sunsetminute;
int sunrisehour;
int sunriseminute;
float mSunrise, mSunset;
byte isDay, isNight;
int fadeAmount = 1;
const long interval = 5; //7058 = 30min
unsigned int brightnessSunrise = 0;
unsigned int brightnessSunset = 255;
unsigned int brightness;
bool dimmedon, dimmedoff;
bool SunriseStarted, SunsetStarted;
String ledstate = "test";
// what is our longitude (west values negative) and latitude (south values negative)
float LONGITUDE = 4.01; //(-52.8)
float LATITUDE = 50.74; //(5.31)
TimeLord tardis;
byte today[] = { 0, 0, 12, 0, 0, 0 };
WiFiUDP ntpUDP;
// the timer object
SimpleTimer timer;
// By default 'time.nist.gov' is used with 60 seconds update interval and
// no offset
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);
OneWire oneWire(ONE_WIRE_BUS);
// a function to update the time object
void updateTime() {
timeClient.update();
realtime = timeClient.getFormattedTime();
epochtime = timeClient.getEpochTime();
}
void ledfadeON(){
if (!dimmedon){
SunsetStarted = true;
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// set the LED with the ledState of the variable:
brightnessSunrise = brightnessSunrise + fadeAmount;
brightness = brightnessSunrise;
whiteDrv.setChannel8bit(3, brightness);
Serial.println(brightnessSunrise);
}
}
if (brightnessSunrise == 255){ //1020
dimmedon = true;
dimmedoff = false;
}
}
void ledfadeOFF(){
SunriseStarted = true;
if (!dimmedoff){
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// set the LED with the ledState of the variable:
brightnessSunset = brightnessSunset - fadeAmount;
brightness = brightnessSunset;
whiteDrv.setChannel8bit(3, brightness);
Serial.println(brightnessSunset);
}
}
if (brightnessSunset == 0){
whiteDrv.setChannel8bit(3, 0);
dimmedon = false;
dimmedoff = true;
}
}
void setup() {
Serial.begin(115200);
//Serial.setDebugOutput(true);
delay(100);
Wire.begin(14,12); // initialize the PWM connection
whiteDrv.begin();
whiteDrv.setFrequency(1000); // set PWM frequency
timeClient.begin();
timer.setInterval(1000, updateTime);
tardis.TimeZone(60); // tell TimeLord what timezone your RTC is synchronized to. You can ignore DST
// as long as the RTC never changes back and forth between DST and non-DST
tardis.Position(LATITUDE, LONGITUDE); // tell TimeLord where in the world we are
}
void loop() {
currentMillis = millis();
timer.run();
today[3] = day(epochtime);
today[4] = month(epochtime);
today[5] = year(epochtime); // store today's date (at noon) in an array for TimeLord to use
tardis.SunRise(today); // calculate sunrise time
sunrisehour = today[tl_hour];
sunriseminute = today[tl_minute];
mSunrise = today[2] * 60 + today[1] + OffsetsunRise;
tardis.SunSet(today); // calculate sunset time
sunsethour = today[tl_hour];
sunsetminute = today[tl_minute];
mSunset = today[2] * 60 + today[1] + OffsetsunSet;
minOfDay = hour(epochtime) * 60 + minute(epochtime);
if ( manualLEDoff == 1 ) {
whiteDrv.setChannel8bit(3, 255);
ledstate = "manual off";
}
else if ( manualLEDon == 1 ) {
whiteDrv.setChannel8bit(3, 0);
ledstate = "manual on";
}
else if ( minOfDay < (mSunset + 10) && minOfDay >= mSunset) {
isDay = 0;
isNight = 1;
if ( !dimmedoff ) {
if ( !SunsetStarted ) {
Serial.println("Started Sunset Sequence");
}
ledfadeON();
ledstate = "Dimmed off";
}
}
else if ( minOfDay > mSunrise && minOfDay < (mSunrise + 10) ) {
isDay = 1;
isNight = 0;
if (!dimmedon) {
if (!SunriseStarted) {
Serial.println("Started Sunrise Sequence");
}
ledfadeOFF();
ledstate = "Dimmed on";
}
}
else if ( minOfDay > (mSunrise + 10) && minOfDay < mSunset && SunriseStarted != 0) {
whiteDrv.setChannel8bit(3, 0);
ledstate = "ON after 10min";
}
else {
whiteDrv.setChannel8bit(3, 255);
ledstate = "OFF after 10min";
}
}
But when there is a power outage during the dimming i want the led to be on immediately and not start the fade again.
How is the Arduino supposed to know what you want? If there is a power outage, and the time is past mSunrise, but less than mSunrise + fade time, how is the Arduino supposed to know to just turn the lights on, rather than fade?
if you are using a Real Time Clock (or some external real-time source) why not just get the program to go immediately to the appropriate setting for whatever the time happens to be after power-up.
I guess the best that you can hope for is to design your fade in (and fade out ?) algorithms in such a way that, if there is a power restore during the fading, that the fading starts at the same intensity as it would have done at that time point, had the power outage not happened.
OK. That is a bit abstract, so a concrete example.
If my reasoning is correct this will prohibit the dimming to start if the arduino was running for less than 10min. So for example it should turn the LED on ( brightness = 255 ).
After the 10mins the led should just stay 100% and not start the fade cycle again because of the && brightness = 255.
Let's hope it works as i think it should thx for the help!!
BulldogLowell:
well, if it daytime, musn't it be nighttime?
if (isDay == 1){
Serial.println("Licht AAN");
}
//if (isNight == 1){
else{ //<<<<<<<<<<<<<<<< how about this instead?
Serial.println("Licht UIT");
}
you certainly have approached this in an interesting manner, like your **serialinfo.h** file that just prints global variables.
may I ask why you chose to do that? Was this code you inherited?
Yes you are right about the day/night. I don't remember why i did it that way.
Certainly cleaner your way.
Very little code was inherited. I did the serialinfo myself for debugging purpose so i can keep track on what is happening.
Is this trange?
A lot of these things are a result of my inexperience. At the end of the day i can usually get it to work, just not very clean.
Bart_e:
Yes you are right about the day/night. I don't remember why i did it that way.
Certainly cleaner your way.
Very little code was inherited. I did the serialinfo myself for debugging purpose so i can keep track on what is happening.
Is this trange?
A lot of these things are a result of my inexperience. At the end of the day i can usually get it to work, just not very clean.
Generally, you would create such a structure (i.e. a discrete header and implementation file; *.h and/or *.cpp) when you had some code that was useful across many of your programs. Think of it like a toolbox you carry to the job, with lots of tools you rely on often but may not always use. Lots of programmers build their own toolkits and choose to include that toolkit as part of some of the programs they write. This is also common in companies that generate a lot of common-use code that is proprietary.
Also, you see separate header and implementation files (and you see this in your program too) when you are relying on someone else's code (ie a Library).
It is not common for someone to create a separate file structure which relies on Global variables. Rather, it is more common to see each of those special-purpose functions in the main program implementation simply because without that main program, the functions in that header are frankly... useless.
Ok. Thanks for explaining that.
My main reason for splitting up the sketch is to keep it a bit clean.
I'm editing my code when i have some spare time and that is mostly when i'm not behind my main desktop but using our small screen laptop.
I really hate using small screens and i find a large sketch a real pain on our laptop.
So that really is my reasoning
Maybe when i get it completely working, i'll move everything together again.