Electronics

RTC battery lifetime online calculator

Free calculator to estimate how long your battery (e.g. CR2032) will last in your microcontroller RTC application. Note: The default capacity of 220 mAh is a typical capacity for a CR2032 coin cells.

TechOverflow calculators:
You can enter values with SI suffixes like 12.2m (equivalent to 0.012) or 14k (14000) or 32u (0.000032).
The results are calculated while you type and shown directly below the calculator, so there is no need to press return or click on a Calculate button. Just make sure that all inputs are green by entering valid values.

Ah

A

Posted by Uli Köhler in Calculators, Electronics

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 delay() by milliseconds / microseconds on the PIC32

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

After that, use

CORETIMER_DelayMs(uint32_t delay_ms)

to delay for a given number of milliseconds or use

CORETIMER_DelayUs(uint32_t delay_us)

to delay for a given number of microseconds.

Posted by Uli Köhler in Electronics, Embedded

How to fix PIC32 Curiosity Board gray / greyed out in MPLab X

Problem:

You want to program your PIC32 Curiosity board in MPLab X using the PicKit 4 on board (PKoB4) programmer that is included on the Curiosity board.

However, when you try to select the Curiosity board in the project settings, it is greyed out and you can only select the Simulator or No Tool.

Solution:

You need to reprogram the firmware of the PicKit On Board using the MPLab X IPE which is installed alongside the MPLab X IDE.

Open MPLab X IPE, open the Tools menu and select Hardware Tool Emergency Boot Firmware Recovery

After that, closely follow the instructions and reprogram the firmware for the PicKit On Board 4 programmer.

After reflashing the PKoB4 is successful, you will be able to select the Curiosity Board in MPLab X IDE.

Posted by Uli Köhler in Electronics, Embedded

Where to set MPLab X PIC32 heap size

In order to set the heap size, use MPLab Harmony 3, click on System in the Project Graph, then open the tree as follows:

  • Device & Project configuration
  • Project configuration
  • Tool Chain Selections
  • XC32 Global Options
  • Linker
  • General

and set Heap Size (bytes) to the desired value.

Additionally, you need to set the heap size in the project options => XC32 options => xc32-ld options:

Posted by Uli Köhler in Electronics, Embedded

How long does a I²C message transmission take? Online calculator

Enter the number of data bytes to be transmitted (excluding the start byte containing the slave address & RW bit).

TechOverflow calculators:
You can enter values with SI suffixes like 12.2m (equivalent to 0.012) or 14k (14000) or 32u (0.000032).
The results are calculated while you type and shown directly below the calculator, so there is no need to press return or click on a Calculate button. Just make sure that all inputs are green by entering valid values.

bytes

N_{\text{bits}} = (N_{\text{bytes}} + 1) \cdot 9\Delta T_{\text{transmission}} = N_{\text{bits}} / \text{bitrate}

Posted by Uli Köhler in Calculators, Electronics

Comprehensive AWG to mm² area / mm diameter chart

This chart covers wire sizes from 0000 AWG to AWG41

AWGmm² areamm diameter
4/0 or 0000 AWG10711.68 mm
3/0 or 000 AWG8510.40384 mm
2/0 or 00 AWG67.4 mm²9.26592 mm
0 AWG53.5 mm²8.25246 mm
1 AWG42.4 mm²7.35 mm
2 AWG33.6 mm²6.54 mm
3 AWG26.7 mm²5.83 mm
4 AWG21.2 mm²5.19 mm
5 AWG16.8 mm²4.62 mm
6 AWG13.3 mm²4.11 mm
7 AWG10.6 mm²3.67 mm
8 AWG8.35 mm²3.26 mm
9 AWG6.62 mm²2.91 mm
10 AWG5.27 mm²2.59 mm
11 AWG4.15 mm²2.3 mm
12 AWG3.31 mm²2.05 mm
13 AWG2.63 mm²1.83 mm
14 AWG2.08 mm²1.63 mm
15 AWG1.65 mm²1.45 mm
16 AWG1.31 mm²1.29 mm
17 AWG1.04 mm²1.15 mm
18 AWG0.823 mm²1.024 mm
19 AWG0.653 mm²0.912 mm
20 AWG0.519 mm²0.812 mm
21 AWG0.412 mm²0.723 mm
22 AWG0.325 mm²0.644 mm
23 AWG0.259 mm²0.573 mm
24 AWG0.205 mm²0.511 mm
25 AWG0.163 mm²0.455 mm
26 AWG0.128 mm²0.405 mm
27 AWG0.102 mm²0.361 mm
28 AWG0.0804 mm²0.321 mm
29 AWG0.0646 mm²0.286 mm
30 AWG0.0503 mm²0.255 mm
31 AWG0.0404 mm²0.16002 mm
32 AWG0.0320 mm²0.2032 mm
33 AWG0.0254 mm²0.18034 mm
34 AWG0.0201 mm²0.16002 mm
35 AWG0.0160 mm²0.14224 mm
36 AWG0.0127 mm²0.12700 mm
37 AWG0.0100 mm²0.11430 mm
38 AWG0.00797 mm²0.10160 mm
39 AWG0.00632 mm²0.08890 mm
40 AWG0.00501 mm²0.07874 mm
Posted by Uli Köhler in Electronics

