Watchwinder motor to stop in 12 o'clock position - non blocking delay

My watchwinder, with 4 seperate 3 V DC (analogue) motors, controls the winding of 4 watches.
The build-in circuit powers the motors for 2 minutes and the motors rotate 20 turns. Then the motors stop for a certain periode varing from 6 minutes to 10 minutes.
Every watch has its specific turns per day (TPD), advised by the watch-manufacturer and the TPD (adjustable via touchscreen) determines this "stopping-periode".
For a Breitling Navitimer TPD is 800 and for a Rolex TPD is 650.
So a Breitling would rotate 40 times a day for a periode of 2 minutes (of 20 rotations) with 7 minutes interval (in 12 hours).
A Rolex would rotate 33 times a day for a periode of 2 minutes with 9,5 minutes interval.

But because of the different weight of the watches and the analoge motors the watches don't always stop in the same position after their 20 turns.
It looks rather chaotic and it is difficult to tell the time on each watch because some are upside down or in a random postion after the rotations.

Ideally the watches should always stop in the 12 o'clock position which I am trying to achive with an arduino and 4 IR sensors and 4 relais.

The IR sensor, positioned at the 12 o'clock position at the rear of the motorshaft, counts the number of rotations. After 19 rotations a relay is powered and switches OFF the motor
(when watch is in 12 oçlock position) for 10 seconds.
Than I know for sure the 2 minute cycle is completed, the relay can be "released" and the motor is waiting to be powered for its next cycle by the built-in circuit.

My sketch, copied and modified from IR object counter, works for one motor/watch with a "delay(10000)" but how do I use this sketch for 4 IR sensors and 4 relais.

I am aware of the fact that I cannot use the delay function for the 10 seconds to power the relay and power-off the motor.

Obviously I have been trying losts of suggestions regarding options for a "non blocking delay" on the forum but if you are more a "watch-guy" than a programmer it is complicated.
Anybody can help me out?

// Pin configuration
const int sensorPin0 = 2;  // Connect the infrared sensor's output pin to Arduino pin 2
const int sensorPin1 = 3;
const int sensorPin2 = 4;
const int sensorPin3 = 5;

// Variables
int objectCount0 = 0;      // Counter to keep track of the number of rotations
int sensorState0 = 0;      // Current state of the sensor (HIGH or LOW)
int lastSensorState0 = 0;  // Previous state of the sensor

int objectCount1 = 0;   
int sensorState1 = 0;   
int lastSensorState1 = 0;

int objectCount2 = 0;   
int sensorState2 = 0;  
int lastSensorState2 = 0;

int objectCount3 = 0;      
int sensorState3 = 0;      
int lastSensorState3 = 0;  

int relay0 = 8;
int relay1 = 9;
int relay2 = 10;
int relay3 = 11;


