I am building a quadruped robot and the example code uses a library call Flexitimer2. I have search through google and can't find where anyone has ported this library over for the ESP32. I am using the Sparkfun ESP32 Thing board which is so far working great.
Any help or direction as to how to port this library to work for the ESP32 would be greatly appreciated.
Port Flexitimer2 for ESP32
Re: Port Flexitimer2 for ESP32
Do you have a link to the original source for that library?
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
-
- Posts: 3
- Joined: Sun Aug 20, 2017 1:35 am
Re: Port Flexitimer2 for ESP32
Hi Kolban
Thanks for the quick response.
Here is the link to the GitHub for Flexitimer2...
https://github.com/wimleers/flexitimer2
They did add the capability for it work with the teensy as well.
Here is the .cpp
/*
FlexiTimer2.h - Using timer2 with a configurable resolution
Wim Leers <work@wimleers.com>
Based on MsTimer2
Javier Valencia <javiervalencia80@gmail.com>
History:
6/Jun/2014 - Added Teensy 3.0 & 3.1 support
16/Dec/2011 - Added Teensy/Teensy++ support (bperrybap)
note: teensy uses timer4 instead of timer2
25/April/10 - Based on MsTimer2 V0.5 (from 29/May/09)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <FlexiTimer2.h>
unsigned long FlexiTimer2::time_units;
void (*FlexiTimer2::func)();
volatile unsigned long FlexiTimer2::count;
volatile char FlexiTimer2::overflowing;
volatile unsigned int FlexiTimer2::tcnt2;
#if defined(__arm__) && defined(TEENSYDUINO)
static IntervalTimer itimer;
#endif
void FlexiTimer2::set(unsigned long ms, void (*f)()) {
FlexiTimer2::set(ms, 0.001, f);
}
/**
* @param resolution
* 0.001 implies a 1 ms (1/1000s = 0.001s = 1ms) resolution. Therefore,
* 0.0005 implies a 0.5 ms (1/2000s) resolution. And so on.
*/
void FlexiTimer2::set(unsigned long units, double resolution, void (*f)()) {
float prescaler = 0.0;
if (units == 0)
time_units = 1;
else
time_units = units;
func = f;
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TIMSK2 &= ~(1<<TOIE2);
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
ASSR &= ~(1<<AS2);
TIMSK2 &= ~(1<<OCIE2A);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2B |= (1<<CS22);
TCCR2B &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2B |= (1<<CS21);
TCCR2B &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2B |= ((1<<CS22) | (1<<CS20));
TCCR2B &= ~(1<<CS21);
prescaler = 128.0;
}
#elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
ASSR &= ~(1<<AS2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2 |= ((1<<CS22) && (1<<CS20));
TCCR2 &= ~(1<<CS21);
prescaler = 128.0;
}
#elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= ((1<<CS21) | (1<<CS20));
TCCR2 &= ~(1<<CS22);
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 256
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 256.0;
}
#elif defined (__AVR_ATmega32U4__)
TCCR4B = 0;
TCCR4A = 0;
TCCR4C = 0;
TCCR4D = 0;
TCCR4E = 0;
if (F_CPU >= 16000000L) {
TCCR4B = (1<<CS43) | (1<<PSR4);
prescaler = 128.0;
} else if (F_CPU >= 8000000L) {
TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4);
prescaler = 64.0;
} else if (F_CPU >= 4000000L) {
TCCR4B = (1<<CS42) | (1<<CS41) | (1<<PSR4);
prescaler = 32.0;
} else if (F_CPU >= 2000000L) {
TCCR4B = (1<<CS42) | (1<<CS40) | (1<<PSR4);
prescaler = 16.0;
} else if (F_CPU >= 1000000L) {
TCCR4B = (1<<CS42) | (1<<PSR4);
prescaler = 8.0;
} else if (F_CPU >= 500000L) {
TCCR4B = (1<<CS41) | (1<<CS40) | (1<<PSR4);
prescaler = 4.0;
} else {
TCCR4B = (1<<CS41) | (1<<PSR4);
prescaler = 2.0;
}
tcnt2 = (int)((float)F_CPU * resolution / prescaler) - 1;
OCR4C = tcnt2;
return;
#elif defined(__arm__) && defined(TEENSYDUINO)
// TODO: should this emulate the limitations and numerical
// range bugs from the versions above?
tcnt2 = resolution * 1000000.0;
return;
#else
#error Unsupported CPU type
#endif
tcnt2 = 256 - (int)((float)F_CPU * resolution / prescaler);
}
void FlexiTimer2::start() {
count = 0;
overflowing = 0;
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
#elif defined (__AVR_ATmega128__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
#elif defined (__AVR_ATmega8__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
#elif defined (__AVR_ATmega32U4__)
TIFR4 = (1<<TOV4);
TCNT4 = 0;
TIMSK4 = (1<<TOIE4);
#elif defined(__arm__) && defined(TEENSYDUINO)
itimer.begin(FlexiTimer2::_overflow, tcnt2);
#endif
}
void FlexiTimer2::stop() {
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TIMSK2 &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega32U4__)
TIMSK4 = 0;
#elif defined(__arm__) && defined(TEENSYDUINO)
itimer.end();
#endif
}
void FlexiTimer2::_overflow() {
count += 1;
if (count >= time_units && !overflowing) {
overflowing = 1;
count = count - time_units; // subtract time_uints to catch missed overflows
// set to 0 if you don't want this.
(*func)();
overflowing = 0;
}
}
#if defined (__AVR__)
#if defined (__AVR_ATmega32U4__)
ISR(TIMER4_OVF_vect) {
#else
ISR(TIMER2_OVF_vect) {
#endif
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TCNT2 = FlexiTimer2::tcnt2;
#elif defined (__AVR_ATmega128__)
TCNT2 = FlexiTimer2::tcnt2;
#elif defined (__AVR_ATmega8__)
TCNT2 = FlexiTimer2::tcnt2;
#elif defined (__AVR_ATmega32U4__)
// not necessary on 32u4's high speed timer4
#endif
FlexiTimer2::_overflow();
}
#endif // AVR
Thanks for the quick response.
Here is the link to the GitHub for Flexitimer2...
https://github.com/wimleers/flexitimer2
They did add the capability for it work with the teensy as well.
Here is the .cpp
/*
FlexiTimer2.h - Using timer2 with a configurable resolution
Wim Leers <work@wimleers.com>
Based on MsTimer2
Javier Valencia <javiervalencia80@gmail.com>
History:
6/Jun/2014 - Added Teensy 3.0 & 3.1 support
16/Dec/2011 - Added Teensy/Teensy++ support (bperrybap)
note: teensy uses timer4 instead of timer2
25/April/10 - Based on MsTimer2 V0.5 (from 29/May/09)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <FlexiTimer2.h>
unsigned long FlexiTimer2::time_units;
void (*FlexiTimer2::func)();
volatile unsigned long FlexiTimer2::count;
volatile char FlexiTimer2::overflowing;
volatile unsigned int FlexiTimer2::tcnt2;
#if defined(__arm__) && defined(TEENSYDUINO)
static IntervalTimer itimer;
#endif
void FlexiTimer2::set(unsigned long ms, void (*f)()) {
FlexiTimer2::set(ms, 0.001, f);
}
/**
* @param resolution
* 0.001 implies a 1 ms (1/1000s = 0.001s = 1ms) resolution. Therefore,
* 0.0005 implies a 0.5 ms (1/2000s) resolution. And so on.
*/
void FlexiTimer2::set(unsigned long units, double resolution, void (*f)()) {
float prescaler = 0.0;
if (units == 0)
time_units = 1;
else
time_units = units;
func = f;
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TIMSK2 &= ~(1<<TOIE2);
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
ASSR &= ~(1<<AS2);
TIMSK2 &= ~(1<<OCIE2A);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2B |= (1<<CS22);
TCCR2B &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2B |= (1<<CS21);
TCCR2B &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2B |= ((1<<CS22) | (1<<CS20));
TCCR2B &= ~(1<<CS21);
prescaler = 128.0;
}
#elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
ASSR &= ~(1<<AS2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2 |= ((1<<CS22) && (1<<CS20));
TCCR2 &= ~(1<<CS21);
prescaler = 128.0;
}
#elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= ((1<<CS21) | (1<<CS20));
TCCR2 &= ~(1<<CS22);
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 256
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 256.0;
}
#elif defined (__AVR_ATmega32U4__)
TCCR4B = 0;
TCCR4A = 0;
TCCR4C = 0;
TCCR4D = 0;
TCCR4E = 0;
if (F_CPU >= 16000000L) {
TCCR4B = (1<<CS43) | (1<<PSR4);
prescaler = 128.0;
} else if (F_CPU >= 8000000L) {
TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4);
prescaler = 64.0;
} else if (F_CPU >= 4000000L) {
TCCR4B = (1<<CS42) | (1<<CS41) | (1<<PSR4);
prescaler = 32.0;
} else if (F_CPU >= 2000000L) {
TCCR4B = (1<<CS42) | (1<<CS40) | (1<<PSR4);
prescaler = 16.0;
} else if (F_CPU >= 1000000L) {
TCCR4B = (1<<CS42) | (1<<PSR4);
prescaler = 8.0;
} else if (F_CPU >= 500000L) {
TCCR4B = (1<<CS41) | (1<<CS40) | (1<<PSR4);
prescaler = 4.0;
} else {
TCCR4B = (1<<CS41) | (1<<PSR4);
prescaler = 2.0;
}
tcnt2 = (int)((float)F_CPU * resolution / prescaler) - 1;
OCR4C = tcnt2;
return;
#elif defined(__arm__) && defined(TEENSYDUINO)
// TODO: should this emulate the limitations and numerical
// range bugs from the versions above?
tcnt2 = resolution * 1000000.0;
return;
#else
#error Unsupported CPU type
#endif
tcnt2 = 256 - (int)((float)F_CPU * resolution / prescaler);
}
void FlexiTimer2::start() {
count = 0;
overflowing = 0;
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
#elif defined (__AVR_ATmega128__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
#elif defined (__AVR_ATmega8__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
#elif defined (__AVR_ATmega32U4__)
TIFR4 = (1<<TOV4);
TCNT4 = 0;
TIMSK4 = (1<<TOIE4);
#elif defined(__arm__) && defined(TEENSYDUINO)
itimer.begin(FlexiTimer2::_overflow, tcnt2);
#endif
}
void FlexiTimer2::stop() {
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TIMSK2 &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega32U4__)
TIMSK4 = 0;
#elif defined(__arm__) && defined(TEENSYDUINO)
itimer.end();
#endif
}
void FlexiTimer2::_overflow() {
count += 1;
if (count >= time_units && !overflowing) {
overflowing = 1;
count = count - time_units; // subtract time_uints to catch missed overflows
// set to 0 if you don't want this.
(*func)();
overflowing = 0;
}
}
#if defined (__AVR__)
#if defined (__AVR_ATmega32U4__)
ISR(TIMER4_OVF_vect) {
#else
ISR(TIMER2_OVF_vect) {
#endif
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TCNT2 = FlexiTimer2::tcnt2;
#elif defined (__AVR_ATmega128__)
TCNT2 = FlexiTimer2::tcnt2;
#elif defined (__AVR_ATmega8__)
TCNT2 = FlexiTimer2::tcnt2;
#elif defined (__AVR_ATmega32U4__)
// not necessary on 32u4's high speed timer4
#endif
FlexiTimer2::_overflow();
}
#endif // AVR
Re: Port Flexitimer2 for ESP32
I used your "flexitimer2.h" library in an Arduino project. It was very useful for my project. Now, in order to obtain data more effectively from this project, I need to use an ESP32 (NodeMCU ESP32S). Would it be very difficult to modify the flexitimer2.h library to use it with ESP32S? Could you please help me with this?
Who is online
Users browsing this forum: No registered users and 56 guests