What are typical insertion & withdrawal forces for PCIe connectors?

This Amphenol datasheet lists 1.15 N/pin insertion force and 0.15 N/pin withdrawal force.

Based on these values:

  • A PCIe x1 connector with 36 pins
    • insertion force of 36*1.15N = 41.4 N = 4.22 kgf and
    • withdrawal force of 36*0.15N = 5.4 N = 0.551 kgf
  • A PCIe x4 connector with 64 pins
    • insertion force of 64*1.15N = 73.6 N = 7.505 kgf and
    • withdrawal force of 64*0.15N = 9.6 N = 0.979 kgf
  • A PCIe x8 connector with 98 pins
    • insertion force of 98*1.15N = 112.7 N = 11.492 kgf and
    • withdrawal force of 98*0.15N = 14.7 N = 1.499 kgf
  • A PCIe x16 connector with 164 pins
    • insertion force of 164*1.15N = 188.6 N = 19.232 kgf and
    • withdrawal force of 164*0.15N = 24.6 N = 2.509 kgf
  • A PCIe x24 connector with 230 pins
    • insertion force of 230*1.15N = 264.5 N = 4.22 kgf and
    • withdrawal force of 230*0.15N = 34.5 N = 3.518 kgf
Posted by Uli Köhler in Electronics

How many pins does a PCIe connector have?

A PCIe x1 connector has 36 pins (18 pins on each side)

A PCIe x4 connector has 64 pins (32 pins on each side)

A PCIe x8 connector has 98 pins (49 pins on each side)

A PCIe x16 connector has 164 pins (82 pins on each side)

A PCIe x24 connector has 230 pins (115 pins on each side)

Source: Samtec catalog, Amphenol datasheet (x24)

 

Posted by Uli Köhler in Electronics

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 Servo controllable via HTTP JSON API / web browser

This sketch for PlatformIO  allows you to use the ESP32 as a Servo controller (servo on pin D25) that connects to Wifi and can be controller using a simple HTTP API. The webserver is implemented using ESPAsyncWebserver. Also see ESP32 minimal JSON webserver example for PlatformIO (ESPAsyncWebserver) in case you are not familiar with that library. This example is not a finished application but a minimal starting point to build your own application.

main.cpp

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

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

AsyncWebServer server(80);

