Go Down

Topic: Seeking better testing language (Read 1 time) previous topic - next topic

myggle

My sketch queries a Real Time Clock, and depending upon the time, a digital pin switches to HIGH or LOW.  I've tried both the Time and TimeAlarms libraries, but have ran into issues, plus have since found the RTClib to work well for me.

I created a few different programmed events based on time, the first of which is triggered to ON at 6am everyday and triggers OFF at midnight every night and this works perfectly, producing a steady output voltage at the respective digital pin.

However, when I get to my second alarm, I fear my knowledge of the code is failing me and keeping me from asking the right question(s) of the RTC.  My thought is that if the hour is 9 and the minute is 0 and equal to or less than 10, that this would create a test that can only be true from 9:00 to 9:09, but the output is buggy.  Every time the sketch loops, the respective pin (D31=Relay_B) pulses HIGH for maybe 100 milliseconds, then goes LOW for the remainder of the loop.  This pulsing process is repeated while the condition is true then goes LOW until tested true again.

Code: [Select]

define# TURN_ON 0  //  TURN_ON/OFF was defined to accommodate relay polarity
define TURN_OFF 1

if (now.hour() == 9 && now.minute() >= 00 && now.minute() < 10) // FeedPump1, ON 9am
  { 
    digitalWrite(Relay_B, TURN_ON);
    Serial.print("\t");
    Serial.println(F("First 10 Minute Feeding"));  //  Text printed to serial monitor
    Serial.print("\t");
  }
  else // Turn off time for FeedPump1, OFF 9:10am
  { 
    digitalWrite(Relay_B, TURN_OFF);
  }


Relay_B is scheduled to be true twice daily, for 10 minutes each time.  I don't know if it matters, but Relay_A will be true during both of Relay_B being true to it's tests.  Can someone please enlighten me how to ask the most efficient questions as I keep getting tied up mentally in semantics of what is true at what given moment in time.

TYIA

MorganS

Please post the whole sketch, or a cut-down sketch that compiles and runs and shows the problem.
"The problem is in the code you didn't post."

nickgammon

Code: [Select]

define# TURN_ON 0  //  TURN_ON/OFF was defined to accommodate relay polarity
define TURN_OFF 1


?
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

myggle

The defines are because of the relay states are active high and it would confuse me when considering the desired end result.  I will attach my whole sketch.

UKHeliBob

Code: [Select]

define# TURN_ON 0

Code: [Select]

define TURN_OFF 1

Spot the difference
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

nickgammon

#5
Jun 10, 2015, 09:19 am Last Edit: Jun 10, 2015, 09:20 am by Nick Gammon
Neither of which is correct, of course.

Code: [Select]
  if (now.hour() == 9 && now.minute() >= 0 && now.minute() < 10) // FeedPump1, ON 9am
  { 
...
  }
  else // Turn off time for FeedPump1, OFF 9:10am
  { 
    digitalWrite(Relay_B, TURN_OFF);
  }
  //******************* 2nd FEED TIME - RELAY B *********************************************//
  if (now.hour() == 18 && now.minute() >= 0 && now.minute() < 10) // FeedPump, ON 6PM
  { 
...
  }
 else 
  {
  digitalWrite(Relay_B, TURN_OFF);
  }



The net effect, surely, is that Relay_B will always be turned off. The hour can't be be both 9 and 18.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon

Let me put it like this ... if I said:

Quote
If it is not 9 o'clock, slap yourself.
If it is not 6 pm, slap yourself.
Are you going to get a slap? If you aren't sure, try it out. You might even get two slaps. ;)
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Robin2

#7
Jun 10, 2015, 09:43 am Last Edit: Jun 10, 2015, 09:50 am by Robin2
Spot the difference
Aren't they BOTH wrong?

Shouldn't it be #define  ?


Quote
You might even get two slaps
or just continuous slaps ?

If it was my project I would test for the HOUR and then in a subsidiary test check the MINUTES just so I could understand what I was doing
Something like
Code: [Select]
if (HOUR == 9) {
  if (MINUTE >0 && MINUTE < 10) {
    // do whatever
  }
}



...R
Two or three hours spent thinking and reading documentation solves most programming problems.

nickgammon

They way it is written, yes.

Quote
Aren't they BOTH wrong?
Indeed.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

jurs

However, when I get to my second alarm, I fear my knowledge of the code is failing me and keeping me from asking the right question(s) of the RTC.
Perhaps use the IPO principle and do a logical seperation of:
- Input
- Processing
- Output

Do not try to mix input with just a small part of the processing logic and then output directly before all processing is done.


