Hello
I am making an automation for aquarium light. Arduino is driving stepper motor which turning potentiometer, which further regulate 1-10V input on ballast for T5 bulbs.
So I have connected everything, made a code and it works.
Just one thing confuses me:
For example, part of the code which does "sunrise" should move stepper motor one step when second on clock is 0,20 and 40. This should last for two hours.
By my calculation, it's 3 steps per minute, so in two hours should be 120 x 3 = 360 steps.
But program now in the morning did just 326 steps.
Now I am thinking...
Can it be that some time program miss some seconds?
Cause is doing refresh twice per 1000 (but just once executes the code), and those arduinos 1000 can be slightly more than RTC one second?
right I missed that check, but millis() is not super precise so I'd be careful with this approach. (why don't you wait for 1 full second then ?)
I'd consider something like this
void loop() {
/*-------------------------------------------------------------------------------------------------*/
/*-------------------------------------Sunrise-----------------------------------------------------*/
/*-------------------------------------------------------------------------------------------------*/
static byte waitingFor = 0;
byte hour = myRTC.getHour(h24, hPM);
if ((hour >= 8) && hour < 10) ) {
byte second = myRTC.getSecond();
if (second >= waitingFor) { // >= to catch the possible event that you missed that second if the code is too busy elsewhere (but not to a point where you miss 20s)
if (step < 360) {
step += 1;
waitingFor = (waitingFor + 20) % 60; // go through 0, 20, 40
myStepper.step(1);
}
else {
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
waitingFor = 0;
}
}
}
/*-------------------------------------------------------------------------------------------------*/
}
I assume you have some other part of the code where you reset step the other way at sunset?
Okay, this is a little bit on advance side for me. Can You please explain "waitingFor = (waitingFor + 20) % 60;"
This code will not execute multiple times per one second?
Also further in the code I need sometime steps to be executed 6 times and 7 times per minute...how to apply your code to that?
Thank You.
Yes, I also have "noon" part where lights are at maximum level, till step 1050 going with potentiometer and than disconnect potentiometer with a relay (it gives slightly stronger light) than further trough the day connect again and go opposite direction till step is zero.
you start with waitingFor being 0
when you are in the 8am 10am bracket (sunrise) and the current second is >= 0 then you take one step and change the the waitingFor value with the formula
waitingFor = (waitingFor + 20) % 60;
the % operator is the modulo, the rest of the integral division by 60.
so when waitingFor is 0, the formula is (0 + 20) % 60 ➜ the rest of 20 divided by 60 is 20, si the new value of waitingFor becomes 20, and thus you don't take further steps until the seconds are >= 20
When your seconds goes above 20, the formula is (20 + 20) % 60 ➜ the rest of 40 divided by 60 is 40, si the new value of waitingFor becomes 40, and thus you don't take further steps until the seconds are >= 40
When your seconds goes above 40, the formula is (40 + 20) % 60 ➜ the rest of 60 divided by 60 is 0, si the new value of waitingFor becomes 40, and thus you don't take further steps until the seconds are >= 0
➜ and this is a bug because it will be true all the way between 40 and 60 sorry for that
you should go for == but it means your loop should spin in less than a second or build the time including the hours and minutes (seconds elapsed since midnight) for example and then you don't have the issue any more
Haha, good that You check it out
Okay, so You are right, I need to make a loop shorter than one second .
Building time is not a bad idea, but i don't know how much it can drift during day?
Or maybe...to make a time triggered by Hour, so every Hour its gonna count seconds and minutes. Like this time should not drift a lot?
Thing is, if you don't know something, why not test it and see? Maybe, run a loop for an hour, see what the drift is, and multiply it by 24? These are the things we can do for ourselves, easily. You will find the accuracy of the clock is marginal, and if you want to, you can do the temperature experiment - run it in your room for an hour, then run it in your fridge for an hour, and see how much difference that makes. Curiosity is your friend.
As for the decision-making in your code, I'd recommend reading through the state-change code for ideas. What you want to do, is act on only the FIRST time the time meets your criteria, and at that time, change your criteria to the next target. Then, it doesn't matter how often your loop() runs(I recommend 'as fast as possible'), you'll only ever take the right actions.
It really doesn't matter what your source of time is, by the way, if you structure your decision-making correctly. It could be millis() comparisons, RTC epoch values, or whatever; as long as you take action only the first time you meet criteria, you're good.
Hope that helps.
Forgive me. I'm using IDE 1.8.13, so your menus may be different, but read through
File|Examples|Digital|StateChangeDetection
While the example is all about button state changes, there's no conceptual difference. You simply want to know the first time your conditions are met, and act on that.