/**
 * 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());
  }
}

Servo servo;

void setup() {
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);

  Serial.begin(115200);

  WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
  WiFi.setHostname("ESP-Servo");

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

  // Attach servo to pin 25
  servo.attach(25, 1000, 2000);
  
  // Configure HTTP routes
  server.on("/api/set-servo", HTTP_GET, [](AsyncWebServerRequest *request) {
      float value = request->arg("value").toFloat();
      servo.write(value);
      // Send {status: "ok"}
      AsyncResponseStream *response = request->beginResponseStream("application/json");
      DynamicJsonDocument json(1024);
      json["status"] = "ok";
      serializeJson(json, *response);
      request->send(response);
  });
  
  // Start webserver
  server.begin();
}

void loop() {
}

platformio.ini

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

How to use

Insert your Wifi credentials in the line

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

and upload the firmware. Now open http://[ip address of the ESP32]/api/set-servo?value=0.0. Note that in the current version of the firmware, you can not use value=10 but you must use value=10.0.

Posted by Uli Köhler in 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

ESP32 minimal JSON webserver example for PlatformIO (ESPAsyncWebserver)

This is my recommended starting point to get a webserver running on the ESP32 using PlatformIO:

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

AsyncWebServer server(80);

void setup() { 
  Serial.begin(115200);
  // Connect Wifi, restart if not connecting
  // https://techoverflow.net/2021/01/21/how-to-fix-esp32-not-connecting-to-the-wifi-network/
  WiFi.begin("MyWifiSSID", "MyWifiPassword");
  uint32_t notConnectedCounter = 0;
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      Serial.println("Wifi connecting...");
      notConnectedCounter++;
      if(notConnectedCounter > 50) { // Reset board if not connected after 5s
          Serial.println("Resetting due to Wifi not connecting...");
          ESP.restart();
      }
  }
  Serial.print("Wifi connected, IP address: ");
  Serial.println(WiFi.localIP());

  // Initialize webserver URLs
  server.on("/api/wifi-info", HTTP_GET, [](AsyncWebServerRequest *request) {
      AsyncResponseStream *response = request->beginResponseStream("application/json");
      DynamicJsonDocument json(1024);
      json["status"] = "ok";
      json["ssid"] = WiFi.SSID();
      json["ip"] = WiFi.localIP().toString();
      serializeJson(json, *response);
      request->send(response);
  });

  // Start webserver
  server.begin();
}

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

Remember to replace your Wifi credentials! WiFi.begin("MyWifiSSID", "MyWifiPassword");

To your platformio.ini add:

monitor_speed = 115200
lib_deps =
    ESP Async [email protected]
    [email protected]

My complete platformio.ini looks like this:

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

Use PlatformIO’s Upload and Monitor so you can see the IP address of the device in your Wifi network, for example:

Wifi connected, IP address: 192.168.178.90

then goto http://192.168.178.90/api/wifi-info (replace 192.168.178.90 by the IP address of the ESP32 that you can see on the command line!

You should now see JSON like:

{
     status: "ok",
     ssid: "MyWifiSSID",
     ip: "192.168.178.90"
}

Remember that you can use a browser plugin like JSON Viewer for Chrome in order to auto-format JSON documents!

Posted by Uli Köhler in ESP8266/ESP32

How to switch on/off ALL3073v2WLAN using HTTP (JSON API)

The ALL3073v2WLAN provides a JSON API to switch on or off the power for the attached device.

In order to enable 230V power for the attached device, use this URL (HTTP GET request):

http://IP-Address-of-ALL3073/xml/jsonswitch.php?id=1&set=1

In order to disable 230V power for the attached device, use this URL (HTTP GET request):

http://IP-Address-of-ALL3073/xml/jsonswitch.php?id=1&set=0

Note that id=1 will always stay the same since 1 is the ID of the actor controlling the power, just set=0 or set=1 are different,

Posted by Uli Köhler in Electronics, Networking

How to fix ESP32 not connecting to the Wifi network

If you use a program like our minimal ESP32 wifi example:

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

void setup() {
  Serial.begin(115200);
  WiFi.begin("MyWifiNetworkName", "MyWifiPassword");
  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:
}

and you just see a loop of

Wifi connecting...

messages, press the RESET button of your board (or unplug and re-plug its power to reset) and and try again. If you still see just Wifi connecting... messages after trying to reset 5 times, most likely your wifi credentials are wrong or the ESP32 can’t see your Wifi network!

Otherwise, if your ESP32 sometimes connects to the Wifi network almost immediately and sometimes it doesn’t seem to connect at all, use this code instead to automatically reset the ESP32 if it doesn’t connect within 5 seconds:

// Wait for wifi to be connected
uint32_t notConnectedCounter = 0;
while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.println("Wifi connecting...");
    notConnectedCounter++;
    if(notConnectedCounter > 50) { // Reset board if not connected after 5s
        Serial.println("Resetting due to Wifi not connecting...");
        ESP.restart();
    }
}

Full example:

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

void setup() {
  Serial.begin(115200);
  WiFi.begin("MyWifiSSID", "MyWifiPassword");

  // Wait for wifi to be connected
  uint32_t notConnectedCounter = 0;
  while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      Serial.println("Wifi connecting...");
      notConnectedCounter++;
      if(notConnectedCounter > 50) { // Reset board if not connected after 5s
          Serial.println("Resetting due to Wifi not connecting...");
          ESP.restart();
      }
  }
  Serial.print("Wifi connected, IP address: ");
  Serial.println(WiFi.localIP());
}

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

Alternatively, use this function:

/**
 * 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());
  }
}

 

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