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.
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.