Timer.stop() not executing because of priority?

I am attempting to use serial commands to start and stop a timer that prints ADC values at a sampling rate of 500 Hz using the code below. A ‘1’ will start the timer and turn on an LED. a ‘2’ will stop the timer and turn off the same LED.

int val0 = 0;                    // variable to store the read value
int val1 = 0;
int val2 = 0;
int count = 0;
char inByte;

void Hertz()
{
    count++;
    val0 = analogRead(A0);  // read the input pin
    //val1 = analogRead(A1);
    //val2 = analogRead(A2);
    Serial1.println(count);
    Serial1.println(val0);
    //Serial1.println(val1);
    //Serial1.println(val2);

}

Timer timer(2, Hertz);  // 500 Hz


void setup()
{
   Serial1.begin(38400);
   Serial1.println("***redacted***");
   pinMode(D7, OUTPUT);
   setADCSampleTime(ADC_SampleTime_3Cycles);
}

void serialEvent1()
{
    if (Serial1.available())
    {
        char inByte = Serial1.read();
        if (inByte == '1'){
            digitalWrite(D7, HIGH);             //turn LED on
            Serial1.println(Time.now());        //unix time stamp
            timer.start();
        }
        if(inByte == '2'){
            digitalWrite(D7, LOW);              //turn LED off
            timer.stop();
            Serial1.println(Time.now());        //unix time stamp
            count = 0;
        }
        
    }
}
    
void loop(){
    serialEvent1();
}

The timer will start fine, but the timer will not stop once i send the stop command (a serial char ‘2’). However, the Particle Photon that I am using will still turn the LED off and reset the variable “count,” but won’t stop the timer. After playing around with some timer.changePeriod() and delay() function inserted in various places within the code, I am fairly certain that it is a priority issue with the timer actually interrupting the very call that’s supposed to stop it- having a ‘2’ as the timer’s input sets the timer to interrupt every 2 milliseconds, so somewhat fast. I am fairly knowledgeable on priority timing dependencies/interrupts, but cannot seem to solve this issue. I would very much appreciate any information or advice pertaining to getting my timer.stop() function to call. Thanks!

@aStringer4, did you try putting Timer.stop() at the start of the callback and a Timer.reset at the end? Timers don’t create “interrupts”. Instead, they run off a FreeRTOS thread so the code above is like disabling/enabling timer interrupts (but not!). Keeping your callbacks short relative to the timer period is important.

I have now done this, but it doesn’t provide any tangible results- a better practice to get into the habit of I’m sure though. However, what I have found is that making the timer period longer increases the percentage of times the timer will actually stop when given the stop command. After just sending ‘start’ and ‘stop’ commands for a bit with a timer every 2 milliseconds, the timer will actually stop about 20%-30% of the timer (I’ll just keeping sending stop commands until it actually stops). When I increase the timer to every 3 milliseconds, I have a 100% rate of stoppage when the command is sent. I have also found that these percentage decrease as a direct function of the amount of Serial1.println() commands I have in the timer.

Is this just a hardware constraint that I’m going to have to work around?

@aStringer4, the FreeRTOS slice time is 1ms which might explain the 3ms condition. That is, the timer thread doesn’t get serviced until the next 1ms slice. @mdma would need to add sanity to this.

You’re using Serial1 from multiple threads - this isn’t a good idea. At the least you’ll get garbled output, and may produce a deadlock.

All serial output should be handled on one thread, typically the main thread. You can send output from the timer thread by using a circular buffer.

Btw, profanity isn’t welcomed here, please don’t include gratuitous profanity in example code.

4 Likes