4 brushless motors with Arduino Uno seemingly unpredictably spin

Hey guys, I am using an Arduino Uno as a flight controller for a quad I'm building, I'm using an AKK 30A 4 in 1 ESC with a 3S LiPo. The issue that I'm having is the ESC seems like it arms sometimes, and then sometimes doesn't. Then, when it does arm, sometimes only 1 or 2 or 3 motors are spinning instead of all 4. The worst part is that I had all 4 working properly until something happened, I honestly have no idea what changed because I didn't disconnect any wires and I'm using the same code.

My code is pretty long, so I'm just gonna post the part where I try to turn on the motors.

#include <Servo.h>

Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;


void setup() {
  motor1.attach(5);
  motor2.attach(9); 
  motor3.attach(10);
  motor4.attach(11);
  
  throttle = 60;
  motorSetSpeed(0);
  delay(1500);
  motorStartAt(throttle); //58 is like barely starting to hover speeds
}

void loop() {
  if(!dmpReady) return;
  
  getCurrAngles();
  getPid();
  motorPower1 = throttle - pid_output_pitch - pid_output_roll + pid_output_yaw; //Calculate the pulse for esc 1 (front-right - CW)
  motorPower2 = throttle - pid_output_pitch + pid_output_roll - pid_output_yaw; //Calculate the pulse for esc 2 (rear-right - CCW)
  motorPower3 = throttle + pid_output_pitch - pid_output_roll - pid_output_yaw; //Calculate the pulse for esc 3 (front-left - CCW)
  motorPower4 = throttle + pid_output_pitch + pid_output_roll + pid_output_yaw; //Calculate the pulse for esc 4 (rear-left - CW)
  
  if (motorPower1 < 42) {
    motorPower1 = 42;
  }
  if (motorPower2 < 42) {
    motorPower2 = 42;
  }
  if (motorPower3 < 42) {
    motorPower3 = 42;
  }
  if (motorPower4 < 42) {
    motorPower4 = 42;
  }
  if (motorPower1 > 75) {
    motorPower1 = 75;
  }
  if (motorPower2 > 75) {
    motorPower2 = 75;
  }
  if (motorPower3 > 75) {
    motorPower3 = 75;
  }
  if (motorPower4 > 75) {
    motorPower4 = 75;
  }
  Serial.print("Motor1:  ");
  Serial.print(motorPower1);
  Serial.print("\tMotor2:  ");
  Serial.print(motorPower2);
  Serial.print("\tMotor3:  ");
  Serial.print(motorPower3);
  Serial.print("\tMotor4:  ");
  Serial.print(motorPower4);
  Serial.println();
  Serial.println();
  motor1.write(motorPower1);
  motor2.write(motorPower2);
  motor3.write(motorPower3);
  motor4.write(motorPower4);
  
}

//These are two functions to start up the motors
void motorSetSpeed(int speeding) {
  motor1.write(speeding);
  motor2.write(speeding);
  motor3.write(speeding);
  motor4.write(speeding);
        
}

void motorStartAt(int start_speed) {
  int i;
  for (i=0; i < start_speed; i++) {
    motorSetSpeed(i);
    //Serial.println(i);
    delay(100);

  }
}

The getPid() and getCurrAngles() are pretty long, but if the drone is on a flat surface, they consistently give the command to hover so I am pretty sure they aren't the problem.

I have tried a lot of different approaches to get these things to fly including an ESC calibration where I have the Arduino doing max throttle motor.write(255);, I turn on the ESC, it does a series of beeps increasing in tone, then have the Arduino do motor.write(0);, there are a series of descending beeps after which I turn off the ESC assuming it is calibrated. Please let me know if that is incorrect.

Thank you in advance for any help!

Okay quick edit here, I left the drone on with the program running while I was typing this, and suddenly it just turned on and is working. I still would like any suggestions as to why this might have happened just in case it suddenly STOPS working again. Thank You!

The getPid() and getCurrAngles() are pretty long, but if the drone is on a flat surface, they consistently give the command to hover so I am pretty sure they aren't the problem.

Are you trying to test your angle calculations? No. You are trying to test the arming of the ESCs.
Take out ALL of the code that does not handle the setup, arming and simple throttle testing of the ESCs.

Restrain your device so that it can be safely tested.
Arm 1 ESC in setup
In the loop, slowly run the throttle from 0 to some small amount, say 25% and slowly back down.

Did it work? If so, repeat for the other 3 ESCs.

If all 4 work, arm all 4 and run the throttle for all 4.

