Relay Control Problems

Hello guys,

a new day and a new Problem...

I use a Relay to controll a suction cup.
My problem is that if i change the high/low relay time the changes will not make.

How i can fix the code that i can set deifferent Relay On/Off times ?

#include <Servo.h>

int in1 =7;

Servo servoLeft;          // Definiere linken Servo
Servo servoRight;         // Definiere rechten Servo

void setup() { 
  servoLeft.attach(44);  // Setzt linken Servo auf digital pin 44
  servoRight.attach(22);  // Setzt rechten Servo auf digital pin 22
  
  pinMode(in1, OUTPUT);
  digitalWrite(in1, HIGH);
  
} 

void loop() {            // Loop für den Bewegungstest

  digitalWrite(in1, LOW);
  delay(3000);
  digitalWrite(in1, HIGH);
  delay(3000);
  
  forward();             // Bsp: Bewege Vorwärts
  delay(2000);           // Warte 2000 millisekunden (2 Sek)
  reverse();
  delay(2000);
  turnRight();
  delay(2000);
  turnLeft();
  delay(2000);
  stopRobot();
  delay(2000);
}

// Bewegungs Routine für Vorwärts, Rückwärts, Drehungen und STOP
void forward() {
  servoLeft.write(0);
  servoRight.write(180);
}

void reverse() {
  servoLeft.write(180);
  servoRight.write(0);
}

void turnRight() {
  servoLeft.write(180);
  servoRight.write(180);
}
void turnLeft() {
  servoLeft.write(0);
  servoRight.write(0);
}

void stopRobot() {
  servoLeft.write(90);
  servoRight.write(90);
}

Thanks and regards

How i can fix the code that i can set deifferent Relay On/Off times ?

Do you want the user to be able to input the on/off times ?

its a pick and place robot arm. The On/Off time should hard coded. Users dont interact with the robot.

The On/Off time should hard coded

If the in1 pin is controlling the relay then just change the delay() values in this code

  digitalWrite(in1, LOW);
  delay(3000);
  digitalWrite(in1, HIGH);
  delay(3000);

If that is not the correct pin for the relay then please identify it

UKHeliBob:

  digitalWrite(in1, LOW);

delay(3000);
 digitalWrite(in1, HIGH);
 delay(3000);

Yes thats the Pin and thats my problem. Normally the code should run 3sec ON and 3sec Off. But the Relay make 1sec off and 10sec ON and i dont know why.

The 10 second delay is being caused by the delay()s between calls to the other functions.

If you want the relay to turn on and off independently of the other timing then you will need to use millis() for timing throughout the program because delay() stops everything while it executes

See Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.

The relay on/off is effectively what the BlinkWithoutDelay example does just with different timing periods for the on and off. The rest of the code would lend itself to a "state machine" with the call to each function and its associated delay (controlled using millis()) as each state.

Thanks for the links and the tip with (controlled using millis())
Will change the code and test it.

UKHeliBob:
The 10 second delay is being caused by the delay()s between calls to the other functions.

If you want the relay to turn on and off independently of the other timing then you will need to use millis() for timing throughout the program because delay() stops everything while it executes

See Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.

The relay on/off is effectively what the BlinkWithoutDelay example does just with different timing periods for the on and off. The rest of the code would lend itself to a "state machine" with the call to each function and its associated delay (controlled using millis()) as each state.

Have i understand the guide korrect ?

Only put inside:

currentMillis = millis();

and change the delay to millis ?

Have i understand the guide korrect ?

If you think you can just change to call to delay() to a call to millis(), then, no, you have NOT understood the guide(s) correctly.

PaulS:
If you think you can just change to call to delay() to a call to millis(), then, no, you have NOT understood the guide(s) correctly.

