So I’m working on a project were I need to generate a pulse with a variable frequency and duration, frequency ranges from 20Hz to 200Hz, and duration around 250us. The code is also watching button inputs, controlling an LCD, outputting serial communication, and reading analog inputs, I’d also like to keep outputting I2C open as a possibility.
After each pulse the code calculates the millis() and microseconds till the next pulse by adding the calculated microsecond delay to the previous time of pulse. Then the code does the less time sensitive things, like query buttons and sending out communications (this leaves anywhere from 5 to 14ms before next pulse). Followed by a while loop that keeps querying the button states till it is in the last millisecond before pulse, then a while loop to freeze it up on the last millisecond, and then finally a microsecond delay.
void loop()
{
if (conFlag & B00000001){
conButtonCheck();//Only Stores Button State
conButtonReact();//Compairs/Debounces/and reacts to buttons
timeCalcNext(); //Calculates timeNPulseMs and timeNPulseUs
conButtonCheck();
serialSend(0,timeNPulseMs); //Currently debugging, but still needed
serialSend(1,timeNPulseUs); //These two lines only store information to be sent
conButtonCheck();
if (disFlag & B10000000){disUpdateMenu();} // Updates Display if needed
conButtonCheck();
serialSend(4,2); //Sends stored information via serial
conButtonCheck();
///Coarse Millis Delay loop
while (millis() < timeNPulseMs){
delayMicroseconds(400);
conButtonCheck();}
///Fine Millis Delay Loop
while (millis() <= timeNPulseMs){}
///Microsecond Delay
delayMicroseconds(timeNPulseUs);
///Pulse
digitalWrite(12,HIGH);
delayMicroseconds(rVals[7]);
digitalWrite(12,LOW);
timeLPulseMs = timeNPulseMs;
timeLPulseUs = timeNPulseUs;
}
void conButtonCheck(){
bI[bICurrent]=~(PIND >> 3);
bICurrent++;
}
The issue is, looking at the output on an oscilloscope, my pulses have the right frequency, but random pulses shift, or are delayed by 1 or 2 milliseconds (about 5%-20% of the pulses). The timing is always off by milliseconds and not microseconds. So for 70Hz, I get mostly 14.286ms periods and few 15.286ms and even 16.286ms periods, and since the next pulse is based off when the last was suppose to happen, and equal number of 13.286ms and 12.286ms respectively. The button querying isn’t long enough to cause issues, even if it was, I’d expect the microseconds to be off too.
Is this due to system related internal interrupts? I tried turning off interrupts, but the code just froze up, was that due to the microsecondDelay function. Can I turn off only the interrupts not needed for the delay functions? Or is there a way to let the system do the routines that are messing up my timing at another point?
Thanks for any inputs.