When are HIGHs, LOWs and LOWs, HIGHs...... relay control

I have a sliding gate that i have built (no pre existing electrical or mechanical hardware) for my drive way that consists of a gate, on rollers, in a track connected at either end to a winch with a nylon rope.
The winch rotates clockwise, pulling the gate open, or ccw pulling the gate closed,
which was carried out manually by push (and hold) direction buttons,
on my quest to automate and reinvent the wheel,
I have added prox switches to either end of the gates travel,
I would like to have a single push button open the gate, then have a single push close the gate
(come to think of it, a single push to open then a timed period before auto closing would be better)

So far I have 'Come up' with this (I use the term loosely, I am trying to 'learn' all i can about coding but the temptation to pinch a slice of code here and there when Im just trying to gt something to work in my minut amount of spare time is too much)

const int buttonPin = 2;
const int openstopPin = 4;
const int closestopPin = 5;
const int openrelayPin = 6;
const int closerelayPin = 7;

boolean gateState = false; //false = closed true = open

int buttonState = 0; 

volatile byte openrelayState = LOW;
volatile byte closerelayState = LOW;

void setup() {
  
  Serial.begin(9600);
  pinMode (buttonPin, INPUT);
  pinMode (closestopPin, INPUT);
  pinMode (openstopPin, INPUT);
  pinMode (openrelayPin, OUTPUT);
  pinMode (closerelayPin, OUTPUT);
 
}

void loop() {
 if (digitalRead(buttonPin) == HIGH && gateState == false) { //check to see if the button is pressed and the gate is closed
  digitalWrite(openrelayPin, HIGH);
  while(1){ //run motor until switch is tripped
    if (digitalRead(openstopPin) == LOW) { //check switch state
        gateState = true;
        digitalWrite(openrelayPin, LOW);
        
        break;
    }
        else digitalWrite(openrelayPin, HIGH);
      }
  }
  if (digitalRead(buttonPin) == HIGH && gateState == true) { //check to see if the button is pressed and the gate is open
    digitalWrite(closerelayPin, HIGH);
    while(1){
       if (digitalRead(closestopPin) == LOW) {
        gateState = false;
        digitalWrite(closerelayPin, LOW);
        break;
       }
        else digitalWrite(closerelayPin, HIGH);
       }
    }
  }

Now this code 'works' as in, i have it mocked in the bench and when the button is pushed, with one 'stop' input ground, it will switch the relays until the ground is removed and applied to the other 'stop' input and vill operate in the opposite fashion with the button pressed and the stops swapped,
however both relays are energised all the time with the arduino turning them off to cause the polarity/direction change.

as soon as i power up the arduino, the relays are energised... even tho the D/OUTPUT is LOW..... i test this with an LED circuit tester.....

before i rant anyfurther could someone take a look and advise me if im missing something very simple...
thanks for your time

Post a link to the datasheet for your relay and also make a simple pencil drawing showing how everything is connected and post a photo of the drawing. See this Simple Image Upload Guide

...R

When are HIGHs, LOWs and LOWs, HIGHs

Answer: never.

But maybe the question should be "when are Highs OFF and Lows ON?" where off and on refer to (eg) relays being de-energised or energised, or leds not glowing or glowing.

And the answer to that one is, "depends" :wink:

Say you have an led with the led anode (+ve side) on a digital pin, and the cathode (-ve side) to ground. When the pin is low, 0V, both sides of the led will be the same 0V and the led will not glow, ie be "off". Make the pin high, then the anode is 5V and the cathode is 0V, it will glow, be "on".

But suppose we put the led anode on the Arduino 5V pin, and the cathode to the digital pin. Then when the pin is high, 5V, both sides of the led will be 5V, it will not glow, and be "off" although our control pin is high. Make the pin low, 0V, and with the anode at 5V and the cathode at 0V, the led will glow, ie be "on", even though our control pin is low.

Relays on breakout boards have usually got some kind of transistor control, perhaps opto-isolation, and a high on the control pin can mean energised or de-energised depending on its wiring. Many are so-called "active low", meaning a low on the control is "on". Some makes have a jumper to allow you to set them active high or active low.

datasheet :slight_smile: :slight_smile: :slight_smile:
its from the local importer of quality chinese 'duino bits tbh,
after a simple modified 'button' example sketch, it appears this relay 'module' is switched via a LOW signal rather than a HIGH.......
So I modify the sketch (I have tried this previously but il do it again just to prove it to myself :slight_smile: )

const int buttonPin = 2;
const int openstopPin = 4;
const int closestopPin = 5;
const int openrelayPin = 6;
const int closerelayPin = 7;

boolean gateState = false; //false = closed true = open

int buttonState = 0; 

