I'm using the exact piece of code in my ESP8266 library (which works OK ), but when used in a ESP32 library- I got an error:
This is the relevant code snip:
void myIOT32::_feedTheDog()
{
_wdtResetCounter++;
if (_wdtResetCounter >= _wdtMaxRetries)
{
sendReset("Dog goes woof");
}
}
void myIOT32::_startWDT()
{
wdt.attach(1, std::bind(&myIOT32::_feedTheDog, this)); // Start WatchDog
}
void myIOT32::sendReset(char *header)
{
char temp[150];
sprintf(temp, "[%s] - Reset sent", header);
if (useSerial)
{
Serial.println(temp);
}
if (strcmp(header, "null") != 0)
{
pub_msg(temp);
}
delay(1000);
ESP.restart();
}
and this is the error:
/home/guy/Documents/git/Arduino/libraries/myIOTesp32/myIOTesp32.cpp: In member function 'void myIOT32::_startWDT()':
/home/guy/Documents/git/Arduino/libraries/myIOTesp32/myIOTesp32.cpp:333:55: error: no matching function for call to 'Ticker::attach(int, std::_Bind_helper<false, void (myIOT32::*)(), myIOT32*>::type)'
wdt.attach(1, std::bind(&myIOT32::_feedTheDog, this)); // Start WatchDog
^
1 Answer 1
ESP32 ticker attach functions take pure function pointers with at max one argument type -- not a std::function
/ std::_Bind_helper
that std::bind
produces.
See code and types at https://github.com/espressif/arduino-esp32/blob/master/libraries/Ticker/src/Ticker.h#L38.
For the ESP8266 however, they do use a std::function
:
https://github.com/esp8266/Arduino/blob/master/libraries/Ticker/src/Ticker.h#L36
And that's why it works on ESP8266 and not on ESP32 -- either adapt the Ticker
library or rework your own code to not use member functions of classes.
Edit: You can easily rewrite your code to use a static helper function with one argument (the watchdog object itself) which then just calls the member function of that object. For this to work, the called function must be public. So a rewrite like
static void watchdog_timer_triggered_helper(myIOT32* watchdog) {
//needs to be public!
watchdog->_feedTheDog();
}
void myIOT32::_feedTheDog()
{
_wdtResetCounter++;
if (_wdtResetCounter >= _wdtMaxRetries)
{
sendReset("Dog goes woof");
}
}
void myIOT32::_startWDT()
{
wdt.attach(1, &watchdog_timer_triggered_helper, this); // Start WatchDog
}
void myIOT32::sendReset(char *header)
{
char temp[150];
sprintf(temp, "[%s] - Reset sent", header);
if (useSerial)
{
Serial.println(temp);
}
if (strcmp(header, "null") != 0)
{
pub_msg(temp);
}
delay(1000);
ESP.restart();
}
Since both the ESP32 and ESP8266 versions implement the
template<typename TArg>
void attach(float seconds, void (*callback)(TArg), TArg arg)
templated function this should work on both platforms now.
-
Thank you for explaining. Can you share an example how to rework ?guyd– guyd2020年06月06日 19:43:03 +00:00Commented Jun 6, 2020 at 19:43
-
@Guy.D see update.Maximilian Gerhardt– Maximilian Gerhardt2020年06月06日 20:12:52 +00:00Commented Jun 6, 2020 at 20:12
-
@Maximillian - thank you for you answer. I'm afraid your it a bit more than I understand :( , and I do not like to copy an answer without fully understand. Can you please explain more, or perhaps a more simple answer ( sorry... )guyd– guyd2020年06月07日 05:17:54 +00:00Commented Jun 7, 2020 at 5:17
-
@Guy.D didn't you write the initial code with
std::bind
, which is more complex than the function pointer used in the answer? Anyways I suggest reading up on C++ templates (attach()
is a templated function), pure function pointers andstd::function
in C++. I'd take some quiet lengthy text to explain that fully in my answer o_o.Maximilian Gerhardt– Maximilian Gerhardt2020年06月07日 13:51:37 +00:00Commented Jun 7, 2020 at 13:51 -
to be honest, when I found that answer for 8266, I just took it as a given solution without knowing how
bind
work for every detail.... ( shame me :) )....guyd– guyd2020年06月07日 17:47:48 +00:00Commented Jun 7, 2020 at 17:47