hmmm ok, that was what i thought. I translatre it in german because my english isn`t perfect.
What i must include into the code that millis work ?

What i must include into the code that millis work ?

You must change the way that the code works completely

(1) save the current time from millis() when a start action occurs such as turning on the relay
(2) each time through loop() check whether the current value of millis() minus the start time is greater than the required period.
(3) if so the start the next action, if any, save the current time and carry on until the new period ends
(4) if not then carry on round loop() until the period ends.

There are examples of doing this in the Beginners Guide to using millis() at the top of the forum page

I try to include the millis in the main sketch. Looks it ok ? I have at the moment not my arduino to debug....

#include <Servo.h>


currentMillis = millis();
unsigned long startMillis;  			//some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 1000;  	//the value is a number of milliseconds
const byte in = 7;   




Servo servoLeft;          			// Definiere linken Servo
Servo servoRight;      				// Definiere rechten Servo

void setup() { 
  servoLeft.attach(44);  			// Setzt linken Servo auf digital pin 44
  servoRight.attach(22);  			// Setzt rechten Servo auf digital pin 22
  
  pinMode(in1, OUTPUT);
  startMillis = millis();  				//initial start time
  
} 

void loop() 
{            						// Loop für den Bewegungstest
  currentMillis = millis();  		//get the current "time" (actually the number of milliseconds since the program started)
  if (currentMillis - startMillis >= period)  	//test whether the period has elapsed
  {
    digitalWrite(in1, !digitalRead(in1));  //if so, change the state of the Relays.  Uses a neat trick to change the state
    startMillis = currentMillis;  			//IMPORTANT to save the start time of the current Relays.
  }
 
  
  forward();             				// Bsp: Bewege Vorwärts
  delay(2000);           				// Warte 2000 millisekunden (2 Sek)
  reverse();
  delay(2000);
  turnRight();
  delay(2000);
  turnLeft();
  delay(2000);
  stopRobot();
  delay(2000);
}

				// Bewegungs Routine für Vorwärts, Rückwärts, Drehungen und STOP
void forward() {
  servoLeft.write(0);
  servoRight.write(180);
}

void reverse() {
  servoLeft.write(180);
  servoRight.write(0);
}

void turnRight() {
  servoLeft.write(180);
  servoRight.write(180);
}
void turnLeft() {
  servoLeft.write(0);
  servoRight.write(0);
}

void stopRobot() {
  servoLeft.write(90);
  servoRight.write(90);
}

Must these delays change to millis too ?

forward();             				// Bsp: Bewege Vorwärts
  delay(2000);           				// Warte 2000 millisekunden (2 Sek)
  reverse();
  delay(2000);
  turnRight();
  delay(2000);
  turnLeft();
  delay(2000);
  stopRobot();
  delay(2000);

The code to turn the relay on and off looks OK apart from the fact that currentMillis is declared twice (once wrongly as it happens) and that you have used the wrong name for the relay pin variable either in the declaration or when using it.

Must these delays change to millis too ?

Yes, otherwise the program will halt during each delay()

Note what I said in a previous reply

The rest of the code would lend itself to a "state machine" with the call to each function and its associated delay (controlled using millis()) as each state.

after compiling i become this error:

too many arguments to function 'long unsigned int millis()'

#include <Servo.h>



unsigned long startMillis;  					//Variablen die überall im Programm verfügbar sind
unsigned long currentMillis;
const unsigned long period = 1000;  			//Wert in Millisekunden
const byte in1 = 7;   




Servo servoLeft;          						//Definiere linken Servo
Servo servoRight;         						//Definiere rechten Servo


void setup() { 
  servoLeft.attach(44);  						//Setzt linken Servo auf digital pin 44
  servoRight.attach(22);  						//Setzt rechten Servo auf digital pin 22
  servoDown.attach(37);
  
  pinMode(in1, OUTPUT);
  startMillis = millis();  						//iniziere Start Zeit
  
} 

void loop() 
{            									//Loop für den Bewegungstest
  currentMillis = millis();  					//erhalte die aktuelle "Zeit" (die aktuelle Anzahl der Millisekunden seitdem das Programm gestartet ist)
  if (currentMillis - startMillis >= period)  	//Prüfung ob der Zeitraum abgelaufen ist
  {
    digitalWrite(in1, !digitalRead(in1));  		//Wenn Zeitraum abgelaufen ist, wird Relais geschaltet   
    startMillis = currentMillis;  				//WICHTIG umask die Startzeit destroy aktuellen Relais zu speichern
  }
 
  
  forward();             						//Bsp: Bewege Vorwärts
  millis(2000);           						//Zeit in Millisekunden (2 Sek) die benötigt wird um den Servo zu drehen
  reverse();
  millis(2000);
  turnRight();
  millis(2000);
  turnLeft();
  millis(2000);
  stopRobot();
  millis(2000);
}

												//Bewegungs Routine für Vorwärts, Rückwärts, Drehungen und STOP
void forward() {
  servoLeft.write(0);
  servoRight.write(180);
  servoDown.write(0);
}

void reverse() {
  servoLeft.write(180);
  servoRight.write(0);
  servoDown.write(0);
}

void turnRight() {
  servoLeft.write(180);
  servoRight.write(180);
  servoDown.write(0);
}
void turnLeft() {
  servoLeft.write(0);
  servoRight.write(0);
  servoDown.write(0);
}

void stopRobot() {
  servoLeft.write(90);
  servoRight.write(90);
  servoDown.write(0);
}

Please post the whole error message

too many arguments to function 'long unsigned int millis()'

That phrase does not appear in your code, but there other problems that prevent it compiling.

As everyone said - if you want two independent things happening (a relay and a servo arm), then the sketch needs to be rewritten as a state machine.

The loop() function should always exit quickly - within microseconds. This means that each time it runs, it has to ask and answer the question "is there anything that I need to do right now?". To do this, the sketch has global variables that hold what "step" the process is in, and the time ( using millis() ) at which the current step began.

If you have two independent processes, then each will have its own little cluster of global variables to manage that process.

Like this:

#include <Servo.h>

int in1 = 7;

Servo servoLeft;          // Definiere linken Servo
Servo servoRight;         // Definiere rechten Servo


// relay operations
byte relayState;
uint32_t relayMs;

// pick and place operations
enum PNPState {
  START,
  FWDREV_FWD,
  FWDREV_REV,
  RIGHTLEFT_RIGHT,
  RIGHTLEFT_LEFT,
  STOPPED
} pnpState;
uint32_t pnpMs;

void setup() {
  servoLeft.attach(44);  // Setzt linken Servo auf digital pin 44
  servoRight.attach(22);  // Setzt rechten Servo auf digital pin 22

  pinMode(in1, OUTPUT);
  digitalWrite(in1, HIGH);

  relayState = LOW;
  digitalWrite(in1, relayState);
  relayMs = millis();

  pnpState = START;
  pnpMs = millis();

}

void loop() {
  handleRelay();
  handlePnP();
}

void handleRelay() {
  if (millis() - relayMs > 3000) {
    relayState = (relayState == LOW ? HIGH : LOW);
    digitalWrite(in1, relayState);
    relayMs = millis();
  }
}

void handlePnP() {            // Loop für den Bewegungstest

  switch (pnpState) {
    case START:
      forward();
      pnpMs = millis();
      pnpState = FWDREV_FWD;
      break;

    case FWDREV_FWD:
      if (millis() - pnpMs >= 2000) {
        reverse();
        pnpMs = millis();
        pnpState = FWDREV_REV;
      }
      break;

    case FWDREV_REV:
      if (millis() - pnpMs >= 2000) {
        turnRight();
        pnpMs = millis();
        pnpState = RIGHTLEFT_RIGHT;
      }
      break;

    case RIGHTLEFT_RIGHT:
      if (millis() - pnpMs >= 2000) {
        turnLeft();
        pnpMs = millis();
        pnpState = RIGHTLEFT_LEFT;
      }
      break;

    case RIGHTLEFT_LEFT:
      if (millis() - pnpMs >= 2000) {
        stopRobot();
        pnpMs = millis();
        pnpState = STOPPED;
      }
      break;

    case STOPPED:
      if (millis() - pnpMs >= 2000) {
        forward();
        pnpMs = millis();
        pnpState = FWDREV_FWD;
      }
      break;
  }
}

// Bewegungs Routine für Vorwärts, Rückwärts, Drehungen und STOP
void forward() {
  servoLeft.write(0);
  servoRight.write(180);
}

void reverse() {
  servoLeft.write(180);
  servoRight.write(0);
}

void turnRight() {
  servoLeft.write(180);
  servoRight.write(180);
}
void turnLeft() {
  servoLeft.write(0);
  servoRight.write(0);
}

void stopRobot() {
  servoLeft.write(90);
  servoRight.write(90);
}

error code

Arduino: 1.8.5 (Windows 7), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

C:\Users\ws-praesentation\Desktop\Servo_millis\Servo_millis.ino: In function 'void loop()':

Servo_millis:38: error: too many arguments to function 'long unsigned int millis()'

   millis(2000);                 //Zeit in Millisekunden (2 Sek) die benötigt wird um den Servo zu drehen

              ^

In file included from sketch\Servo_millis.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:140:15: note: declared here

 unsigned long millis(void);

               ^

Servo_millis:40: error: too many arguments to function 'long unsigned int millis()'

   millis(2000);

              ^

In file included from sketch\Servo_millis.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:140:15: note: declared here

 unsigned long millis(void);

               ^

Servo_millis:42: error: too many arguments to function 'long unsigned int millis()'

   millis(2000);

              ^

In file included from sketch\Servo_millis.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:140:15: note: declared here

 unsigned long millis(void);

               ^

Servo_millis:44: error: too many arguments to function 'long unsigned int millis()'

   millis(2000);

              ^

In file included from sketch\Servo_millis.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:140:15: note: declared here

 unsigned long millis(void);

               ^

Servo_millis:46: error: too many arguments to function 'long unsigned int millis()'

   millis(2000);

              ^

In file included from sketch\Servo_millis.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:140:15: note: declared here

 unsigned long millis(void);

               ^

exit status 1
too many arguments to function 'long unsigned int millis()'
  millis(2000);                       //Zeit in Millisekunden (2 Sek) die benötigt wird um den Servo zu drehen

Check the syntax of the millis() function.

millis() returns a value, it does not accept values. You cannot simply use it in place of delay()

PaulMurrayCbr:
As everyone said - if you want two independent things happening (a relay and a servo arm), then the sketch needs to be rewritten as a state machine.

The loop() function should always exit quickly - within microseconds. This means that each time it runs, it has to ask and answer the question "is there anything that I need to do right now?". To do this, the sketch has global variables that hold what "step" the process is in, and the time ( using millis() ) at which the current step began.

If you have two independent processes, then each will have its own little cluster of global variables to manage that process.

Like this:

#include <Servo.h>

int in1 = 7;

Servo servoLeft;          // Definiere linken Servo
Servo servoRight;        // Definiere rechten Servo

// relay operations
byte relayState;
uint32_t relayMs;

// pick and place operations
enum PNPState {
  START,
  FWDREV_FWD,
  FWDREV_REV,
  RIGHTLEFT_RIGHT,
  RIGHTLEFT_LEFT,
  STOPPED
} pnpState;
uint32_t pnpMs;

void setup() {
  servoLeft.attach(44);  // Setzt linken Servo auf digital pin 44
  servoRight.attach(22);  // Setzt rechten Servo auf digital pin 22

pinMode(in1, OUTPUT);
  digitalWrite(in1, HIGH);

relayState = LOW;
  digitalWrite(in1, relayState);
  relayMs = millis();

pnpState = START;
  pnpMs = millis();

}

void loop() {
  handleRelay();
  handlePnP();
}

void handleRelay() {
  if (millis() - relayMs > 3000) {
    relayState = (relayState == LOW ? HIGH : LOW);
    digitalWrite(in1, relayState);
    relayMs = millis();
  }
}

void handlePnP() {            // Loop für den Bewegungstest

switch (pnpState) {
    case START:
      forward();
      pnpMs = millis();
      pnpState = FWDREV_FWD;
      break;

case FWDREV_FWD:
      if (millis() - pnpMs >= 2000) {
        reverse();
        pnpMs = millis();
        pnpState = FWDREV_REV;
      }
      break;

case FWDREV_REV:
      if (millis() - pnpMs >= 2000) {
        turnRight();
        pnpMs = millis();
        pnpState = RIGHTLEFT_RIGHT;
      }
      break;

case RIGHTLEFT_RIGHT:
      if (millis() - pnpMs >= 2000) {
        turnLeft();
        pnpMs = millis();
        pnpState = RIGHTLEFT_LEFT;
      }
      break;

case RIGHTLEFT_LEFT:
      if (millis() - pnpMs >= 2000) {
        stopRobot();
        pnpMs = millis();
        pnpState = STOPPED;
      }
      break;

case STOPPED:
      if (millis() - pnpMs >= 2000) {
        forward();
        pnpMs = millis();
        pnpState = FWDREV_FWD;
      }
      break;
  }
}

// Bewegungs Routine für Vorwärts, Rückwärts, Drehungen und STOP
void forward() {
  servoLeft.write(0);
  servoRight.write(180);
}

void reverse() {
  servoLeft.write(180);
  servoRight.write(0);
}

void turnRight() {
  servoLeft.write(180);
  servoRight.write(180);
}
void turnLeft() {
  servoLeft.write(0);
  servoRight.write(0);
}

void stopRobot() {
  servoLeft.write(90);
  servoRight.write(90);
}

I taste your code, and the servo turn to left and right don`t work for me. I include a 3rd Servo for the turn to left and right.