volatile byte openrelayState = HIGH;
volatile byte closerelayState = HIGH;

void setup() {
  
  Serial.begin(9600);
  pinMode (buttonPin, INPUT);
  pinMode (closestopPin, INPUT);
  pinMode (openstopPin, INPUT);
  pinMode (openrelayPin, OUTPUT);
  pinMode (closerelayPin, OUTPUT);
 
}

void loop() {
 if (digitalRead(buttonPin) == HIGH && gateState == false) { //check to see if the button is pressed and the gate is closed
  digitalWrite(openrelayPin, LOW);
  while(1){ //run motor until switch is tripped
    if (digitalRead(openstopPin) == LOW) { //check switch state
        gateState = true;
        digitalWrite(openrelayPin, HIGH);
        
        break;
    }
        else digitalWrite(openrelayPin, HIGH);
      }
  }
  if (digitalRead(buttonPin) == HIGH && gateState == true) { //check to see if the button is pressed and the gate is open
    digitalWrite(closerelayPin, LOW);
    while(1){
       if (digitalRead(closestopPin) == LOW) {
        gateState = false;
        digitalWrite(closerelayPin, HIGH);
        break;
       }
        else digitalWrite(closerelayPin, HIGH);
       }
    }
  }

Setting the volatile byte to HIGH (am I right doing this to set the relays off above all else?)

Ive inverted all the values so the digitalWrite(****relayPin, LOW) to energise the relays and vice-versa to de-energise them,

after uploading the result is much the same, the relays are energised imediately, pushing the button turns off one relay, swapping the stop switch grounds (gate travelling from one stop to the other) and pressing the button turns off the other relay but the relays do not reset to an energised state, no amount of button pushing or stop switch grounding makes them re-energise.....

working on the circuit sketch upload now....

Some makes have a jumper to allow you to set them active high or active low.

now we may be getting somewhere, there is a jumper between 'JD-VCC' and 'VCC' with 'GND' left 'unjumped' this may be my issue.....

Joe_duino:
now we may be getting somewhere, there is a jumper between 'JD-VCC' and 'VCC' with 'GND' left 'unjumped' this may be my issue.....

No, that's a different thing. That's to allow you to provide an external power supply to operate the relay, rather than powering it (as distinct from controlling it) from the Arduino 5V.

If you provide power from the Arduino, leave the jumper on, and apply 5V from Arduino to the Vcc pin, and join the Arduino gnd and relay board gnd. (The presence of that common ground thwarts the opto-isolation, though.)

If you provide external power, take the jumper off, apply the external power to the JdVcc pin, Arduino 5V to Vcc, but DO NOT connect the Arduino gnd to the relay gnd.

On those boards, the opto isolator has an led inside, and that's what controls the relay. To energise the relay, the led must be on, but it's across the Arduino 5V (Vcc) and the relay board INx pin on an Arduino digital pin. So the led is on, and the relay energised, when the digital pin is low.

ah that makes more sense regarding the markings.....

Joe_duino:
ah that makes more sense regarding the markings.....

The ones I've seen that have the choice between active high and low, were marked "hi" and "lo" or some such.

The JD-Vcc markings seem "standard" for those that can have external power and opto-isolation.

wow that image is bad, ill have another go in the morning, its past late already.....

Joe_duino:
datasheet :slight_smile: :slight_smile: :slight_smile:
its from the local importer of quality chinese 'duino bits tbh,

So how about a link to the website where you bought it or even a photo of it so we can have some idea what you are trying to work with.

There are thousands of different relays on the market.

...R

I think you'll have a much easier time if you define a variable for the open relay state and the closed relay state. That will make your code more readable and less prone to bugs.

It appears that you made an attempt at this:

Joe_duino:

volatile byte openrelayState = HIGH;

volatile byte closerelayState = HIGH;

but you failed to correctly define them (obviously, the open state and the closed state can't both be HIGH) and you never bother to use the variables in the rest of your code!

pert:
(obviously, the open state and the closed state can't both be HIGH) and you never bother to use the variables in the rest of your code!

I think I see what your saying, however the two outputs are 'open' relay and 'close' relay,
not 'open and closed' or 'on and off', so both should be in a HIGH or LOW state simultaneously which causes the motor to not operate.

found the website for the relays, sorry I tend to just buy stuff then it all goes into a big drawer full of bits :smiley:

They are obviously driven by a LOW signal, making this adjustment to code certainly doesnt help me out tho....

OK, then create some new variables like relayOnState and relayOffState.

Which do you think is easier to understand and maintain?

digitalWrite(openrelayPin, LOW);

or

digitalWrite(openrelayPin, relayOnState);

In the first code, LOW is essentially a "magic number". It has not real meaning unless you happen to have some extra knowledge about the system (i.e. the relay is active LOW).

pert:
OK, then create some new variables like relayOnState and relayOffState.

Which do you think is easier to understand and maintain?

digitalWrite(openrelayPin, LOW);

or

digitalWrite(openrelayPin, relayOnState);

In the first code, LOW is essentially a "magic number". It has not real meaning unless you happen to have some extra knowledge about the system (i.e. the relay is active LOW).

I think i understand what your getting at with regards to stating within the sketch what the state of the relay, in the on position, for simplification, rather than relying on the state of LOW or HIGH.
Doesnt that sort of just add words to the sketch tho, can't we just rely on the LOW being ground and HIGH being anything over 1.5v...

I tried adding the variables

int relayOnState = 0;
int relayOffState = 1;

and then referencing

digitalWrite(openrelayPin, relayOnState)

that didnt work as intended

I guess Im somehow confusing the situation, maybe i rewrite the sketch in a more simple fashion and expand from there...

Joe_duino:
Doesnt that sort of just add words to the sketch tho

Why do you think that's a problem? Comments "add words", but when you are trying to understand someone's code or even your own after you haven't looked at it for a while, you'll be very grateful for those extra words. The same goes for descriptive variable names. These can be even better than a comment because they make the code be self-documenting.

Using variables like this also make adjusting the parameters of your sketch very easy. With the variables, you could adapt your sketch to an active HIGH relay module by simply changing two lines of code. With your code as it is, you would need to go through the entire sketch line by line and change every time you digitalWrite() to the relay pins. If you miss a single one, that will be a nasty bug. You might not think this is such a big deal since your code is currently very short and simple, but you need to develop good habits now so that when you are ready to work on a more advanced project, it doesn't turn into a nightmare.

Joe_duino:
can't we just rely on the LOW being ground and HIGH being anything over 1.5v.

That's irrelevant. LOW and HIGH are just states. But what do those states actually do? Some devices are active LOW, some are active HIGH. You shouldn't be required to remember which it is, or add a comment to every digitalWrite() statement.

It's a very frequent problem for beginners to assume that HIGH always means on, even though this is more often not the case. Defining variables for these states as I have recommended prevents that issue.

Joe_duino:
I tried adding the variables

int relayOnState = 0;
int relayOffState = 1;

Why would you use 0 and 1 instead of the much more helpful LOW and HIGH?

Joe_duino:
that didnt work as intended

That's not a useful description of the problem.

first off, Pert - thank you so much for your time.

The same goes for descriptive variable names. These can be even better than a comment because they make the code be self-documenting.

this makes a lot of sense now you've stated the reasoning :smiley:

Why would you use 0 and 1 instead of the much more helpful LOW and HIGH?

honestly I just assumed the computer would 'like' binary over words, was grasping at straws tbh

That's not a useful description of the problem.

understood, it was just getting very 'wordy' trying to state what i was doing, intending to happen and what was happening unintentionally

I'm going to try restructure my sketch with the suggestions you've made, thanks again

Well, I have have made adjustments.....

const int buttonPin = 2;
const int gateOpen = 4;
const int gateClosed = 5;
const int openrelayPin = 6;
const int closerelayPin = 7;

boolean gateState = false; //false = closed true = open

int buttonState = LOW;
int relayOnState = LOW;
int relayOffState = HIGH;

void setup() {
pinMode (buttonPin, INPUT);
pinMode (gateClosed, INPUT);
pinMode (gateOpen, INPUT);
pinMode (openrelayPin, OUTPUT);
pinMode (closerelayPin, OUTPUT);

}

void loop() {
if (buttonState = digitalRead(buttonPin) == HIGH && gateState == false) { //check to see if the button is pressed and the gate is closed
digitalWrite(openrelayPin, relayOnState);
while (1) { //run motor until switch is tripped
if (digitalRead(gateOpen) == LOW) { //check switch state
gateState = true;
digitalWrite(openrelayPin, relayOffState);

break;
}
else digitalWrite(openrelayPin, relayOffState);
}
}
if (buttonState = digitalRead(buttonPin) == HIGH && gateState == true) { //check to see if the button is pressed and the gate is open
digitalWrite(closerelayPin, relayOnState);
while (1) {
if (digitalRead(gateClosed) == LOW) {
gateState = false;
digitalWrite(closerelayPin, relayOffState);
break;
}
else digitalWrite(closerelayPin, relayOffState);
}
}
}

However the problem persists....
When the sketch is loaded the relays are energised, pushing the button with the 'gate' closed, turns off one relay, 'opening' the gate and pushing the button again turns off the other relay. they do not turn back on.
Can I use the serial monitor to serial.print the inouts/outputs so I can see what is going in and out of the arduino?

cheers