void setup() {
  pinMode(sensorPin0, INPUT);  // Set sensor pin as input
  pinMode(sensorPin1, INPUT);
  pinMode(sensorPin2, INPUT);
  pinMode(sensorPin3, INPUT);

  Serial.begin(9600);  // Initialize serial communication for debugging

  pinMode(relay0, OUTPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
}

void loop() {

  sensorState0 = digitalRead(sensorPin0);  // Read the state of the sensor
  sensorState1 = digitalRead(sensorPin1);
  sensorState2 = digitalRead(sensorPin2);
  sensorState3 = digitalRead(sensorPin3);

  // Check if the sensor state has changed (watchrotation)
  if (sensorState0 != lastSensorState0) {
    if (sensorState0 == HIGH) {
      objectCount0++;  // Increment the object count when rotation is complete
      Serial.print("Object 0 detected! Count: ");
      Serial.println(objectCount0);
    }
    if (objectCount0 > 18) {
      digitalWrite(relay0, LOW);
      Serial.print("Motor0 powered off for 10 sec. and wait till next cycle");
      Serial.println();

      //HERE A NON BLOCKING DELAY FOR 10 SECONDS TO STOP MOTOR

      objectCount0 = 0;
    }
    if (objectCount0 < 19) {
      digitalWrite(relay0, HIGH);
    }
  }
  lastSensorState0 = sensorState0;

  if (sensorState1 != lastSensorState1) {
    if (sensorState1 == HIGH) {
      objectCount1++; 
      Serial.print("Object 1 detected! Count: ");
      Serial.println(objectCount1);
    }
    if (objectCount1 > 18) {
      digitalWrite(relay1, LOW);
      Serial.print("Motor1 powered off for 10 sec. and wait till next cycle");
      Serial.println();

      //HERE A NON BLOCKING DELAY FOR 10 SECONDS TO STOP MOTOR
      objectCount1 = 0;
    }
    if (objectCount1 < 19) {
      digitalWrite(relay1, HIGH);
    }
  }
  lastSensorState1 = sensorState1;

  if (sensorState2 != lastSensorState2) {
    if (sensorState2 == HIGH) {
      objectCount2++;  
      Serial.print("Object 2 detected! Count: ");
      Serial.println(objectCount2);
    }
    if (objectCount2 > 18) {
      digitalWrite(relay2, LOW);
      Serial.print("Motor2 powered off for 10 sec. and wait till next cycle");
      Serial.println();

      //HERE A NON BLOCKING DELAY FOR 10 SECONDS TO STOP MOTOR

      objectCount2 = 0;
    }
    if (objectCount2 < 19) {
      digitalWrite(relay2, HIGH);
    }
  }
  lastSensorState2 = sensorState2;

  if (sensorState3 != lastSensorState3) {
    if (sensorState3 == HIGH) {
      objectCount3++;  
      Serial.print("Object 3 detected! Count: ");
      Serial.println(objectCount3);
    }
    if (objectCount3 > 18) {
      digitalWrite(relay3, LOW);
      Serial.print("Motor3 powered off for 10 sec. and wait till next cycle");
      Serial.println();

      //HERE A NON BLOCKING DELAY FOR 10 SECONDS TO STOP MOTOR

      objectCount3 = 0;
    }
    if (objectCount3 < 19) {
      digitalWrite(relay3, HIGH);
    }
  }
  lastSensorState3 = sensorState3;
}

Seems like Stepper Motors would be a more appropriate choice.

Thanks, it is an existing watchwinder and not that easy to change the motors to stepper motor and rewriting the software...

I'm not sure how it starts - do you have to push each watch to cause a change on the sensor?

Anyway, The code is crying out of structs and functions - that copy and paste code is going to trip you up eventually, but in the current theme, try this:

// declarations
bool waiting0 = false;
unsigned long waitStartTime0 = 0;
//Code for watch zero
  // Check if the sensor state has changed (watchrotation)
  if (sensorState0 != lastSensorState0)
  {
    if (sensorState0 == HIGH)
    {
      objectCount0++;  // Increment the object count when rotation is complete
      Serial.print("Object 0 detected! Count: ");
      Serial.println(objectCount0);
    }
    if (objectCount0 > 18)
    {
      if (!waiting0)
      {
        digitalWrite(relay0, LOW);
        Serial.print("Motor0 powered off for 10 sec. and wait till next cycle");
        Serial.println();
        waiting0 = true;
        waitStartTime0 = millis();
      }
      //Waiting handled below
    }
    if (objectCount0 < 19)
    {
      digitalWrite(relay0, HIGH);
    }
  }
  lastSensorState0 = sensorState0;
  
  if (waiting0)
  {
    if ((millis() - waitStartTime0) > 10000UL)
    {
      waiting0 = false;
      objectCount0 = 0;
      digitalWrite(relay0, HIGH);
    }
  }

Wildbill, tnx!! This is great. It works just the way I want...really appriciate your help. I would have never fixed this by myself.
Have a nice weekend..

I want to add another feature to my 4 watch watchwinder;
If I open the door of the watchwinder and one of the watches (or more) is/are still rotating it should stop as soon as it reaches the "12 o'clock postion" and stays in that position al long as the door is open..

The problem I am facing is that if the the watch triggers the IR sensor (in the 12 o'clock position) and the door is open it only activates the relay, which switches the motor OFF) , very very briefly. It should activate the relay as long as the door is opened.....

Any suggestions???

// Pin configuration
const int sensorPin0 = 2;  // Connect the infrared sensor's output pin to Arduino pin 2
const int sensorPin1 = 3;
const int sensorPin2 = 4;
const int sensorPin3 = 5;

const int doorswitch = A4;


// Variables
int objectCount0 = 0;      // Counter to keep track of the number of objects
int sensorState0 = 0;      // Current state of the sensor (HIGH or LOW)
int lastSensorState0 = 0;  // Previous state of the sensor

int objectCount1 = 0;  // Counter to keep track of the number of objects
int sensorState1 = 0;  // Current state of the sensor (HIGH or LOW)
int lastSensorState1 = 0;

int objectCount2 = 0;  // Counter to keep track of the number of objects
int sensorState2 = 0;  // Current state of the sensor (HIGH or LOW)
int lastSensorState2 = 0;

int objectCount3 = 0;      // Counter to keep track of the number of objects
int sensorState3 = 0;      // Current state of the sensor (HIGH or LOW)
int lastSensorState3 = 0;  // Previous state of the sensor


int relay0 = 10;
int relay1 = 11;
int relay2 = 12;
int relay3 = 13;

bool waiting0 = false;
bool waiting1 = false;
bool waiting2 = false;
bool waiting3 = false;

unsigned long waitStartTime0 = 0;
unsigned long waitStartTime1 = 0;
unsigned long waitStartTime2 = 0;
unsigned long waitStartTime3 = 0;


void setup() {
  pinMode(sensorPin0, INPUT);  // Set sensor pin as input
  pinMode(sensorPin1, INPUT);
  pinMode(sensorPin2, INPUT);
  pinMode(sensorPin3, INPUT);
  

  
  pinMode(A4, INPUT);   //doorswitch
  

  Serial.begin(9600);  // Initialize serial communication for debugging

  pinMode(relay0, OUTPUT);  //digital output for relay to stop motor 0
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
}

void loop() {

  sensorState0 = digitalRead(sensorPin0);  // Read the state of the sensor
  sensorState1 = digitalRead(sensorPin1);
  sensorState2 = digitalRead(sensorPin2);
  sensorState3 = digitalRead(sensorPin3);
  
  int valA4 = digitalRead(A4);


  // Check if the sensor state has changed (object detected)
  if (sensorState0 != lastSensorState0) {
      if (sensorState0 == LOW && valA4 == HIGH) {   // relay only very briefly activated but should stay HIGH als long as door is open
      digitalWrite(relay0, HIGH);

        }else{
      }
      if (sensorState0 == HIGH){
        objectCount0++;  // Increment the object count when an object is detected
        Serial.print("Object 0 detected! Count: ");
        Serial.println(objectCount0);
      }
      if (objectCount0 > 18) {
        if (!waiting0) {
          digitalWrite(relay0, HIGH);
          Serial.print("Motor0 powered off for 10 sec. and wait till next cycle");
          Serial.println();
          waiting0 = true;
          waitStartTime0 = millis();
        }
        //Waiting handled below
      }
      if (objectCount0 < 19) {
        digitalWrite(relay0, LOW);
      }
    }
    lastSensorState0 = sensorState0;

    if (waiting0) {
      if ((millis() - waitStartTime0) > 10000UL) {
        waiting0 = false;
        objectCount0 = 0;
        digitalWrite(relay0, LOW);
      }
    }


    if (sensorState1 != lastSensorState1) {
      if (sensorState1 == HIGH) {
        objectCount1++;  // Increment the object count when an object is detected
        Serial.print("Object 1 detected! Count: ");
        Serial.println(objectCount1);
      }
      if (objectCount1 > 18) {
        if (!waiting1) {
          digitalWrite(relay1, LOW);
          Serial.print("Motor1 powered off for 10 sec. and wait till next cycle");
          Serial.println();
          waiting1 = true;
          waitStartTime1 = millis();
        }
        //Waiting handled below
      }
      if (objectCount1 < 19) {
        digitalWrite(relay1, HIGH);
      }
    }
    lastSensorState1 = sensorState1;

    if (waiting1) {
      if ((millis() - waitStartTime1) > 10000UL) {
        waiting1 = false;
        objectCount1 = 0;
        digitalWrite(relay1, HIGH);
      }
    }

    if (sensorState2 != lastSensorState2) {
      if (sensorState2 == HIGH) {
        objectCount2++;  // Increment the object count when an object is detected
        Serial.print("Object 2 detected! Count: ");
        Serial.println(objectCount2);
      }
      if (objectCount2 > 18) {
        if (!waiting2) {
          digitalWrite(relay2, LOW);
          Serial.print("Motor2 powered off for 10 sec. and wait till next cycle");
          Serial.println();
          waiting2 = true;
          waitStartTime2 = millis();
        }
        //Waiting handled below
      }
      if (objectCount2 < 19) {
        digitalWrite(relay2, HIGH);
      }
    }
    lastSensorState2 = sensorState2;

    if (waiting2) {
      if ((millis() - waitStartTime2) > 10000UL) {
        waiting2 = false;
        objectCount2 = 0;
        digitalWrite(relay2, HIGH);
      }
    }

    if (sensorState3 != lastSensorState3) {
      if (sensorState3 == HIGH) {
        objectCount3++;  // Increment the object count when an object is detected
        Serial.print("Object3 detected! Count: ");
        Serial.println(objectCount3);
      }
      if (objectCount3 > 18) {
        if (!waiting3) {
          digitalWrite(relay3, LOW);
          Serial.print("Motor3 powered off for 10 sec. and wait till next cycle");
          Serial.println();
          waiting3 = true;
          waitStartTime3 = millis();
        }
        //Waiting handled below
      }
      if (objectCount3 < 19) {
        digitalWrite(relay3, HIGH);
      }
    }
    lastSensorState3 = sensorState3;

    if (waiting3) {
      if ((millis() - waitStartTime3) > 10000UL) {
        waiting3 = false;
        objectCount3 = 0;
        digitalWrite(relay3, HIGH);
      }
    }
}

It was said, before we saw the final result

and I would say yes, it screams for array variables too.

It would be easier to change the behaviour of every motor/sensor if they all did their work through one general function.

Otherwise you'll be copy/paste/editing every little tweak, which is not just painful but also each one an opportunity to make a tiny editing mistake, or to overlook part of the modification.

Rinse and repeat. Die with things left undone because wasted time.

I understand this may be a one-off. I ask if you would like to try making this code 1/4 the size with no new features as a way to first set it up for easier fixing, modifying or enhancing.

What you'd need to learn about are functions, array variables and loops, all of which learning would be no waste of time should you ever revisit this or get new ideas for projects.

Like the one I haven't done yet - a master clock that has GPS, internet time, a WWVB receiver and good old fashioned synchronous clock to count the cycles from the power company... time is a minor passion of mine.

We can help with that, but first thing for you would be to google

arduino functions

and

arduino array variables

both of which searches would lead you to fairly good material that would probably be within your current ability to absorb.

a7

Tks, I'll have a look at it and see how far I can get but as I've said before, I'am more of a "watch-guy" than an Arduino guy..

I'd suggest that if the door is open, just run separate logic that rotates any watches that need it to the 12:00 position. Don't try to mix it in with the normal winding logic.

When the door closes again go back to regular operations.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.