C/C++

How to catch ANY exception in gdb

In gdb, run

catch throw

in order to break on any exception that is being thrown.

If you want to only break on a specific exception type instead, use

catch throw [exception type]

 

Posted by Uli Köhler in C/C++

How to compile boost unit test program using CMake

Add this to your CMakeLists.txt:

#
# Compile test suite
#
find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)

add_executable(test_myprogram
    tests/MyTest.cpp
)
target_include_directories(test_myprogram PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include")
target_compile_features(test_myprogram PRIVATE cxx_std_17)

target_link_libraries(test_myprogram
                      ${Boost_FILESYSTEM_LIBRARY}
                      ${Boost_SYSTEM_LIBRARY}
                      ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
                      )
add_test(test_myprogram test_myprogram)
# make "make test" run the test program
add_custom_target(test
     DEPENDS myprogram
     COMMAND ./test_myprogram
)

In order to build the program and the test, run

make

In order to run the tests, use

make test
Posted by Uli Köhler in Boost, C/C++, CMake

How to fix CMake error Could not find a package configuration file provided by “boost_unit_test_framework”

Problem:

When compiling your CMake-based C++

CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:117 (find_package):
  Could not find a package configuration file provided by
  "boost_unit_test_framework" (requested version 1.71.0) with any of the
  following names:

    boost_unit_test_frameworkConfig.cmake
    boost_unit_test_framework-config.cmake

  Add the installation prefix of "boost_unit_test_framework" to
  CMAKE_PREFIX_PATH or set "boost_unit_test_framework_DIR" to a directory
  containing one of the above files.  If "boost_unit_test_framework" provides
  a separate development package or SDK, be sure it has been installed.
Call Stack (most recent call first):
  /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:182 (boost_find_component)
  /usr/share/cmake-3.16/Modules/FindBoost.cmake:443 (find_package)
  OCCUtils/CMakeLists.txt:58 (find_package)


-- Configuring incomplete, errors occurred!

Solution:

The error message is trying to tell you that you don’t have the boost unit test library installed (or CMake can’t find it).

On Ubuntu, for example, install it using

sudo apt -y install libboost-test-dev

On Windows you can install it using the prebuilt boost binaries for Windows.

Posted by Uli Köhler in C/C++, CMake

How to fix CMake error Could not find a package configuration file provided by “boost_filesystem”

Problem:

When compiling your CMake-based C++

CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:117 (find_package):
  Could not find a package configuration file provided by "boost_filesystem"
  (requested version 1.71.0) with any of the following names:

    boost_filesystemConfig.cmake
    boost_filesystem-config.cmake

  Add the installation prefix of "boost_filesystem" to CMAKE_PREFIX_PATH or
  set "boost_filesystem_DIR" to a directory containing one of the above
  files.  If "boost_filesystem" provides a separate development package or
  SDK, be sure it has been installed.
Call Stack (most recent call first):
  /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake:182 (boost_find_component)
  /usr/share/cmake-3.16/Modules/FindBoost.cmake:443 (find_package)
  CMakeLists.txt:58 (find_package)

Solution:

The error message is trying to tell you that you don’t have the boost filesystem library installed (or CMake can’t find it).

On Ubuntu, for example, install it using

sudo apt -y install libboost-filesystem-dev

On Windows you can install it using the prebuilt boost binaries for Windows.

Posted by Uli Köhler in C/C++, CMake

Minimal Boost C++ Unit test example

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE( test1 )
{
    BOOST_CHECK( 2 == 1 );
}

 

Posted by Uli Köhler in C/C++

How to ping gateway in ESP32

You can use the ESP32Ping library in order to easily ping the current gateway IP:

if(Ping.ping(WiFi.gatewayIP(), 1)) { // 1: Just one ping
  // TODO What to do on ping succes
  // Example: Print response time 
  Serial.print(Ping.averageTime()); // Unit: ms
  Serial.println(" ms");
} else {
  // TODO What to do if ping failed?
}

Full example:

#include <Arduino.h>
#include <WiFi.h>

#include <ESP32Ping.h>

void waitForWiFiConnectOrReboot(bool printOnSerial=true) {
  uint32_t notConnectedCounter = 0;
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      if(printOnSerial) {
        Serial.println("Wifi connecting...");
      }
      notConnectedCounter++;
      if(notConnectedCounter > 50) { // Reset board if not connected after 5s
          if(printOnSerial) {
            Serial.println("Resetting due to Wifi not connecting...");
          }
          ESP.restart();
      }
  }
  if(printOnSerial) {
    // Print wifi IP addess
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
  }
}

