Managing output states depending on inputs

Hi
I am using an Uno and a Duinotech board with 4 relays.

I am using relays 1 and 2 as single pole double throw control for a motor to change the direction of the motor. CW and CCW.
Relay 3 supplies the power to Relays 1 and 2.
Relay 4 is in series with relay 3, and looks for an input from a second Arduino (Arduino2) to ensure that power is not supplied to relays 1 and 2 unless Arduino 2 is running its cycle. Arduino 2 controls a fertiliser pump. I would rather not try and incorporate this new code into the Arduino Code as that seems a step too far, and also I will not always need the Arduino 1 code in play when running Arduino 2.

The process steps for Arduino 1, as I want them, are as follows.
Relays 1 - 4 are LOW.
Arduino 2 starts and "Doser Control" of Arduino 1 is read as HIGH.
Relay 4 goes HIGH as Doser Control is HIGH, and will stay HIGH until Arduino 2 goes LOW.
As Relay4 is high, Relay 3 has a 5 second delay and then goes HIGH. As Relay 1 and 2 are Double throw, the motor attached to them runs clockwise. Relays 3 and 4 are both HIGH so current flows.
The motor runs a winch and the unit goes along a line until it reaches a magnet on the line and "Hall_1" goes HIGH for a moment as the Hall Sensor detects the magnet.
As Hall_1 went HIGH, Relays 1 and 2 now go HIGH. Relay 3 goes LOW for 5 seconds so that the winch motor is not thrown from one direction straight into the opposite direction. Relay 3 goes HIGH after the 5 seconds and the motor runs Counter clockwise until it reaches the magnet at the other end and Hall_1 goes HIGH for a moment and Relays 1 and 2 go low. Relay 3 goes low for 5 seconds.

As long as 'Doser Control' is HIGH then this process of going back and forth continues. When Doser Control is LOW I want all Relays to be LOW.

So that explains how I want it to be.
Now to explain how it is at the moment.

At the moment the code I have is that when started, all relays are LOW, and then after the 5 second debounce time (StateChangeDelay) then Relay 3 goes HIGH. This means that even when 'Doser Control' is LOW, Relay 3 goes HIGH, and at some point it will wear out or just waste power sitting HIGH when it doesn't need to be on.

So my question is, what do I need to do, to get relay 3 to stay LOW when 'Doser Control' is LOW?
Then when Doser control goes HIGH, relay 3 comes on and works as it currently does.

I should also note that I realise that relay 4 is kind of unnecessary, as Relay 3 should be used on its own if I can get it to stay off when Doser Control is LOW, but that was too much for my brain to manage.

I have pasted my code below.

CODE:

// this constant won't change:
const int Hall_1Pin = 2;     
const int relayIN1 = 3;
const int relayIN2 = 4;
const int relayIN3 = 5;
const int relayIN4 = 6;   
const int DoserControl = 8;        

// Variables will change:
int DoserState;     //Variable for current Doser state
int relay1State = LOW;      //Variable for current Relay state
int relay2State = LOW;      //Variable for current Relay state
int relay3State = LOW;      //Variable for current Relay state
int relay4State = LOW;      //Variable for current Relay state
int Hall_1State;        //Variable for current Hall reading
int lastHall_1State = LOW; //Variable for last known Hall1 reading
int lastDoserState = LOW; //Variable for last known Doser reading

unsigned long lastDebounceTime = 0; //last time the pin was toggled, used to keep track of time
unsigned long debounceDelay = 50;   //the debounce time which user sets prior to run
unsigned long StateChangeTime = 0;  // last time the pin was toggled, used to keep track of time
unsigned long StateChangeDelay = 5000; //the delay before turning on relay 3
unsigned long lastDoserTime = 0; //last time the pin was toggled, used to keep track of time
unsigned long debounceDoserDelay = 50;   //the debounce time which user sets prior to run

void setup() {
 pinMode(relayIN1, OUTPUT);
 pinMode(relayIN2, OUTPUT);
 pinMode(relayIN3, OUTPUT);
 pinMode(relayIN4, OUTPUT);
 pinMode(Hall_1Pin, INPUT);
 pinMode(DoserControl, INPUT);   
 digitalWrite(relayIN1, relay1State);
 digitalWrite(relayIN2, relay2State); 
 digitalWrite(relayIN3, relay3State);
 digitalWrite(relayIN4, relay4State);
 
}

void loop(){

 int reading3 = digitalRead(DoserControl);  //Is the doser on?
 if (reading3 != lastDoserState)  {
   lastDoserTime = millis();
   
 }
 if ((millis()- lastDoserTime) > debounceDoserDelay) {
   if (reading3 != DoserState) {
     DoserState = reading3;
   if (DoserState == HIGH) {
     relay1State = relay1State;
     relay2State = relay2State;
     relay3State = relay3State;
     relay4State = HIGH;
     
     }
   }
 }
     
else {
 
   relay4State = LOW;
   relay3State = LOW;
       
   
}
 digitalWrite (relayIN3, relay3State);
 digitalWrite (relayIN4, relay4State);
 
 
//save the reading. next time through the loop the state of the reading will be known as the lastDoserState
 lastDoserState = reading3;
 
//read the Hall pin, if pressed will be high, if not pressed will be low
 int reading1 = digitalRead(Hall_1Pin);
 //in the case that the reading is not equal to the last state set the last debounce time to current millis time
 if (reading1 != lastHall_1State)  {
   lastDebounceTime = millis();
   StateChangeTime = millis(); 
 }
 //check the difference between current time and last registered button press time, if it's greater than user defined delay then change the LED state as it's not a bounce
 if ((millis()-lastDebounceTime) > debounceDelay) {
   if (reading1 != Hall_1State) {
     Hall_1State = reading1;
   if (Hall_1State == LOW) {
     
     relay1State = !relay1State;
     relay2State = !relay2State;
     relay3State = LOW;
    
     }
   }
 }
 if ((millis()-StateChangeTime) > StateChangeDelay) {
     relay3State = HIGH;
    
 }
    
   digitalWrite(relayIN1, relay1State); 
   digitalWrite(relayIN2, relay2State);  
   digitalWrite(relayIN3, relay3State);   
   
 
 //save the reading. next time through the loop the state of the reading will be known as the lastHall_1State
 lastHall_1State = reading1;
}

