millis and while loop

I want to turn on and off a relay in intervals when a PIR sensor is HIGH. The relay should be turned off when the sensor is LOW.

I use this code and it seems to work but the Serial.monitor is updating slow when the code runs.

//// SENSOR 1 och RELAY1(pinout8):
int sensorState1 = digitalRead(sensor1);
int interval = 1000;
int interval2 = 2000;

   if (sensorState1 == HIGH) {
     unsigned long currentTime = millis();
   digitalWrite(relay1, LOW); // Turns the relay ON for 1 second. 
   while(millis() < currentTime + interval){
   digitalWrite(relay1, HIGH);  // Turns the relay OFF 
   while(millis() < currentTime + interval2){    //for 1 second. 

     } else {
      digitalWrite(relay1, HIGH);

How is the proper way to write this?

I would appreciate some advice since I am new to programming.


The proper way would be a state machine coded up with the behaviour and no calls to delay() nor
any busy-waiting such as your while loops.

The correct way to test for a time interval is this:

   while(millis() - currentTime < interval){

and not as you used:

   while(millis() < currentTime + interval){

Otherwise your code will misbehave when millis() wraps round. Always subtract two timestamps and
compare the result. The result of a subtraction is valid even when the counter wraps round.

You didn't post all your code. You could have replaced all that faulty millis() code with a simple delay(), but neither way will work for the reason stated above.

Look at the tutorials on the guide to posting on the top 3 stickies in this section. There are a few there called “doing Multiple things at the same time” etc. They will explain the use of millis correctly.

A while loop is blocking code. Like delay your code is stuck for an ‘eternity’ in uC time rather than looping every bit of a microsecond. Avoid all blocking code if you can.

See this code:

 * Created by
 * This example code is in the public domain
 * Tutorial page:

const int PIN_TO_SENSOR = 2;   // the pin that OUTPUT pin of sensor is connected to
int pinStateCurrent   = LOW; // current state of pin
int pinStatePrevious  = LOW; // previous state of pin
const unsigned long DELAY_TIME_MS = 30000; // 30000 miliseconds ~ 30 seconds
bool delayEnabled = false;
unsigned long delayStartTime;

void setup() {
  Serial.begin(9600);            // initialize serial
  pinMode(PIN_TO_SENSOR, INPUT); // set arduino pin to input mode to read value from OUTPUT pin of sensor

void loop() {
  pinStatePrevious = pinStateCurrent; // store state
  pinStateCurrent = digitalRead(PIN_TO_SENSOR);   // read new state

  if (pinStatePrevious == LOW && pinStateCurrent == HIGH) {   // pin state change: LOW -> HIGH
    Serial.println("Motion detected!");
    Serial.println("Turning on / activating");
    delayEnabled = false; // disable delay
    // TODO: turn on alarm, light or activate a device ... here
  if (pinStatePrevious == HIGH && pinStateCurrent == LOW) {   // pin state change: HIGH -> LOW
    Serial.println("Motion stopped!");
    delayEnabled = true; // enable delay
    delayStartTime = millis(); // set start time

  if (delayEnabled == true && (millis() - delayStartTime) >= DELAY_TIME_MS) {
    Serial.println("Turning off / deactivating");
    delayEnabled = false; // disable delay
    // TODO: turn off alarm, light or deactivate a device ... here

The above code is from this motion sensor tutorial

Thanks for all the helpful comments.
I will go through all your great code and comments tonight.