#define LED_BUILTIN 2

void setup() {
  Serial.begin(115200);
  WiFi.begin("MyWifiSSID", "MyWifiPassword");
  // Wait for wifi to be connected
  waitForWiFiConnectOrReboot();
  // Initialize LED
  pinMode(LED_BUILTIN,OUTPUT);
}

void loop() {
  if(Ping.ping(WiFi.gatewayIP())) {
    digitalWrite(LED_BUILTIN,HIGH);
    Serial.print(Ping.averageTime());
    Serial.println(" ms");
  } else {
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("Error :(");
  }

}

Example output

6.12 ms
5.12 ms
5.11 ms
5.16 ms
4.95 ms
4.88 ms
4.84 ms
7.67 ms
5.01 ms
4.87 ms
4.81 ms
4.80 ms
4.85 ms
5.08 ms
5.76 ms
4.54 ms
5.12 ms
2.77 ms
4.88 ms
4.84 ms
6.07 ms
5.08 ms
4.91 ms
6.04 ms
4.88 ms
4.98 ms
6.43 ms
8.18 ms
4.93 ms
5.17 ms
4.97 ms
5.46 ms
5.88 ms
4.78 ms
4.88 ms
6.03 ms
4.84 ms
5.70 ms
5.94 ms
7.25 ms
5.07 ms
4.78 ms
5.51 ms
4.99 ms
5.04 ms
4.79 ms
4.94 ms
4.81 ms
5.97 ms
5.85 ms
4.83 ms
4.80 ms
4.80 ms
6.29 ms
4.99 ms
5.04 ms
9.21 ms
5.20 ms
6.05 ms
6.14 ms
5.03 ms
4.90 ms
7.22 ms
5.06 ms
4.94 ms
9.03 ms
5.13 ms
11.97 ms
6.32 ms
6.12 ms
4.92 ms
4.92 ms
6.01 ms
4.96 ms
4.98 ms
4.94 ms
6.08 ms
6.11 ms
4.93 ms
5.05 ms
5.78 ms
4.47 ms
6.28 ms
5.02 ms
5.13 ms
5.11 ms
5.19 ms
8.89 ms
5.76 ms
5.18 ms
8.08 ms
4.97 ms
4.89 ms
4.70 ms
5.40 ms
7.46 ms
5.09 ms
4.95 ms
4.96 ms
5.01 ms
5.01 ms
4.89 ms
6.22 ms
6.76 ms
6.92 ms
6.10 ms
9.61 ms
5.29 ms
6.13 ms
5.15 ms
5.02 ms
5.03 ms
5.01 ms
6.13 ms
4.78 ms
3.90 ms
6.27 ms
8.07 ms
5.94 ms
4.50 ms
6.13 ms
4.99 ms
6.07 ms
4.80 ms
4.84 ms
4.95 ms
4.95 ms
6.78 ms
4.88 ms

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32, Networking

How to fix GCC error: implicit declaration of function …

Problem:

While trying to compile your C/C++ program, you see an error message like

../src/main.c:48:9: error: implicit declaration of function 'StartBenchmark' [-Werror=implicit-function-declaration]
         StartBenchmark();

Solution:

implicit declaration of function means that you are trying to use a function that has not been declared. In our example above, StartBenchmark is the function that is implicitly declared.

This is how you call a function:

StartBenchmark();

This is how you declare a function:

void StartBenchmark();

The following bullet points list the most common reasons and how to fix them:

  1. Missing #include: Check if the header file that contains the declaration of the function is #included in each file where you call the function (especially the file that is listed in the error message), before the first call of the function (typically at the top of the file). Header files can be included via other headers,
  2. Function name typo: Often the function name of the declaration does not exactly match the function name that is being called. For example, startBenchmark() is declared while StartBenchmark() is being called. I recommend to fix this by copy-&-pasting the function name from the declaration to wherever you call it.
  3. Bad include guard: The include guard that is auto-generated by IDEs often looks like this:
    #ifndef _EXAMPLE_FILE_NAME_H
    #define _EXAMPLE_FILE_NAME_H
    // ...
    #endif

    Note that the include guard definition _EXAMPLE_FILE_NAME_H is not specific to the header filename that we are using (for example Benchmark.h). Just the first of all header file names wil

  4. Change the order of the #include statements: While this might seem like a bad hack, it often works just fine. Just move the #include statements of the header file containing the declaration to the top. For example, before the move:
    #include "Benchmark.h"
    #include "other_header.h"

    after the move:

    #include "Benchmark.h"
    #include "other_header.h"
Posted by Uli Köhler in C/C++, GCC errors

