Moving a servo using 2 push buttons without using a delay

Im new to Arduino so don't fully understand the language, but have written some code to allow me to change a motorcycle gears using a servo.
however I have some questions on how to approach some of the things I'm attempting. for example I assume the library for the servo is for those micro servos, I don't know if the same library will work with a 60kg servo?
my code I have written is fully functional and works great, but I will be adding many extra functions and will want to choose exactly when the relay turns off and on, so will need to get rid of the delay functions, however I still need the servo to do it movements as quick as possible. any help one this would be much appreciated. thanks.


#include <Servo.h> 
Servo servo; 
int pot = 90; // initial servo position (always return to 90 after servo has moved)
const int RELAY_PIN = 4; //switches off while moving the servo
const int buttonPin1 = 2; //go to 180 degrees
const int buttonPin2 = 3; //go to 0 degrees
const int buttonPin3 = 5; //go to 45 degrees
boolean currentState1 = LOW;//stroage for current button state
boolean lastState1 = LOW;//storage for last button state
boolean currentState2 = HIGH;//stroage for current button state
boolean lastState2 = HIGH;//storage for last button state
boolean currentState3 = HIGH;//stroage for current button state
boolean lastState3 = HIGH;//storage for last button state
boolean pos = true;


void setup(){
  
  pinMode(buttonPin1, INPUT_PULLUP);
  Serial.begin(9600); //initialize Serial connection
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(buttonPin3, INPUT_PULLUP);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH); // Set Relay to on state
  
}

void loop(){
  //// down gear
  currentState1 = digitalRead(buttonPin1);
  if (currentState1 == HIGH && lastState1 == LOW){//if button has just been pressed
    delay(10);
    
    if (pos == true){
      servo.attach(9);  // attaches the servo on pin 9 to the servo object
      servo.write(180);              // tell servo to go to "180" 
      digitalWrite(RELAY_PIN, LOW); //relay off
      delay(200);
      servo.write(90); // tell servo to go to "90"
      digitalWrite(RELAY_PIN, HIGH); //relay on 
      delay(150);
      Serial.println("up");  
            pos = true;
servo.detach();
    }
      
      
    }
  lastState1 = currentState1;

 
//// up gear
  
  currentState2 = digitalRead(buttonPin2);
  if (currentState2 == HIGH && lastState2 == LOW){//if button has just been pressed
    delay(10);
    
    if (pos == true){
      servo.attach(9);  // attaches the servo on pin 9 to the servo object
      servo.write(0); // tell servo to go to "0" 
      digitalWrite(RELAY_PIN, LOW); //relay off
      delay(200);
      digitalWrite(RELAY_PIN, HIGH); //relay on
      servo.write(90); 
      delay(150);
      
      
      Serial.println("down");  

            pos = true;
servo.detach();
    }
  }
  
  lastState2 = currentState2;


  
///// neutral
  
  currentState3 = digitalRead(buttonPin3);
  if (currentState3 == HIGH && lastState3 == LOW){//if button has just been pressed
    delay(10);
        
    if (pos == true){
      servo.attach(9); 
      servo.write(45); // tell servo to go to "45" 
      delay(200);
      servo.write(90); 
      delay(150);

      Serial.println("neutral");  
            pos = true;
servo.detach();
      
    }
  }
  
  lastState3 = currentState3;
}

P.S I have looked at using mills() to do the timing, but don't understand it to the extent where I feel I can implement it into my code. an edit to part of my code would help a lot!
thanks

The way that it works here is that you write the code to the best of your ability and if the code does not do what you want you post the code, a detailed description of what the code actually does and a description if what the code is supposed to do. Then we help.

Read the forum guidelines to see how to properly post code and some good information on making a good post.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

Some good non-blocking timing tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

sure, so I've tried to include most of the detail next to the code, but the main function is for the servo to move to a set position when button 1 is pressed, then return to "90" position, and move to another set position when button 2 is pressed and then return to 90 again, and to have a relay turn off and on while the servo is moving (as this will turn the engine off to allow for a full throttle gear change).
I just need to modify the code to edit out the delays as these will create issues for any extra loops I might want to add.

If You post a link to the datasheet helpers can surely give You precise advice.
Which Arduino You use is valuable to know.