#include <Servo.h>

int in1 = 7;

Servo servoLeft;          // Definiere linken Servo
Servo servoRight;         // Definiere rechten Servo
Servo servoDown;          // Definiere unteren Servo

// relay operations
byte relayState;
uint32_t relayMs;

// pick and place operations
enum PNPState {
  START,
  FWDREV_FWD,
  FWDREV_REV,
  RIGHTLEFT_RIGHT,
  RIGHTLEFT_LEFT,
  STOPPED
} pnpState;
uint32_t pnpMs;

void setup() {
  servoLeft.attach(44);   // Setzt linken Servo auf digital pin 44
  servoRight.attach(22);  // Setzt rechten Servo auf digital pin 22
  servoDown.attach(38);   // Setzt unteren Servo auf digital pin 38
  
  pinMode(in1, OUTPUT);
  digitalWrite(in1, HIGH);

  relayState = LOW;
  digitalWrite(in1, relayState);
  relayMs = millis();

  pnpState = START;
  pnpMs = millis();

}

void loop() {
  handleRelay();
  handlePnP();
}

void handleRelay() {
  if (millis() - relayMs > 3000) {
    relayState = (relayState == LOW ? HIGH : LOW);
    digitalWrite(in1, relayState);
    relayMs = millis();
  }
}