How to measure performance on the PIC32

First, use MPLab Harmony Configurator 3 to enable the CORETIMER module for your project. No special configuration is neccessary.

The PIC32 Core Timer always runs at half the CPU frequency. For example, if the CPU is running at 200 MHz, the Core Timer will run at 100 MHz.

You an then use

uint32_t CORETIMER_CounterGet();

to get the current value of the core timer. Additionally, you can get the frequency of the Core Timer in Hz using

uint32_t CORETIMER_FrequencyGet();

Use the following snippet to measure how long it takes to run a specific function:

uint32_t t0 = CORETIMER_CounterGet();
run_my_func();
uint32_t t1 = CORETIMER_CounterGet();

After that, you can compute the number of seconds it took to run the function using e.g.

uint32_t tdelta = t1 - t0;
float seconds = tdelta / (float)CORETIMER_FrequencyGet();

or the number of milliseconds:

uint32_t tdelta = t1 - t0;
float milliseconds = tdelta / (CORETIMER_FrequencyGet() / 1000.0);

or the number of microseconds:

uint32_t tdelta = t1 - t0;
float microseconds = tdelta / (CORETIMER_FrequencyGet() / 1000000.0);

 

Posted by Uli Köhler in C/C++, Electronics, Embedded

How to fix GCC lots of undefined reference to std:: functions

Problem:

When trying to compile your C++ application, you see lots of undefined reference to messages like

AutoBenchmark.cpp:(.text+0x6a): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x81): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x8a): undefined reference to `std::chrono::_V2::system_clock::now()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0xcd): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0xe6): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::~AutoBenchmark()':
AutoBenchmark.cpp:(.text+0x17e): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x18e): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::Record(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
AutoBenchmark.cpp:(.text+0x1db): undefined reference to `std::chrono::_V2::system_clock::now()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::Record(char const*)':
AutoBenchmark.cpp:(.text+0x252): undefined reference to `std::allocator<char>::allocator()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x288): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x294): undefined reference to `std::allocator<char>::~allocator()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x2b9): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x2ce): undefined reference to `std::allocator<char>::~allocator()'
/usr/bin/ld: /tmp/cc356AdP.o: in function `AutoBenchmark::Print()':
AutoBenchmark.cpp:(.text+0x316): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::length() const'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x332): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x337): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x344): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x572): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x577): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x59c): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x5ab): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x5c2): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x5d1): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x607): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x60c): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x631): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x640): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x657): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x666): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x69c): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6a1): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6c6): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6d5): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6ec): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x6fb): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x731): undefined reference to `std::cout'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x736): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x75b): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x76a): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x781): undefined reference to `std::ostream::operator<<(double)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x790): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
/usr/bin/ld: AutoBenchmark.cpp:(.text+0x7c6): undefined reference to `std::cout'

Solution:

You need to link the stdc++ library by adding -lstdc++ to your compiler/linker flags.

For example, instead of

gcc -o myprogram *.c

use

gcc -o myprogram *.c -lstdc++

 

Posted by Uli Köhler in C/C++, GCC errors

How to fix GCC error: expected constructor, destructor, or type conversion before __declspec(dllexport)

Problem:

When trying to compile an application on Linux, you see a compiler error message like