For your relay switching I'd suggest a programming logic like that looping around in the loop() function (untested code):
Code: [Select]

  // Input ==> read the current time from RTC

  // Processing
  boolean relayBstate=false; // initial guess is "relay B is OFF"
  if (now.hour() == 9 && now.minute() >= 00 && now.minute() < 10) relayBstate=true; // 1st 'ON' time
  if (now.hour() == 12 && now.minute() >= 00 && now.minute() < 10) relayBstate=true; // 2nd 'ON' time
  if (now.hour() == 15 && now.minute() >= 00 && now.minute() < 10) relayBstate=true; // 3nd 'ON' time

  // Output
  if (relayBstate==true)
  {
    if (digitalRead(Relay_B)!=TURN_ON) Serial.println("Turn ON relay B");
    digitalWrite(Relay_B, TURN_ON);
  }
  else
  {
     if (digitalRead(Relay_B)!=TURN_OFF) Serial.println("Turn OFF relay B");
     digitalWrite(Relay_B, TURN_OFF);
  }

myggle

#10
Jun 10, 2015, 12:52 pm Last Edit: Jun 10, 2015, 01:22 pm by myggle
Thanks for the feedback.  I pasted the snippet about the test and mistyped the includes by mistake with hopes I would not have to explain why they were defined in the first place.  Yet here I am again explaining them for other reasons.  I was hoping someone would point out the flaws in my test(s) so I can learn from my mistake(s), but I guess not. 

Thank you jurs for at least giving me a different way of doing things, I will start testing immediately.

Edit - @jurs, can you explain the purpose of using the NOT operator?  I see that it is used in many places throughout the example sketches I've been through and never understood why it is important to ask in code if something is NOT, when the code never told it to be?  Or why is the code testing to see if the light was turned on before the mention of the command to turn it on?

TYIA

aarg

Thanks for the feedback.  I pasted the snippet about the test and mistyped the includes by mistake with hopes I would not have to explain why they were defined in the first place.  Yet here I am again explaining them for other reasons.  I was hoping someone would point out the flaws in my test(s) so I can learn from my mistake(s), but I guess not. 

Thank you jurs for at least giving me a different way of doing things, I will start testing immediately.
Well, that can happen when you ignore the very first response.

  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

jurs

Edit - @jurs, can you explain the purpose of using the NOT operator?
The NOT operator will do a little "state change detection" before the OUTPUT is set to its value.

As I have seen in your source code, you want to have a small message on Serial each time the state changes.

So with this code:
Code: [Select]

  if (digitalRead(Relay_B)!=TURN_ON) Serial.println("Turn ON relay B");
  digitalWrite(Relay_B, TURN_ON);

I first check if the relay is already in the ON state, and only if it is NOT in ON state, I show the message.
Then it is set to ON state.

Same check happens when turning to OFF state.

myggle

I just tried a few combinations with, and without the not operator statement, and the result was the same.  I even relocated the whole block to occur before the Relay_A test, and the resulted in Relay_B not even pulsing high momentarily.  So I'm at a loss as to why this is the result.

The funny thing is that this was happening when I was using the Mega with an Ethernet shield on it, but now I am using an EtherMega which rules out hardware issues.  To the best of your knowledge, can you spot why Relay_B is only pulsing HIGH and not steadily HIGH?  Some weeks ago I tested to see if the relay channel was faulty by running the blink sketch for pins 30-37, and all pins went to HIGH for the duration I specified, so I know it has to be something in my code.

@aarg, I did not ignore the first response, I attached my sketch as an attachment because it is too many characters to fit into code brackets.

I will attach an updated version of my sketch as I added the boolean tests that jurs suggested, and modified the println language to be generic to the channel and not the event.  I also cut out the second block for Relay_B as the boolean test can incorporate other tests.

PaulS

Code: [Select]
  if (now.hour() >= 6 && now.minute() >= 0) {  // Turn on time for Veg Lights, ON at 6am
    digitalWrite(Relay_A, TURN_ON);

    Serial.print("\t");
    Serial.println(F("Vegetative Lights On"));  //  Text printed to serial monitor
    Serial.print("\t");
  }
  else if (now.hour() >= 0 && now.minute() >= 0) // "else if" was needed to create opposition to lights on
  {  // Turn off time for Veg Lights, OFF at 12am
    digitalWrite(Relay_A, TURN_OFF);
    Serial.print("\t");
    Serial.println(F("Vegitative Lights OFf"));  //  Text printed to serial monitor
    Serial.print("\t");
  }

Can you envision a scenario where the hour value is 6 or more, and the minute value is not greater than or equal to 0?

Can you envision a scenario where the else if test would not evaluate to true?
The art of getting good answers lies in asking good questions.

Go Up