How to replace delay with millis for servo sequence?

Hi,

I wrote the below program to operate an automated bale wrapper using Arduino and servos. At the minute it is doing everything fine. The only problem is when I start the tip sequence I cant stop it because I am using delay(). I shouldn’t need to stop it, but I’d like the option. This is the full code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

Servo tipservo;
Servo rotateservo;
Servo cutservo;
Servo armservo;

int msg = 0;

int hallPin = 2;
int hallCount = 0;
int hallState = 0;
int lasthallState = 0;
int Count = 0;
int tipCount = 0;

bool Start = false;
bool tip = false;

RF24 radio(7, 8); // CE, CSN
const byte addresses[][6] = {"00001"};

void setup() {
  Serial.begin(9600);
  pinMode(hallPin, INPUT);
  tipservo.write(80);
  tipservo.attach(9);
  delay(500);
  rotateservo.write(90);
  rotateservo.attach(3);
  delay(500);
  cutservo.write(80);
  cutservo.attach(4);
  delay(500);
  armservo.write(100);
  armservo.attach(5);
  delay(500);
  radio.begin();
  radio.openReadingPipe(1, addresses[0]); // 00001
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate(RF24_250KBPS);
  radio.setChannel(115);             //set frequency to channel 100
  radio.startListening();
}

void loop() {
  Serial.println(msg);
  hallState = digitalRead(hallPin);
  if (hallState != lasthallState){
    if (hallState == LOW){
      Count++;
      Serial.println(Count);
    }
  }
  lasthallState = hallState;
  

  if (Count == 2 && Start == true){
    rotateservo.write(170);
    cutservo.write(40);
  }

  if (Count == 4 && Start == true){
    cutservo.write(80);
  }

  if (Count == 14 && Start == true){
    rotateservo.write(115);
  }

  if (Count >= 16 && Start == true){
    rotateservo.write(90);
    Count = 0;
    Start = false;
  }


  if (msg == 0) {
    tipservo.write(80);
  }
  delay(5);
  // if there is data ready
  if ( radio.available() )
  {
    // Dump the payloads until we've gotten everything
    while (radio.available()){
      radio.read(&msg, sizeof(msg));
      if (msg == 1 && tip == false) {
        Count = 0;
        Start = true;
        Serial.println("Start");
        rotateservo.write(130);
      }
      if (msg == 2) {
        Serial.println("Stop");
        Count = 0;
        Start = false;
        rotateservo.write(90);
        delay(100);
        tipservo.write(80);
        delay(100);
        cutservo.write(80);
        delay(100);
        armservo.write(100);
        delay(100);
      }
      if (msg == 3 && Start == false && tipCount <= 0) {
        tip = true;
        Serial.println("Tip");
        tipservo.write(135);
        delay(1500);
        tipservo.write(80);
        delay(1000);
        armservo.write(180);
        delay(2300);
        armservo.write(100);
        delay(1000);
        cutservo.write(155);
        delay(1000);
        cutservo.write(80);
        delay(1000);
        armservo.write(10);
        delay(2700);
        armservo.write(100);
        delay(1000);
        tipservo.write(160);
        delay(1500);
        tipservo.write(80);
        delay(1000);
        tipservo.write(0);
        delay(1500);
        tipservo.write(80);
        
        tip = false;
        msg = 0;
        tipCount++;
      }
      if (msg == 4 && Start == false) {
        Serial.println("");
        msg = 0;
      }
    }
    tipCount = 0;
    msg = 0;
  }
}

I’m guessing I’d have to use millis, but I cant for the life of me work it out. And I cant find much about using millis with servos.

This is the only section that needs a non-blocking alternative to delay();

if (msg == 3 && Start == false && tipCount <= 0) {
        tip = true;
        Serial.println("Tip");
        tipservo.write(135);
        delay(1500);
        tipservo.write(80);
        delay(1000);
        armservo.write(180);
        delay(2300);
        armservo.write(100);
        delay(1000);
        cutservo.write(155);
        delay(1000);
        cutservo.write(80);
        delay(1000);
        armservo.write(10);
        delay(2700);
        armservo.write(100);
        delay(1000);
        tipservo.write(160);
        delay(1500);
        tipservo.write(80);
        delay(1000);
        tipservo.write(0);
        delay(1500);
        tipservo.write(80);
        
        tip = false;
        msg = 0;
        tipCount++;
      }

I would appreciate your help. Thanks very much.

Damien.

Have a look at how the servo is controlled using millis() in Several Things at a Time

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

Robin2:
Have a look at how the servo is controlled using millis() in Several Things at a Time

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

Thanks, I found what I needed in another members sketch. Still haven't totally got my head around millis

the function millis() starts to count milliseconds since power-on of your Arduino. It counts up milliseconds for minutes, hours, days, weeks. Therefore it uses a vriable of type unsigned long. An unsigned long can store values from 0 up to 4,294,967,295 milliseconds. This is 49,7 days. After this time the value just rolls over to zero and starts counting up again. This rollover is absolutely no problem if the calculation of any elapsed time is calculated in the recommended way.

best regards Stefan

Seedler:
Still haven't totally got my head around millis

1. There is a 4-byte (32-bit) wide RAM space (Fig-1) within ATmega328P MCU of UNO Board, which is known as Millis Counter. Initially, all four locations hold 0s.
millisCounter.png
Figure-1:

2. When the uploading of a sketch is finished, the counter of Fig-1 advances by 1 (one) at the elapse of every millisecond. Now, we may say that the Millis Counter records how much time has elapsed since the sketch has begun. The 1 millisecond time tick (TT) is provided by TC0 (Timer/Counter 0) of the MCU. I understand that the counting process is interrupt driven; so, when the MCU is executing the delay() function, the Millis Counter is not updated as delay() function disables interrupt.

3. There is a function named millis() which can be used to read the current content of the Millis Counter "on the fly (without disturbing the counting process)"

4. Because time can not be negative -- can not go backward, Millis Counter counts always in the forward direction (positive) from 0x00000000 to 0xFFFFFFFF (0 to 4,294,967,295) which equals to about 49 days. So, the Millis Counter can be declared by an "unsigned long" data type variable.

5. There are many good uses of Millis Counter. For example: You wish to see that a LED remains ignited for 500 ms and at the same time, you want to refresh a multiplexed type display unit. The codes are:

digitalWrite(LED, HIGH);     //LED is ON
unsigned long prMillis = millis();   //record the current content of Millis Counter in millisecond.
while(millis() - prMillis <500)
{
    refreshDisplay();    
}
digitalWrite(LED, LOW);    //LED is OFF

millisCounter.png