myheader.h:23:12: error: expected constructor, destructor, or type conversion before ‘(’ token
   23 |  __declspec(dllexport) int myfunc(

Solution:

__declspec(dllexport) is a Windows-specific feature and not available on Linux. In order to fix it in a compatible way, add this code either in a header that is included in every file containing __declspec(dllexport) or add it in each file where the error occurs:

#ifdef __linux__
#define __declspec(v)
#endif

This will basically ignore any __declspec() call on the preprocessor level.

Posted by Uli Köhler in C/C++, GCC errors

How to fix GCC undefined reference to `sqrt’

Problem:

When trying to compile your application using gcc, you see an error message like

/usr/bin/ld: /tmp/ccxPIowU.o: in function `run_mymath':
mathstuff.c:(.text+0x15d): undefined reference to `sqrt'

Solution:

You need to link the math library using the -lm flag (-lxxx means: “link the xxx library”, i.e. -lm means “link the m” library)

For example, instead of

gcc -o myprogram *.c

use

gcc -o myprogram *.c -lm

 

Posted by Uli Köhler in C/C++, GCC errors

How to fix GCC undefined reference to `_finite’ or implicit declaration of function ‘_finite’

Problem:

If you’re trying to compile Windows code on Linux, you will often see messages like

lmmin.c:261:10: warning: implicit declaration of function ‘_finite’; did you mean ‘finite’? [-Wimplicit-function-declaration]
  116 |     if(!_finite(myvalue)){

or

/usr/bin/ld: mymath.c:(.text+0x1057): undefined reference to `_finite'

and your code won’t compile.

Solution:

_finite is a function that is only available on Windows. In order to use it on Linux using GCC or G++, one option is to use isfinite() from math.h:

#include <math.h>

#define _finite(v) (isfinite((v)))

In case that function is not available (like on some Microcontroller platforms), you can use __builtin_isfinite(). Note that glibc defines isfinite() as an alias for __builtin_isfinite(). Use it like this:

#define _finite(v) (__builtin_isfinite(v))

In case you want to have code that is compatible with both platforms (Windows and Linux), use

#ifdef __linux__
#define _finite(v) (__builtin_isfinite(v))
#endif

or

#include <math.h>

#ifdef __linux__
#define _finite(v) (isfinite((v)))
#endif

 

Posted by Uli Köhler in C/C++, GCC errors

Minimal ESP32 NTP client example using NTPClient_Generic and PlatformIO

Example of using NTPClient_Generic

main.cpp

#include <Arduino.h>
#include <WiFi.h>
#include <NTPClient_Generic.h>

#define TIME_ZONE_OFFSET_HRS 1 // UTC+1 for Germany, winter time
#define NTP_UPDATE_INTERVAL_MS 60000L // Update every 60s automatically
WiFiUDP ntpUDP;
NTPClient ntpClient(ntpUDP, "europe.pool.ntp.org", (3600 * TIME_ZONE_OFFSET_HRS), NTP_UPDATE_INTERVAL_MS);

void ntpUpdateTask(void* param) {
  while(true) {
    // Update NTP. This will only ACTUALLY update if
    // the NTP client has not updated for NTP_UPDATE_INTERVAL_MS
    ntpClient.update();
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void setup() {
  Serial.begin(115200);
  // Force reset Wifi to avoid failure to connect
  WiFi.disconnect(true);
  // Set hostname
  WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
  WiFi.setHostname("ESP-NTP");
  // Connect to Wifi
  WiFi.begin("MyWifiSSID", "MyWifiPassword");
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      Serial.println("Wifi connecting...");
  }

  // Start NTP client (i.e. start listening for NTP packets)
  ntpClient.begin();
  // Create task to automatically update NTP in the background
  xTaskCreate(ntpUpdateTask, "NTP update", 2000, nullptr, 1, nullptr);
}

void loop() {
  delay(1000);
  if (ntpClient.updated()) {
    Serial.println("# Time in sync with NTP server");
  } else {
    Serial.println("# TIME NOT IN SYNC WITH NTP SERVER !");
    return; // Do not print time
  }

  Serial.println("UTC : " + ntpClient.getFormattedUTCTime());
  Serial.println("UTC : " + ntpClient.getFormattedUTCDateTime());
  Serial.println("LOC : " + ntpClient.getFormattedTime());
}

platformio.ini

[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
lib_deps =
    khoih.prog/NTPClient_Generic @ ^3.2.2
    Time

Example output:

Wifi connecting...
Wifi connecting...
Wifi connecting...
# TIME NOT IN SYNC WITH NTP SERVER !
# Time in sync with NTP server
UTC : 01:22:07
UTC : 01:22:07 Sun 07 Feb 2021
LOC : 02:22:07
# Time in sync with NTP server
UTC : 01:22:08
UTC : 01:22:08 Sun 07 Feb 2021
LOC : 02:22:08
# Time in sync with NTP server
UTC : 01:22:09
UTC : 01:22:09 Sun 07 Feb 2021
LOC : 02:22:09

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32, PlatformIO

How to get current gateway IP address on ESP8266/ESP32

In order to get the current gateway IP address on the ESP8266 or ESP32, use:

WiFi.gatewayIP();

In order to print the gateway IP address on the serial port, use

Serial.println("Gateway IP address: ");
Serial.println(WiFi.gatewayIP());

In order to get the gateway IP address as string, use

String gatewayIP = WiFi.gatewayIP().toString();

 

Posted by Uli Köhler in C/C++, Embedded, ESP8266/ESP32, PlatformIO

ESP32 minimal WebSocket example (ESPAsyncWebserver / PlatformIO)

Minimal firmware to use WebSockets on the ESP32 using ESPAsyncWebserver:

main.cpp

#include <Arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

AsyncWebServer server(80);
AsyncWebSocket ws("/ws");

AsyncWebSocketClient* wsClient;
 
void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
  if(type == WS_EVT_CONNECT){
    wsClient = client;
  } else if(type == WS_EVT_DISCONNECT){
    wsClient = nullptr;
  }
}

/**
 * Wait for WiFi connection, and, if not connected, reboot
 */
void waitForWiFiConnectOrReboot(bool printOnSerial=true) {
  uint32_t notConnectedCounter = 0;
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      if(printOnSerial) {
        Serial.println("Wifi connecting...");
      }
      notConnectedCounter++;
      if(notConnectedCounter > 50) { // Reset board if not connected after 5s
          if(printOnSerial) {
            Serial.println("Resetting due to Wifi not connecting...");
          }
          ESP.restart();
      }
  }
  if(printOnSerial) {
    // Print wifi IP addess
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
  }
}


void setup() { 
  Serial.begin(115200);
  WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
  WiFi.setHostname("ESP-Websocket-Test");

  WiFi.begin("MyWifiSSID", "MyWifiPassword");
  waitForWiFiConnectOrReboot();

  // Start webserver
  ws.onEvent(onWsEvent);
  server.addHandler(&ws);
  server.begin();
}

uint64_t counter = 0;
void loop() {
  // If client is connected ...
  if(wsClient != nullptr && wsClient->canSend()) {
    // .. send hello message :-)
    wsClient->text("Hello client");
  }

  // Wait 10 ms
  delay(10);
}

platformio.ini:

[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
lib_deps =
    ESP Async [email protected]
    [email protected]

Python code for testing:

import websocket
ws = websocket.WebSocket()
ws.connect("ws://192.168.1.211/ws")
while True:
    result = ws.recv()
    print(result)

This will print Hello Client many times a second.

Posted by Uli Köhler in C/C++, ESP8266/ESP32, PlatformIO

How to fix ESP32 too few arguments to function ‘esp_err_t esp_wifi_sta_wpa2_ent_enable(const esp_wpa2_config_t*)’

Problem:

While trying to compile your ESP32 application, you see this compiler error:

src\main.cpp: In function 'void wifiConnectWPAEAP(const char*, const char*, const char*, const char*)':
src\main.cpp:23:32: error: too few arguments to function 'esp_err_t esp_wifi_sta_wpa2_ent_enable(const esp_wpa2_config_t*)'   esp_wifi_sta_wpa2_ent_enable();
                                ^

Solution:

Replace

esp_wifi_sta_wpa2_ent_enable();

by

esp_wpa2_config_t config = WPA2_CONFIG_INIT_DEFAULT();
esp_wifi_sta_wpa2_ent_enable(&config);
Posted by Uli Köhler in C/C++, Embedded, ESP8266/ESP32

How to fix ESP32 fatal error: ESP8266WiFi.h: No such file or directory

Problem:

While trying to compile your ESP32 application, you see this compiler error:

fatal error: ESP8266WiFi.h: No such file or directory

Solution:

ESP8266WiFi.h is the Wifi header for the ESP8266. For the ESP32, it’s named WiFi.h. In order to fix the issue, replae

#include <ESP8266WiFi.h>

by

#include <WiFi.h>
Posted by Uli Köhler in C/C++, Embedded, ESP8266/ESP32

How to fix Alpine Linux fatal error: stdio.h: No such file or directory

Problem:

When trying to compile a C/C++ program or library on Alpine Linux, you see an error message like

/home/user/test.cpp:5:10: fatal error: stdio.h: No such file or directory
  123 | #include <stdio.h>
      |          ^~~~~~~~~

Solution:

Install the libc headers using

apk add musl-dev

 

Posted by Uli Köhler in Alpine Linux, C/C++, GCC errors, Linux

Minimal ESP8266 WiFi example

#include <Arduino.h>
#include <ESP8266WiFi.h>

void setup() {
  Serial.begin(115200);
  WiFi.begin("MySSID", "MyPassword");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Wifi connecting...");
    delay(500);
  }
  Serial.println("Wifi connected");
}

void loop() {
  // put your main code here, to run repeatedly:
}

 

Posted by Uli Köhler in C/C++, ESP8266/ESP32

Where to find info about mbed mbed_app.json overridable parameters?

The first resource can have a look at is the platform configuration option page. Additionally, check the manual on how to use the mbed CLI to show configuration options.

Additionally, you can look at targets.json on GitHub:

For example, "Target" => "config" => "default-adc-vref" would need to be entered like this into mbed_app.json:

{
    "target_overrides": {
      "*": {
          "target.default-adc-vref": 3300
      }
    }
}

 

Posted by Uli Köhler in C/C++, mbed, PlatformIO