No angle calculations.
No input from RC systems.
Just Arm and throttle test.

As a suggestion, you should consider using arrays for collections of things, like the collection of pin numbers and the collection of servos.

And a request. Post pics of what you have so far. Quads are cool!

Okay, I've taken out all code that does not pertain to arming motors. This is simply supposed to gradually increase power and then decrease it. It only goes up to just over 30% throttle. It only seems to spin 2 motors at a time, and those two change seemingly at random.

#include <Servo.h>

Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;

//Min throttle is like 40.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  motor1.attach(5);
  motor2.attach(9);
  motor3.attach(10);
  motor4.attach(11);
  motorStartAt(80);
  
  
  
}

void loop() {
    for (int i = 80; i > 38; i--) {
      motor3.write(i);
      motor2.write(i);
      motor1.write(i);
      motor4.write(i);
      Serial.println(i);
      delay(100);
    }
    delay(1000);
    for (int i = 38; i < 80; i++) {
      motor3.write(i);
      motor2.write(i);
      motor1.write(i);
      motor4.write(i);
      Serial.println(i);
      delay(100);
    }
    delay(1000);
}

void motorSetSpeed(int speeder) {
    motor1.write(speeder);
    motor2.write(speeder);
    motor3.write(speeder);
    motor4.write(speeder);
        
}
void motorStartAt(int start_speed) {
    int i;
    for (i=0; i < start_speed; i++) {
    motorSetSpeed(i);
    //Serial.println(i);
    delay(100);
  }
}

An interesting note, the code in my last post seems to work, but only if I reset the Arduino by pushing the little red button after it enters the main loop. I can't figure out why though and I'd like to not have to press the button every time.

I'll attach a few photos of the quad below

okay it only is allowing one photo... idk sorry

okay one more quick edit, I tried using multiple motors at a time instead of one because one at a time was working and I wanted to check if it would make all of them spin.

Okay everyone, I know that since I posted this only a few hours ago it makes it seem like I didn't work on it very hard if I say I solved it now, but I actually have poured many hours into this. I solved the problem.

So if anyone else is having this problem, here is how you solve it. Add a switch from the battery power to the ESC. This way you can turn on the Arduino WITHOUT powering up the ESC. Then run this sketch I have below. It will tell you when you should turn on the ESC and when to turn it off. You must calibrate ALL FOUR ESC at the SAME TIME (which the sketch does). That was my mistake before, because since they are all connected to the same power supply, trying to calibrate just one at a time will screw up the calibration of another one.

#include <Servo.h>

Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;

void setup() {
  Serial.begin(115200);
  motor1.attach(9);
  motor2.attach(10);
  motor3.attach(11);
  motor4.attach(5);
}

void loop() {
  motor2.write(255);
  motor1.write(255);
  motor3.write(255);
  motor4.write(255);
  Serial.println("Turn on power");
  delay(10000);
  motor2.write(0);
  motor1.write(0);
  motor3.write(0);
  motor4.write(0);
  Serial.println("Turn off ESC");
  delay(10000);
  
  
}

Then, in order to use the motors in other sketches you must be careful to turn the ESC on BEFORE commands are sent to it. If it gets turned on while there is a command running to it, it will enter calibration mode again and you have to restart.

The startup procedure (that worked for me) was as follows

#include <Servo.h>

Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;

void setup() {
  Serial.begin(115200);
  motor1.attach(9);
  motor2.attach(10);
  motor3.attach(11);
  motor4.attach(5);
  int throttle = 80;
  motorSetSpeed(40);
  delay(1500);
  motorStartAt(throttle);
  delay(1500);
  motorSetSpeed(40);
}

//These are two functions to start up the motors
void motorSetSpeed(int speeding) {
  motor1.write(speeding);
  motor2.write(speeding);
  motor3.write(speeding);
  motor4.write(speeding);
        
}

void motorStartAt(int start_speed) {
  int i;
  for (i=0; i < start_speed; i++) {
    motorSetSpeed(i);
    //Serial.println(i);
    delay(10);

  }
}

So essentially, after calibrating all of the motors in a different sketch, to arm them you must give a low command (in my case 40 seems to be where the ESC registers as 0), then a highish command (IDK how much the range matters but mine was only about 30% throttle), and then ANOTHER low command in order to get the things to arm.

Hopefully this helps anyone having the same problem, sorry if I wasted anyones time, I just happened to have an epiphany today!

Thank You!

I think that you can get away with a single sketch.
What you are calling calibrating is some times called arming.
And either way it should go into the setup routine.

Then your loop routine can basically be from the second sketch you posted.