0

I'm trying to control motor based on rain sensor and my own build anemometer. It should only controlling motor clockwise/CW for open the roof if there are no rain (indicated by value above 900) AND the wind speed below 4 km/h. If there are raining (analog value below 650) and/or wind speed above 4 km/h the motor should spin counterclockwise/CCW. I succeed to rotate the motor CCW if rain and/or high wind speed happen, but when the motor hit the limit switch for stopping the motor, motor only stop for maybe 2 seconds and then back rotating CW (open the roof), even the wind still above 4 km/h. The roof should be open only when there is no rain (analog value above 900) and the wind speed below 2 km/h. Here is my If Statement logic program:

if ((analogRead(rain) < 650 || (Wind > 4)){
  motor_closed();
}

else if (analogRead(rain) < 650 && (Wind > 4)){
  motor_closed();
}

else if (analogRead(rain) < 650 && (Wind < 2)){
  motor_closed();
}

else if (analogRead(rain) > 900 && Wind > 4){
  motor_closed();
}

else if (analogRead(rain) > 900 && Wind < 2){
  motor_open();
}

Did I make mistake when using && boolean operator? Or its something else?

  • Why do you call analogRead() multiple times? Do you expect the result to change that quickly? – Ignacio Vazquez-Abrams Aug 24 '17 at 17:55
  • Only the first and last options will be possible there. – Majenko Aug 24 '17 at 17:57
  • Use analogRead() once and reuse the variable, also what about nesting if statements instead? I think that would improve readability as you can first check if it's raining and then check if it's windy, follows human pattern of thought a bit more than two comparisons at once. Another thing I would avoid is separating else statements from the if statement with a newline, harder to read. – Avamander Aug 24 '17 at 17:58
  • I don't expect for fast result change, only want that the motor respond accordingly. I'm thought it would work with multiple if statements and raining and windy comparisons. – rofimu Aug 24 '17 at 18:05
  • You only need two tests: "is it too windy or too wet?" Yes, close it. Otherwise, "is it not windy enough and not rainy enough?" Yes, open it. – Majenko Aug 24 '17 at 18:13
1

I ran a test with your original code, with rain and wind varying over all the range:

(rain, wind) -> action
------------------------
(600, 1) -> motor_closed
(600, 2) -> motor_closed
(600, 3) -> motor_closed
(600, 4) -> motor_closed
(600, 5) -> motor_closed
(650, 1) -> 
(650, 2) -> 
(650, 3) -> 
(650, 4) -> 
(650, 5) -> motor_closed
(700, 1) -> 
(700, 2) -> 
(700, 3) -> 
(700, 4) -> 
(700, 5) -> motor_closed
(750, 1) -> 
(750, 2) -> 
(750, 3) -> 
(750, 4) -> 
(750, 5) -> motor_closed
(800, 1) -> 
(800, 2) -> 
(800, 3) -> 
(800, 4) -> 
(800, 5) -> motor_closed
(850, 1) -> 
(850, 2) -> 
(850, 3) -> 
(850, 4) -> 
(850, 5) -> motor_closed
(900, 1) -> 
(900, 2) -> 
(900, 3) -> 
(900, 4) -> 
(900, 5) -> motor_closed
(950, 1) -> motor_open
(950, 2) -> 
(950, 3) -> 
(950, 4) -> 
(950, 5) -> motor_closed

So your logical expression reduces to this:

if (analogRead(rain) < 650 || Wind > 4) {motor_close();}
else if (analogRead(rain) > 900 and Wind == 1) {motor_open();}

It's that what you want?

What's that "limiting switch"? May be it's a physical problem (like installing sensor under de roof)

  • you can improve your code by declaring a temporary variable, e.g. ar in this way ar = analogRead(rain); and then perform your code checking ar instead of analogRead(rain). – next-hack Aug 24 '17 at 18:28
  • The concept is when its raining or strong wind the motor will closing the roof, and when no rain and no strong wind then the motor will open the roof. For controlling motor I use 2 limit switches for stopping the motor when it reach the edge of the roof, 1 for stopping from closing, 1 for stopping from opening. There no issue with limit switches, everything looks good. – rofimu Aug 24 '17 at 18:43
  • @rofimu. Look at test I ran. What is missing or superfluous in that? – user31481 Aug 24 '17 at 19:04
  • actually, my first code before I use with multiple If statements is similar like this. But I don't know why every limit switch active (pressed), the motor stop (roof closed), but maybe 1-2 seconds later it turn the opposite way and open the roof although in strong wind condition, but able to stop completely after pressing the second limit switch. I still prefer with else if (analogRead(rain) > 900 and Wind < 2) {motor_open();}. Is it and or && for the operators? – rofimu Aug 24 '17 at 19:08
  • In C it is && and || for logical "and" and "or" operations. – Majenko Aug 24 '17 at 19:25
0

Personally I like to force precedence in my if statements to ensure that things always work precisely as I intend. Group your logical predicates with brackets:

if ((analogRead(rain) < 650) || (Wind > 4)) {
    motor_close();
} else if ((analogRead(rain) > 900) and (Wind < 2)) {
    motor_open();
}

Using intermediate variables would make it more readable:

bool tooWindy = (Wind > 4);
bool notWindy = (Wind < 2);
bool tooRainy = (analogRead(rain) < 650);
bool notRainy = (analogRead(rain) > 900);

if (tooWindy || tooRainy) {
    motor_close();
} else if (notWindy && notRainy) {
    motor_open();
}

Giving names to the logical conditions makes it far more obvious what is going on:

  • If it is too window or it is too rainy then close the roof.
  • Otherwise, if it's not too windy and it's not too rainy then you can open the roof.

And of course you have the time when it's between too rainy and not too rainy, or between too windy and not too windy, in which case nothing should happen. This is called hysteresis and is good to have since it stops the roof from opening and then immediately wanting to close.

You could also improve the logic of the system even more and implement a small Finite State Machine:

enum {
    CLOSED, OPENING, OPEN, CLOSING
};

int state = CLOSED;

switch (state) {
    case CLOSED:
        if ((analogRead(rain) > 900) && (Wind < 2)) {
            motor_open();
            state = OPENING;
        }
        break;

    case OPENING:
        if (digitalRead(limit_open) == HIGH) {
            motor_stop();
            state = OPEN;
        }
        break;

    case OPEN: 
        if ((analogRead(rain) < 650) || (Wind > 4)) {
            motor_closed();
            state = CLOSING;
        }
        break;

    case CLOSING:
        if (digitalRead(limit_close) == HIGH) {
            motor_stop();
            state = CLOSED;
        }
        break;
}

In that you only attempt to open the roof (and even check to see if you should open the roof) if the roof is actually closed. Similarly for checking for and closing the roof - it only happens when the roof is actually open. Nothing happens in the way of checks while the roof is in the process of opening or closing, so it has to complete its open or close operation first before any more decisions are made as to whether the roof should be open or closed.

0

Did I make mistake when using && boolean operator? Or its something else?

use brackets liberally.

rather than

if (x > 65 && y < 10)

instead,

if ((x > 65) && (y < 10))
-1

Try this:

if(analogRead(rain) > 900 && Wind < 2){
  motor_open();
}
else{
  motor_closed();
}
  • The existing tests provide a bit of hysteresis which you have lost in your simplification. – Majenko Aug 24 '17 at 18:18
  • We are only looking at a piece of the entire sketch. Based on just the code provided, the extra else if's are not needed. I am assuming he has added some type of delay that only runs this code every 30 seconds or perhaps every minute. Do you think this code is in the loop() with no form of delay? I hope not. The problem here is I've only been a member of this forum for a week and I'm eager to help as many people as I can. The mistake I made was answering a question without seeing the entire sketch. I won't make that mistake again. – VE7JRO Aug 24 '17 at 19:31
  • I don't mean the removal of the extra if clauses - that is fine. It's the removal of the last one and replacing it with else. Before there was a dead zone in the wind speed between 2 and 4, and in the rain reading between 650 and 900. You have lost that completely. – Majenko Aug 24 '17 at 19:37
  • I've asked rofimu for clarification about his question. The first and last paragraphs contradict themselves. Hint: What if the wind is 3 km/h. Should the roof be open or closed (based on his written question, not the code he povided)? – VE7JRO Aug 24 '17 at 20:36
  • That is called a dead zone and stops the roof from opening and closing all the time when the wind or rain is borderline. – Majenko Aug 24 '17 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.