What is the reason why you are attaching then detaching the servo ?

Do you know what State Machine programming is ?

Do you know what the the millis( ) function does ?

Do you know what a Flag is when talking about programming ?

I'm using an Arduino mega.
this is the info I have about the servo:

Note:

  1. The best service voltage is 7.4V.It’s recommended to use 2s battery for power supply (6-8.4V)
    2.The working angle of this servo is 180 degrees(PWM: 500us-2500us),
    as the output of some remote controls can only be 1000-2000us,we recommend you to purchase 270 degrees model.(ASIN: B07KTSCN4J)

Feature:

  • High-precision metal gear.
  • Durable SS Metal Gear
  • Double Ball Bearing
  • Programmable Digital Amplifier with Mosft Drive
  • Bottom Side Axial Mount Hole
  • Orientation Angle: maximum 180deg
  • Mechanical Angle:360deg (Plug/Output wheel/Radio control system compatible with Futaba JR Hitec)

Speed:
:arrow_forward:0.17sec/60 degree @6V
:arrow_forward:0.15sec/60 degree @7.4V
:arrow_forward:0.13sec/60 degree @8.4V
Torque:
:arrow_forward:58kg.cm.@6V
:arrow_forward:65kg.cm.@7.4V
:arrow_forward:70kg.cm.@8.4V

Operating Voltage:6V-8.4V
Connector wire length:17.7in (450mm)
Gear ratio:279
Pulse width range: 500~2500μsec
Dead band width Microseconds
Waterproof performance:IP67

Missing is the very important specification of stall current. Can't really choose a proper power supply without that knowledge.

executing the function

means the arduino stops creating a valid servo-signal. All and every RC-servo needs an infinite train of servo-signal-pulses to operate properly. If you stop feeding in a valid servo-signal the servo is in an undefined state and could start wiggle randomly.

best regards Stefan

  1. Set a timeout
  2. Store an old milis() read
  3. Do something if a new millis() read has met or exceeded the timeout
  4. Store the new millis() in the old millis()
  5. Goto 3.

I wasn't sure if I should detach the servo to prevent glitching or jittering while its waiting for a new command. is it even necessary?

I think I'm familiar with flags as I recon I've used one or two in my code?

I know what the mills() function does, but not quite sure how to replace the delays with it.
I have just been reading about State Machine programming, is this another potential way of doing it?

Posting a hand-drawn timing diagram that shows the timely relation between servo turned to a certain position and switching on/off the relais would clear things up a lot.

best regards Stefan

Stall Torque: 58kg.cm(6.0V), 65kg.cm(7.4V), 70kg.cm(8.4V)

Adding to @groundFungus reply.... The level of the logic signals is missing but likely an "Arduino" will work. Note that some Arduino outputs 3.3 volt levels and the others output 5 volt logic levels.

Stall current?

all RC-servo work this way:
receive every 0,02 seconds a NEW short pulse where the short pulse defines the servohorn-position 0 to 180 degrees. Compare real position of servhorn with wanted position.
If there is a deviation between wanted and real position drive motor to minimise the deviation until (ideally) the deviation is down to zero.

servo.write(90) tells the servo-object create infinite pulsetrain with pulses 1500 microseconds long

servo.write(180) tells the servo-object create infinite pulsetrain with pulses 2000 microseconds long

servo.write(0) tells the servo-object create infinite pulsetrain with pulses 1000 microseconds long

you can imagine servo.write() similar to adjusting a volume-knob of an amplifier to a different position. The amplifier is amplifying all the time with the adjusted volume
until you change the knobs position.

similar thing with an rc-servo: create inifinite pulstrain with pulse-length X
best regards Stefan

I have-not yet tested at which point the relay should turn off as that will take some live tuning to get it right, so I'm trying to be able to choose when the relay turns off and on in relation to the servo, by changing a few numbers when it come to tuning.

that's good to know- thank you!
ill be using a separate power supply anyway.

here's the servo:

the exact numbers don't matter. Your timing-diagram shall show the principles
turn servo to what position?
switch relay on or off ?
switching the relay prior or after turning the servo?
etc.

okay, so I should get rid of the detach servo and have it constantly attached?
regards