Delay between PID calculations and motor write for quadcopter

I've finished hammering out most of the functions for the quadcopter firmware that I am trying to write. My problem, I believe, is that there is a delay between any calculations I make (PID, etc) and the analogWrite() function actually writing the values to my motors. I know that some people seem to prefer the servo library function for writing, is this faster? Or would this not even be a problem involving analogWrite? I do not think that my code is so congested that it would put it this far behind, but I really have almost no background in programming, MEMS, arduino.... I know that most ESC's can only update at about 50 Hz, but I also know that the PWM it defaulted to run at 290 Hz on the I/O I am using. Has anybody encountered this problem?

The PID algorithm, of which I am now using the library, seems to work fine. The angles from my sensors are pretty good and the noise minimal. Any bright ideas or input would be greatly appreciated!

//Edit
I realized I should describe why I think this is my problem. No matter the PID coefficients I put in, the quad always ends up oscillating a great deal back and forth, eventually losing any sort of control. I tested the delay by pulling down on one spar, and it took a while for it to ramp up.

I also had a though... is it possible that because my sensors update no faster (in total) than 100 Hz, that the PWM becomes static and keeps "pulling" until a new sensor value is put through the PID loop? Maybe their slowness is giving too much lag time for the motors? If this were the case, could I put a delay() in somewhere? Doesn't seem right, but how else could I fix this?

  Serial.begin(9600);                                                                                                         //Serial Monitor, used for debugging

So each time you print a byte it will take 1/960 of a second (over 1 mS).

  Serial.print("  pitchAngle  "); 
  Serial.print(calcAngle[0]);
  Serial.print("  rollAngle  "); 
  Serial.println(calcAngle[1]);

Say, 32 bytes there.

    Serial.print("  accDelay  "); 
    Serial.print(micros() - nta);

Maybe another 14.

    Serial.print("  gyroDelay  "); 
    Serial.print(micros() - ntg);

Maybe another 16 (depends on the numbers).

So, about 32 + 14 + 16 = 62

62 * 0.001042 = 0.065 (65 mS)

I timed how long between the reading of sensors, and came up with 73828 microseconds, or .073828 seconds.

Pretty close to my estimate. So, lose the serial prints. :slight_smile: Or use a higher baud rate (eg. 115200). Or just have them there for debugging on the bench, eg.

#if DEBUGGING_MODE
    Serial.print("  gyroDelay  "); 
    Serial.print(micros() - ntg);
#endif
void readFrom(int device, byte address, int num, byte buff[]) {
  Wire.beginTransmission(device);                                  //start transmission to device 
  Wire.write(address);                                             //sends address to read from
  Wire.endTransmission();                                          //end transmission
  Wire.beginTransmission(device);                                  //start transmission to device (initiate again)
  Wire.requestFrom(device, num);                                   // request number of bytes from device
  int i = 0;
  while(Wire.available())                                          //device may send less than requested (abnormal)
  { 
    buff[i] = Wire.read();                                         // receive a byte
    i++;
  }
  Wire.endTransmission();                                          //end transmission
}

Don't put Wire.beginTransmission and Wire.endTransmission around Wire.requestFrom.

See: Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino

Suspiciously similar threads merged.

Nick Gammon, thanks for the reply! I will eliminate/tighten up the problems, and see what happens without all of the Serial.print's, etc. I appreciate some useful feedback! Suspiciously similar, I agree.