Dear all, I need an accurate periodic timer whose frequency I can change while the program is running.
I have an Arduino R4 WiFi.
Phil Schatzmann's excellent article (bless him) shows how to set up such a timer, but not how to change its frequency if this has already been set.
After not getting very far by looking at FspTimer.h and FspTimer.cpp on github, I ended up doing what seemed sensible to me, which is shown in the sketch below.
With this sketch, I type the frequency into the serial port and the board LED flashes at this frequency. I can re-enter the frequency and the LED will flash at the new frequency.
The sketch works fine, but I have the following questions:
- Is what I have done correct?
- Is there a more elegant way of doing this?
- I understand what the functions begin/end do. But could someone be so kind as to explain the purpose of the open/close and start/stop functions? What about setup_overflow_irq()?
#include <FspTimer.h>
FspTimer FTimer;
int iLed = LED_BUILTIN;
volatile int iLedState;
void vTimerCallback(timer_callback_args_t __attribute((unused)) *p_args) {
if (iLedState == LOW) {
digitalWrite(iLed, HIGH);
iLedState = HIGH;
}
else {
digitalWrite(iLed, LOW);
iLedState = LOW;
}
}
bool bBeginTimer(float rate) {
/* This is from */
/* https://www.pschatzmann.ch/home/2023/07/01/under-the-hood-arduino-uno-r4-timers/ */
uint8_t timer_type = GPT_TIMER;
int8_t tindex = FspTimer::get_available_timer(timer_type);
if (tindex < 0){
tindex = FspTimer::get_available_timer(timer_type, true);
}
if (tindex < 0){
return false;
}
FspTimer::force_use_of_pwm_reserved_timer();
if(!FTimer.begin(TIMER_MODE_PERIODIC, timer_type, tindex, rate, 0.0f, vTimerCallback)){
return false;
}
if (!FTimer.setup_overflow_irq()){
return false;
}
if (!FTimer.open()){
return false;
}
if (!FTimer.start()){
return false;
}
return true;
}
bool bHaltTimer(void) {
if (!FTimer.stop()){
return false;
}
/* Skipping Ftimer.close() as it is already included in FspTimer::end() in */
/* FspTimer.cpp */
/* if (!FTimer.close()){ */
/* return false; */
/* } */
FTimer.end();
return true;
}
void setup() {
pinMode(iLed, OUTPUT);
/* start serial port at 9600 bps and wait for port to open: */
Serial.begin(9600);
/* wait for serial port to connect. Needed for native USB port only */
while (!Serial) {}
Serial.println("Enter frequency in Hz");
/* Start the timer with an arbitrary frequency (1Hz) */
bBeginTimer(1);
}
void loop() {
String sInput;
float fInput;
if (Serial.available()) {
sInput = Serial.readStringUntil('\n');
fInput = sInput.toFloat();
if (fInput > 0.00) {
Serial.println(fInput);
bHaltTimer();
bBeginTimer(fInput);
}
else {
Serial.println("Erroneous value entered");
}
}
}
Any assistance would be thoroughly appreciated! Many thanks.