I'm using Arduino.h, Servo.h, and HX711.h. My Servo jitters routinely about every 57 seconds. I've spent days searching and trying various possible solutions. I suspect the problem is that the PWM signal is being disrupted by something using a timer, but I don't know how to verify that, nor how to find it.
I'm using the RexQualis Mega 2560. The Servo is connected to pin 9. The only two places I use Servo.write() is once in setup() and once in loop(). I've added Serial.print() lines to reveal if Servo.write() is being called unexpectedly. It isn't.
I disconnected from the USB cable and powered the Arduino from a separate 9V 1A supply. The Servo is powered by a 5V 6A supply. The HX711 is powered by a breadboard supply. The breadboard supply also feeds a DFPlayer. The DFPlayer connects to the Mega on RX1 and TX1. No DFPlayer libraries are being used.
I've tried a completely different brand and power level of Servo.
At the top of loop() I set currentTimeStamp = millis(). From then on the code uses currentTimeStamp.
During Idle time, when nothing else is going on, currentTimeStamp is used to periodically report on various state machines. These reports happen multiple times per minute without any Servo jitter. Various buttons & switches are read during each loop. All code sections check either currentTimeStamp or a State machine variables to decide whether to execute.
I use delay() during setup, at the end of a game just prior to another idle period, and in the DFPlayer function to prevent DFPlayer commands from executing too close together. During idle time, DFPlayer is invoked about once per hour to restart the theme music. Otherwise, during idle time, delay() is never used.
if (currentTimeStamp < (lastDFCommandTime + dfCmdDelay)) {
delay((lastDFCommandTime + dfCmdDelay) - currentTimeStamp); // Briefest delay possible
}
lastDFCommandTime = currentTimeStamp; // record time of last command
WIRING:
Servo: pin 9
HX711-DT: pin 4
HX711-CK: pin 5
LED: pin 13
DFPlayer TX: RX1
DFPlayer RX: TX1
Relay1: pin 6
Relay2: pin 7
Buttons & Switches: pins 23-35 odd
Concering the HX711 library, I use Scale.begin() during setup(). I use read_average(), before idle time, during initialization. During idle time, this section of code runs with two library calls...
(note: weighInterval = 80)
// -------------------------- Weigh periodically -------------------------
if (currentTimeStamp > weighTime) {
// Is Load Cell data available?
if (Scale.is_ready()) {
// Yes.
recordScaleWeights(Scale.read());
weightOfObject = scaleWeight();
}
weighTime += weighInterval; // The Time of next weighing
}
// --------- Function recordScaleWeights -------------------------------------------
// The purpose of this function is to record the most recent RAW scale readings
void recordScaleWeights(long scaleReading) {
scaleWeights[scaleWeightIndex++] = scaleReading;
if (scaleWeightIndex == WeightsSize) {
WeightReady = true; // This will stay True, after enough weighs are made
scaleWeightIndex = 0;
}
}
// ---------- Function scaleWeight -----------------------------------------------
// The purpose of this function is to turn the array of RAW readings into a weight.
float scaleWeight() {
long weightMin = scaleWeights[0]; // start tracking weights in the array
long weightMax = weightMin;
long weightTot = weightMin;
for (byte i = 1; i < WeightsSize; i++) {
if (scaleWeights[i] < weightMin) { weightMin = scaleWeights[i]; } // Track smallest
if (scaleWeights[i] > weightMax) { weightMax = scaleWeights[i]; } // Track largest
weightTot += scaleWeights[i]; // Accumulate
}
long weight = ((weightTot - weightMin - weightMax) / (WeightsSize - 2));
return float(0.9f + (weight - scaleTare) / scaleFactor);
}
I can tell, with my ears, that the theme music plays without disruption. The idle code...
switch (gameStateNext) {
case gameStateIdle: // Idle - Play Theme Music, wait for Go-Watch
// We get here from gameStateWeighedIdol, Yellow button, bigGreen-bigRed buttons
// Are we already in Idle mode?
if (gameState != gameStateIdle) {
// No. Execute the transition (i.e. nothing to transition in this state)
gameState = gameStateIdle;
} else {
// Yes. follow through
// bigGreen Button will advance state to gameStateGoWatch
// Did we reach end of Theme music?
if (songFlagDone) {
sendDFCommand(dfCmdTrack, 0, dfThemeSong); // Play the Theme Music
} // endIf - end of Theme music
} // endIf - in Idle mode?
break;
case gameStateGoWatch: // Watch for Go-Trigger
I also wonder what else might disrupt the PWM signal, such as routine garbage collection.
At this time, the code is over 2100 lines. After much testing, all seems well... except for the jitter during idle time.
Any suggestions are very welcome as to what might cause jitter so regularly.