void handlePnP() {            // Loop für den Bewegungstest

  switch (pnpState) {
    case START:
      forward();
      pnpMs = millis();
      pnpState = FWDREV_FWD;
      break;

    case FWDREV_FWD:
      if (millis() - pnpMs >= 2000) {
        reverse();
        pnpMs = millis();
        pnpState = FWDREV_REV;
      }
      break;

    case FWDREV_REV:
      if (millis() - pnpMs >= 2000) {
        turnRight();
        pnpMs = millis();
        pnpState = RIGHTLEFT_RIGHT;
      }
      break;

    case RIGHTLEFT_RIGHT:
      if (millis() - pnpMs >= 2000) {
        turnLeft();
        pnpMs = millis();
        pnpState = RIGHTLEFT_LEFT;
      }
      break;

    case RIGHTLEFT_LEFT:
      if (millis() - pnpMs >= 2000) {
        stopRobot();
        pnpMs = millis();
        pnpState = STOPPED;
      }
      break;

    case STOPPED:
      if (millis() - pnpMs >= 2000) {
        forward();
        pnpMs = millis();
        pnpState = FWDREV_FWD;
      }
      break;
  }
}

// Bewegungs Routine für Vorwärts, Rückwärts, Drehungen und STOP
void forward() {
  servoLeft.write(0);
  servoRight.write(180);
  servoDown.write(0);
}

void reverse() {
  servoLeft.write(180);
  servoRight.write(0);
  servoDown.write(0);
}

void turnRight() {
  servoLeft.write(180);
  servoRight.write(180);
  servoDown.write(0);
}
void turnLeft() {
  servoLeft.write(0);
  servoRight.write(0);
  servoDown.write(0);
}

void stopRobot() {
  servoLeft.write(90);
  servoRight.write(90);
  servoDown.write(0);
}

UKHeliBob:

  millis(2000);                       //Zeit in Millisekunden (2 Sek) die benötigt wird um den Servo zu drehen

Check the syntax of the millis() function.

millis() returns a value, it does not accept values. You cannot simply use it in place of delay()

Dont understand the syntax problem.
the syntax looks for me the same like in this tutorial...