It would be best to draw a schematic and show us.

This is a schematic of the system. I couldn't find a 4 relay board so I have added 4 relays with the line from each Arduino port to each relay.
The rest should make sense I hope.

Image from Reply #2 so we don't have to download it. See this Simple Image Guide

...R

BigKiwi:
At the moment the code I have is that when started, all relays are LOW, and then after the 5 second debounce time (StateChangeDelay) then Relay 3 goes HIGH. This means that even when 'Doser Control' is LOW, Relay 3 goes HIGH, and at some point it will wear out or just waste power sitting HIGH when it doesn't need to be on.

I have not looked at your code. It is too long for me to study quickly without copying to a text editor.

To make it easy for people to help you please modify your post and use the code button </> so your code looks like this and is easy to copy to a text editor. See How to use the Forum

It seems to me you only need the relays that directly control the motor. All the others are just providing logic functions that could be handled by program code. And I suspect if you think about the project from that perspective you will find it easier to figure out an answer to your questions.

Think about it like this ...

What are the conditions that must be true in order to activate the motor in a Forward direction?
And in the Reverse direction?

The code will probably be something like

if (conditionA is true) {
   if (conditionB is true) {
      if (direction == 'F') {
         // set relays for FWD
      }
      else {
         // set relays for REV
      }
    }
    else {
        // set relays for OFF
    }
  }
}

And, when you think of it like that it may be a simple matter to add this code to Arduino2 and dispense with Arduino1 altogether.

...R

Hi Robin,
Thanks for your comments.
I have fixed the code as suggested. I missed that bit in the intro notes. :frowning:

I do not see how I can get to where you are suggesting with two relays. If the two relays are LOW and NC then the motor is running one way. If they both go HIGH then the motor runs in the other direction. I need another relay to cut the power don't I? I can't see how else to do it. :frowning:

The second Arduino is already using all but one ports so I am very loath to muck about with this. And as I mentioned, I won't always use this set up along with the other Arduino.

I realise it is a bit of an ask, but if you can provide a schematic or a link on how to change motor polarity with just two relays that would be very much appreciated. I looked for this as a solution first and could not get there. That is why I am where I am now.
Thanks

I do not see how I can get to where you are suggesting with two relays. If the two relays are LOW and NC then the motor is running one way. If they both go HIGH then the motor runs in the other direction. I need another relay to cut the power don't I? I can't see how else to do it. :frowning:

As you have two separate single-pole-double-throw relays you can wire the relays so that when neither relay is powered they connect both sides of the motor to GND. Then just energize one or other of the relays to give movement in the desired direction. This would not be possible if you had a single double-pole-double-throw relay.

If you don't have spare I/O pins on Arduino2 I can understand your predicament. Are you aware that the analogue pins can also be used as digital I/O pins?

...R

Hi
I am still totally stumped as to how you can change the polarity with two SPDT relays.
If both commons at NC are at GND and then you take one to HIGH I can't see how that gets me to what I need re the positive terminal.

I have attached a rough schematic (I am new at Fritzing) so have stuck with Paint at this stage.
Could you please add in the bits I am missing.
I really am not sure how it will work.


Thanks

This is what I have in mind

BigKiwiRelays.png

...R

In the SPDT relay diagram in Reply #9 it is assumed that both relays are triggered by the same signal. That is not necessary and if they are triggered separately there is no need for the ON/OFF relay.

...R

Just a representative drawing with SPDT vs DPDT.

Wiring can be modified as needed.

OP did say "Relay 3 supplies the power to Relays 1 and 2"
(in this schematic, K1 supplies power to K2 and K3)

larryd:
OP did say "Relay 3 supplies the power to Relays 1 and 2"
(in this schematic, K1 supplies power to K2 and K3)

I am trying to persuade him that that is not necessary.

...R

Robin2:
I am trying to persuade him that that is not necessary.

...R

My sch was a left over from other training.

Yes, when you are using SPST relays there is no need to use a relay for on/off

Smells like a tutorial maybe needed :wink:

Hi Robin and Larry
Thanks to both for the suggestions. I am feeling a bit 'stoopid' for not thinking about changing the motor from one of the contacts to the commons to get there.

More than one Tutorial is needed Larry. It is a case for 'a stitch in time.' As I am trying to get this done asap, tutorials feel like a luxury, but they are also likely to speed me up. :slight_smile:

So I have the code that works for that now.

Thanks.

Now I have to work out how to create the delays in the code to get the relays to change based on the Hall input, while keeping a 5 second pause with no power before they swap over. Once I get there then I have another delay to add before I then start working out how to add in overide with a blue tooth phone signal. Fun times.

Thanks for getting me this far.

Regards

BigKiwi

Remember, when you are timing things do not use delay().

Repeat after us, "delay() causes problems … "

LOL.
Yes, I learnt that early on. I should have said using millis to create timing opportunities!

:slight_smile: