And also thanks for the explanation in relation to the intricacies of defining 'anti_hunt_delay". On a previous occasion (when it was defined as 'const int anti_hunt_delay = 15 * 60 * 1000') the program would hang. When I did some research into the different variables I found out that as an 'int' it could not be more than 32,767, and when I reduced the number below that, the program worked.
Shouldn't the compiler pick this error up? Obviously it does not. A trap for young players (like myself).
Yes. It should. Its disappointing the compiler doesn't provide a warning of type overflow. This is a gimme on just about any modern c/c++ compiler. Perhaps they don't enable warnings when they call the compiler? I dunno. If so, that's not so smart. Compilers typically emit warnings for good reason.
The problem with that is the delay function requires an unsigned int, which he also pointed out (I've not confirmed
Anyway, what I have done is changed it to an 'unsigned int' and reduced the anti_hunt_delay to 60 * 1000 (as recommend by you). I am sure this anti_hunt_delay will be sufficient, do you?
Just an idea, is it possible to have a nested delay loop to provide the full 15 minutes? (ie loop 1 (outside loop) runs 15 times and loop 2 (inside loop) runs 60,000 times). Would this then produce the total of 15 * 60 * 1000 as suggested by you originally? Perhaps it is all too much trouble and the 60 seconds (60 *1000) is enough, I am just curious to know if my approach would work.
Okay, I decided to put this to rest. No more laziness on my part. I'm checking. According to this page
, delay accepts an unsigned long rather than an unsigned int. That's very typical for time functions to accept unsigned longs, so its not really surprising.
And I quote:
ms: the number of milliseconds to pause (unsigned long)
So yes, as stated by PaulS, change the type to unsigned long as that is the proper data type expected by the delay
I also want to stress, 15-minutes is a completely arbitrary value. Also please note, we delay the anti-hunt duration at the end of every loop AND every time a condition did not trigger a transition. So that means we'll delay up to 2x the anti-hunt delay every loop. This is important to remember because it sets an upper threshold of up to 2x the anti-hunt delay before our door will transition. This means, when we experience a false positive, we'll have to wait up to 2x delay before the door resumes its proper state. So just food for thought.
If you want, you can take the delay out of the else, simply leave the delay at the end of every loop, and add a blinky led or whatever in the else condition. Doing so will keep you from having split-delay behavior. Regardless, the else is really there to allow you to do something else when at state of rest (most of the day or night; aka, steady-state
) is observed by the system.
On a side note, thought you would be very interested to hear of another issue that I had. Last night when I was running the door with the laptop attached so I could watch the serial monitor in order to see how your smoothing algorithm worked. As the door was lowering, the door itself jammed in the rails, the motor kept going until all the string wound off the spool, then immediately started winding up again in the opposite direction and started to lift the door. The door hit the top limit switch but didn't stop (off course not as this is not a condition that I, or assumingly you, could ever have imagined would happen) and the motor kept going. There was lots of gear clunking and groaning going on as the motor continued to turn. I had to quickly pull the power out to kill it. It was a wake up call to me to see the potential power in the motor - potentially scary stuff! I have also decided to screw in a piece of wood across the top of the door to stop the door at its top position. This will also stop the potential of the door ripping the top limit switch off.
I sprayed some silicone spray all throughout the vertical rails and the door slides up and down much better now. I am also going to shave the edge of the doors a bit thinner to make the door slide up and down easier.
Could this potential issue be resolved by checking if either limit switch has been hit (regrdless of whether the door is lifting or lowering)?
I'm don't really understand how the door lifting, hitting the top limit switch, didn't stop the door. That is, the entire purpose of the lift function. Any idea? Or do I misunderstand?
I thought about something like that. I didn't really expect the door to jam on the rails but it did occur to me a pet or other obstruction may get caught. I didn't mention it because of the spindle design rather than direct drive. You're going to need to allow for expansion and contraction of the material. Because of expansion, it might bind up. Because of contraction, the door might wobble in the slot and jam. Your design needs to account for the materials, season, and weather. You might consider using a roller track, such as what you would use for a drawer, rather than a slot. Or, have some wheels/bearings move in the slot rather than the door itself.
Murphy is a bitch. There are many options to look at in an attempt to avoid catastrophic failure. What I had originally envisioned was a simple timer in the lift and lower functions. If it takes a second to lift or lower, a timer of something like one and half to two seconds may be an viable threshold. If it hasn't completely opened or closed within the allotted window of time, then you know you have an error condition. I'm not entirely sure a completely automatic recovery is always possible.
I'll also point out, this is one of those cases where having an RTC can greatly simplify things. I really wish an RTC were far more common on board designs. Its far, far easier for me to think of cases where an RTC isn't needed than to think of all the cases where an RTC makes things easier. And contrary to popular mantra, RTC's empower far, far more than just time stamped logging. In this case, with an RTC, you'd define an ISR and volatile variable. On entry into lift or lower you'd set an alarm of the desired duration. In the loop, you'd also check for a change in the alarm's state. If either variable changed, you exit the loop. But I digress... At any rate, it can be simulated by assigning the current millis time to a variable before you enter your loop and doing some math in the loop against current millis time to see if you should exit. If you need help, let us know.
P.S. Wax is an old school lubricant which does not attract dirt and dust; especially if the lubricated surface is used daily. Its also naturally water proof. I'm frequently surprised how many people don't know wax can be a lubricant. There are commercial wax lubricants (frequently used on motorcycle chains) available as well as simple block paraffin, or even a simple candle. Just remember, whatever you use needs to be appropriate for weather and season. I've used wax, right off of a candle, on sliding doors and stuck windows.