text:
object of "ESPAsyncWebServer" causing conflict
I have been trying to develop multi cpp project in platformio and whenever I define ESPAsyncWebServer class object with the extern in defines.h and declare it in main.cpp I am getting scarry looking error 'HTTP_DELETE' conflicts with a previous declaration But when I define ESPAsyncWebServer class object without the extern in main.cpp instead I am not getting any error. Can you help in this regard?
main.cpp:
#include "defines.h"
#include <AsyncMQTT_ESP32.h>
#include <WebServer_ESP32_W5500.h>

AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;

/* ESPAsyncWebServer */
WiFiClient clientWiFi;
AsyncWebServer serverAsyncWeb(80);
AsyncWebSocket WebSocketAsync("/ws");
/* Processors */

String prc(const String &var)
{
  return String();
}

/* Processors End */
void allAsyncWebServer()
{
  serverAsyncWeb.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
                    { request->send(SPIFFS, "/index.htm", String(), false, prc); }); /// log
}

/* allAsyncWebServer End */

/* WebSocketAsync */

void AsyncWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
{
  switch (type)
  {
  case WS_EVT_CONNECT:
    Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
    break;
  case WS_EVT_DISCONNECT:
    Serial.printf("WebSocket client #%u disconnected\n", client->id());
    break;
  case WS_EVT_DATA:
    // handleWebSocketMessage(arg, data, len);
    break;
  case WS_EVT_PONG:
  case WS_EVT_ERROR:
    break;
  }
}

byte mac[][NUMBER_OF_MAC] =
{
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x01 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x02 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x03 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x04 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x05 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x06 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x07 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x08 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x09 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0A },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0B },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0C },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0D },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0E },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0F },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x10 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x11 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x12 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x13 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x14 },
};

// Select the IP address according to your local network
IPAddress myIP(192, 168, 2, 232);
IPAddress myGW(192, 168, 2, 1);
IPAddress mySN(255, 255, 255, 0);

// Google DNS Server IP
IPAddress myDNS(8, 8, 8, 8);

extern "C"
{
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}

const char *PubTopic = "async-mqtt/ESP32_W5500_Pub"; // Topic to publish

// ESP32_W5500 ETH;

void connectToWifi()
{
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void connectToMqtt()
{
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

void WiFiEvent(WiFiEvent_t event)
{
  switch (event)
  {
#if USING_CORE_ESP32_CORE_V200_PLUS

  case ARDUINO_EVENT_WIFI_READY:
    Serial.println("WiFi ready");
    break;

  case ARDUINO_EVENT_WIFI_STA_START:
    Serial.println("WiFi STA starting");
    break;

  case ARDUINO_EVENT_WIFI_STA_CONNECTED:
    Serial.println("WiFi STA connected");
    break;

  case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
  case ARDUINO_EVENT_WIFI_STA_GOT_IP:
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    connectToMqtt();
    break;

  case ARDUINO_EVENT_WIFI_STA_LOST_IP:
    Serial.println("WiFi lost IP");
    break;

  case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
    Serial.println("WiFi lost connection");
    xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
    xTimerStart(wifiReconnectTimer, 0);
    break;
#else

  case SYSTEM_EVENT_STA_GOT_IP:
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    connectToMqtt();
    break;

  case SYSTEM_EVENT_STA_DISCONNECTED:
    Serial.println("WiFi lost connection");
    xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
    xTimerStart(wifiReconnectTimer, 0);
    break;
#endif

  default:
    break;
  }
}

void ETH_event(WiFiEvent_t event)
{
  switch (event)
  {
#if USING_CORE_ESP32_CORE_V200_PLUS

  case ARDUINO_EVENT_ETH_START:
    Serial.println("ETH starting");
    break;

  case ARDUINO_EVENT_ETH_CONNECTED:
    Serial.println("ETH connected");
    break;

  case ARDUINO_EVENT_ETH_GOT_IP:
    Serial.println("ETH got IP");
    Serial.print("IP address: ");
    Serial.println(ETH.localIP());
    connectToMqtt();
    break;

  case ARDUINO_EVENT_ETH_DISCONNECTED:
    Serial.println("ETH lost connection");

    // ensure we don't reconnect to MQTT when no ETH
    xTimerStop(mqttReconnectTimer, 0);

    break;

  case ARDUINO_EVENT_ETH_STOP:
    Serial.println("ETH stops");

    // ensure we don't reconnect to MQTT when no ETH
    xTimerStop(mqttReconnectTimer, 0);

    break;
#else

  case SYSTEM_EVENT_ETH_CONNECTED:
    erial.println(F("ETH Connected"));
    break;

  case SYSTEM_EVENT_ETH_GOT_IP:
    Serial.println("ETH connected");
    Serial.println("IP address: ");
    Serial.println(ETH.localIP());
    connectToMqtt();
    break;

  case SYSTEM_EVENT_ETH_DISCONNECTED:
  case SYSTEM_EVENT_ETH_STOP:
    Serial.println("ETH lost connection");

    // ensure we don't reconnect to MQTT when no ETH
    xTimerStop(mqttReconnectTimer, 0);

    break;
#endif

  default:
    break;
  }
}

void printSeparationLine()
{
  Serial.println("************************************************");
}

void onMqttConnect(bool sessionPresent)
{
  Serial.print("Connected to MQTT broker: ");
  Serial.print(MQTT_HOST);
  Serial.print(", port: ");
  Serial.println(MQTT_PORT);
  Serial.print("PubTopic: ");
  Serial.println(PubTopic);

  printSeparationLine();
  Serial.print("Session present: ");
  Serial.println(sessionPresent);

  uint16_t packetIdSub = mqttClient.subscribe(PubTopic, 2);
  Serial.print("Subscribing at QoS 2, packetId: ");
  Serial.println(packetIdSub);

  mqttClient.publish(PubTopic, 0, true, "ESP32_W5500 Test");
  Serial.println("Publishing at QoS 0");

  uint16_t packetIdPub1 = mqttClient.publish(PubTopic, 1, true, "test 2");
  Serial.print("Publishing at QoS 1, packetId: ");
  Serial.println(packetIdPub1);

  uint16_t packetIdPub2 = mqttClient.publish(PubTopic, 2, true, "test 3");
  Serial.print("Publishing at QoS 2, packetId: ");
  Serial.println(packetIdPub2);

  printSeparationLine();
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason)
{
  (void)reason;

  Serial.println("Disconnected from MQTT.");

  if (ESP32_W5500_isConnected())
  {
    xTimerStart(mqttReconnectTimer, 0);
  }
}

void onMqttSubscribe(const uint16_t &packetId, const uint8_t &qos)
{
  Serial.println("Subscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  Serial.print("  qos: ");
  Serial.println(qos);
}

void onMqttUnsubscribe(const uint16_t &packetId)
{
  Serial.println("Unsubscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void onMqttMessage(char *topic, char *payload, const AsyncMqttClientMessageProperties &properties,
                   const size_t &len, const size_t &index, const size_t &total)
{
  (void)payload;

  Serial.println("Publish received.");
  Serial.print("  topic: ");
  Serial.println(topic);
  Serial.print("  qos: ");
  Serial.println(properties.qos);
  Serial.print("  dup: ");
  Serial.println(properties.dup);
  Serial.print("  retain: ");
  Serial.println(properties.retain);
  Serial.print("  len: ");
  Serial.println(len);
  Serial.print("  index: ");
  Serial.println(index);
  Serial.print("  total: ");
  Serial.println(total);
}

void onMqttPublish(const uint16_t &packetId)
{
  Serial.println("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup()
{
  #define FORMAT_SPIFFS_IF_FAILED false
  Serial.begin(115200);
  if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED))
  {
    Serial.println(F("W0")); // W0: SPIFFS Mount Failed
    return;
  }

  while (!Serial && millis() < 5000)
    ;

  Serial.print("\nStarting FullyFeature_ESP32_W5500 on ");
  Serial.print(BOARD_NAME);
  Serial.println(" with " + String(SHIELD_TYPE));
  Serial.println(WEBSERVER_ESP32_W5500_VERSION);
  // Serial.println(ASYNC_MQTT_GENERIC_VERSION);

  AMQTT_LOGWARN(F("Default SPI pinout:"));
  AMQTT_LOGWARN1(F("SPI_HOST:"), ETH_SPI_HOST);
  AMQTT_LOGWARN1(F("MOSI:"), MOSI_GPIO);
  AMQTT_LOGWARN1(F("MISO:"), MISO_GPIO);
  AMQTT_LOGWARN1(F("SCK:"), SCK_GPIO);
  AMQTT_LOGWARN1(F("CS:"), CS_GPIO);
  AMQTT_LOGWARN1(F("INT:"), INT_GPIO);
  AMQTT_LOGWARN1(F("SPI Clock (MHz):"), SPI_CLOCK_MHZ);
  AMQTT_LOGWARN(F("========================="));
  wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0,
                                    reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));
  mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0,
                                    reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));

  WiFi.onEvent(WiFiEvent);

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onSubscribe(onMqttSubscribe);
  mqttClient.onUnsubscribe(onMqttUnsubscribe);
  mqttClient.onMessage(onMqttMessage);
  mqttClient.onPublish(onMqttPublish);

  // mqttClient.setServer(MQTT_HOST, MQTT_PORT);

  ///////////////////////////////////

  // To be called before ETH.begin()
  WiFi.onEvent(ETH_event);

  // start the ethernet connection and the server:
  // Use DHCP dynamic IP and random mac
  uint16_t index = millis() % NUMBER_OF_MAC;

  // bool begin(int MISO_GPIO, int MOSI_GPIO, int SCLK_GPIO, int CS_GPIO, int INT_GPIO, int SPI_CLOCK_MHZ,
  //            int SPI_HOST, uint8_t *W5500_Mac = W5500_Default_Mac);
  // ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST );
  //  ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST, mac[index] );
  //  byte esp32Mac[] = WiFi.macAddress();
  Serial.print("WiFi.macAddress(): ");
  Serial.println(WiFi.macAddress());
  uint8_t baseMac[6];
  esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
  // ETH.begin(MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST, baseMac);
  test();
  Serial.print("index: ");
  Serial.println(index);
  Serial.print("ETH.macAddress(): ");
  Serial.println(ETH.macAddress());
  // Static IP, leave without this line to get IP via DHCP
  // bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0);
  // ETH.config(myIP, myGW, mySN, myDNS);

  ESP32_W5500_waitForConnect();
  connectToWifi();

  allAsyncWebServer();    // Enable ESP Asynchronous Servers
  serverAsyncWeb.begin(); // Start ESP Asynchronous Server
  /* Initiallize AsyncWebSocket */
  WebSocketAsync.onEvent(AsyncWebSocketEvent);
  serverAsyncWeb.addHandler(&WebSocketAsync);
  ///////////////////////////////////
}

void loop()
{
}

define.h:
/****************************************************************************************************************************
  defines.h
  AsyncMqttClient_Generic is a library for ESP32, ESP8266, Protenta_H7, STM32F7, etc. with current AsyncTCP support

  Based on and modified from :

  1) async-mqtt-client (https://github.com/marvinroger/async-mqtt-client)

  Built by Khoi Hoang https://github.com/khoih-prog/AsyncMqttClient_Generic
 ***************************************************************************************************************************************/

#ifndef defines_h
#define defines_h
#include <Arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
#include <Update.h>
#include <ESPmDNS.h>
#include <SPIFFS.h>

#include "Test.h"
#include <AsyncMQTT_ESP32.hpp>
#include <WebServer_ESP32_W5500.hpp>
#include "w5500/esp32_w5500.h"
// Debug Level from 0 to 4
#define _ETHERNET_WEBSERVER_LOGLEVEL_       1
#define _ASYNC_MQTT_LOGLEVEL_               1

//////////////////////////////////////////////////////////

// Optional values to override default settings
// Don't change unless you know what you're doing
//#define ETH_SPI_HOST        SPI3_HOST
//#define SPI_CLOCK_MHZ       25

// Must connect INT to GPIOxx or not working
// #define INT_GPIO            21  //4

// #define MISO_GPIO           19
// #define MOSI_GPIO           23
// #define SCK_GPIO            18
// #define CS_GPIO             22  //5

//////////////////////////////////////////////////////////

// #include <WebServer_ESP32_W5500.h>

/////////////////////////////////////////////

// Enter a MAC address and IP address for your controller below.
extern AsyncMqttClient mqttClient;
extern TimerHandle_t mqttReconnectTimer;
extern TimerHandle_t wifiReconnectTimer;
// extern ESP32_W5500 ETH;

// // extern WiFiClient clientWiFi;
// extern AsyncWebServer serverAsyncWeb;
// extern AsyncWebSocket WebSocketAsync;

#define NUMBER_OF_MAC      20

#define WIFI_SSID         "Digisol"
#define WIFI_PASSWORD     "12345678"

#define MQTT_HOST IPAddress(192, 168, 1, 2)
// #define MQTT_HOST         "broker.emqx.io"        // Broker address
#define MQTT_PORT 1883

#endif    //defines_h

Test.h:
#ifndef Test_H
#define Test_H
void test();
#endif

Test.cpp:
#include "defines.h"
void test()
{
    uint8_t baseMac[6];
    esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
    mqttClient.setServer(MQTT_HOST, MQTT_PORT);
    ETH.begin(MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST, baseMac);
}

Error:
In file included from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h:4,
                 from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h:30,
                 from .pio/libdeps/esp32dev/WebServer_ESP32_W5500/src/WebServer_ESP32_W5500.hpp:33,
                 from include/defines.h:24,
                 from src/Test.cpp:1:
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:95:6: error: 'HTTP_DELETE' conflicts with a previous declaration
   XX(0,  DELETE,      DELETE)       \
      ^
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:138:45: note: in definition of macro 'XX'
 #define XX(num, name, string) HTTP_##name = num,
                                             ^~~
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^~~~~~~~~~~~~~~
In file included from include/defines.h:16,
                 from src/Test.cpp:1:
.pio/libdeps/esp32dev/ESP Async WebServer/src/ESPAsyncWebServer.h:64:3: note: previous declaration 'WebRequestMethod HTTP_DELETE'
   HTTP_DELETE  = 0b00000100,
   ^~~~~~~~~~~
In file included from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h:4,
                 from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h:30,
                 from .pio/libdeps/esp32dev/WebServer_ESP32_W5500/src/WebServer_ESP32_W5500.hpp:33,
                 from include/defines.h:24,
                 from src/Test.cpp:1:
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:96:6: error: 'HTTP_GET' conflicts with a previous declaration
   XX(1,  GET,         GET)          \
      ^
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:138:45: note: in definition of macro 'XX'
 #define XX(num, name, string) HTTP_##name = num,
                                             ^~~
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^~~~~~~~~~~~~~~
In file included from include/defines.h:16,
                 from src/Test.cpp:1:
.pio/libdeps/esp32dev/ESP Async WebServer/src/ESPAsyncWebServer.h:62:3: note: previous declaration 'WebRequestMethod HTTP_GET'
   HTTP_GET     = 0b00000001,
   ^~~~~~~~
In file included from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h:4,
                 from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h:30,
                 from .pio/libdeps/esp32dev/WebServer_ESP32_W5500/src/WebServer_ESP32_W5500.hpp:33,
                 from include/defines.h:24,
                 from src/Test.cpp:1:
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:97:6: error: 'HTTP_HEAD' conflicts with a previous declaration
   XX(2,  HEAD,        HEAD)         \
      ^
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:138:45: note: in definition of macro 'XX'
 #define XX(num, name, string) HTTP_##name = num,
                                             ^~~
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^~~~~~~~~~~~~~~
In file included from include/defines.h:16,
                 from src/Test.cpp:1:
.pio/libdeps/esp32dev/ESP Async WebServer/src/ESPAsyncWebServer.h:67:3: note: previous declaration 'WebRequestMethod HTTP_HEAD'
   HTTP_HEAD    = 0b00100000,
   ^~~~~~~~~
In file included from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h:4,
                 from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h:30,
                 from .pio/libdeps/esp32dev/WebServer_ESP32_W5500/src/WebServer_ESP32_W5500.hpp:33,
                 from include/defines.h:24,
                 from src/Test.cpp:1:
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:98:6: error: 'HTTP_POST' conflicts with a previous declaration
   XX(3,  POST,        POST)         \
      ^
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:138:45: note: in definition of macro 'XX'
 #define XX(num, name, string) HTTP_##name = num,
                                             ^~~
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^~~~~~~~~~~~~~~
In file included from include/defines.h:16,
                 from src/Test.cpp:1:
.pio/libdeps/esp32dev/ESP Async WebServer/src/ESPAsyncWebServer.h:63:3: note: previous declaration 'WebRequestMethod HTTP_POST'
   HTTP_POST    = 0b00000010,
   ^~~~~~~~~
In file included from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h:4,
                 from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h:30,
                 from .pio/libdeps/esp32dev/WebServer_ESP32_W5500/src/WebServer_ESP32_W5500.hpp:33,
                 from include/defines.h:24,
                 from src/Test.cpp:1:
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:99:6: error: 'HTTP_PUT' conflicts with a previous declaration
   XX(4,  PUT,         PUT)          \
      ^
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:138:45: note: in definition of macro 'XX'
 #define XX(num, name, string) HTTP_##name = num,
                                             ^~~
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^~~~~~~~~~~~~~~
In file included from include/defines.h:16,
                 from src/Test.cpp:1:
.pio/libdeps/esp32dev/ESP Async WebServer/src/ESPAsyncWebServer.h:65:3: note: previous declaration 'WebRequestMethod HTTP_PUT'
   HTTP_PUT     = 0b00001000,
   ^~~~~~~~
In file included from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h:4,
                 from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h:30,
                 from .pio/libdeps/esp32dev/WebServer_ESP32_W5500/src/WebServer_ESP32_W5500.hpp:33,
                 from include/defines.h:24,
                 from src/Test.cpp:1:
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^~~~~~~~~~~~~~~
In file included from include/defines.h:16,
                 from src/main.cpp:1:
.pio/libdeps/esp32dev/ESP Async WebServer/src/ESPAsyncWebServer.h:68:3: note: previous declaration 'WebRequestMethod HTTP_OPTIONS'
   HTTP_OPTIONS = 0b01000000,
   ^~~~~~~~~~~~
In file included from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/HTTP_Method.h:4,
                 from C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src/WebServer.h:30,
                 from .pio/libdeps/esp32dev/WebServer_ESP32_W5500/src/WebServer_ESP32_W5500.hpp:33,
                 from include/defines.h:24,
                 from src/main.cpp:1:
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:128:6: error: 'HTTP_PATCH' conflicts with a previous declaration
   XX(28, PATCH,       PATCH)        \
      ^~
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:138:45: note: in definition of macro 'XX'
 #define XX(num, name, string) HTTP_##name = num,
                                             ^~~
C:/Users/shubh/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include/http_parser.h:139:3: note: in expansion of macro 'HTTP_METHOD_MAP'
   HTTP_METHOD_MAP(XX)
   ^~~~~~~~~~~~~~~
In file included from include/defines.h:16,
                 from src/main.cpp:1:
.pio/libdeps/esp32dev/ESP Async WebServer/src/ESPAsyncWebServer.h:66:3: note: previous declaration 'WebRequestMethod HTTP_PATCH'
   HTTP_PATCH   = 0b00010000,
   ^~~~~~~~~~
Compiling .pio\build\esp32dev\liba04\AsyncMQTT_ESP32\AsyncMqttClient\Packets\ConnAckPacket.cpp.o
Compiling .pio\build\esp32dev\liba04\AsyncMQTT_ESP32\AsyncMqttClient\Packets\Out\Connect.cpp.o
*** [.pio\build\esp32dev\src\Test.cpp.o] Error 1
*** [.pio\build\esp32dev\src\main.cpp.o] Error 1
=========================== [FAILED] Took 10.22 seconds ===========================

Look at the pre-compiled code in your temp folder, in a sub-folder named something like arduino_build_513965/sketch/project_name.cpp; Arduino does a lot of code "helping" just before compilation, so it's often helpful to see the actual code that's causing the error.


text:
Wire.write invalid conversion from ‘char*’ to ‘const uint8_t*
I have written this code:
char message[4];
memcpy(message, &delta, 4);

Wire.write(message, 4);

When I try to compile I get this warning:
warning: invalid conversion from ‘char*’ to ‘const uint8_t* {aka const unsigned char*}’ [-fpermissive]
   Wire.write(message, 4);
                        ^

Also followed by this note:
In file included from main.ino:5:0:
/usr/share/arduino/libraries/Wire/Wire.h:61:20: note:   initializing argument 1 of ‘virtual size_t TwoWire::write(const uint8_t*, size_t)’
     virtual size_t write(const uint8_t *, size_t);
                    ^

I do not understand what is wrong?

Try
Wire.write((const uint8_t*) message, 4);

I.e., cast it to the correct type, uint8_t and char are the same (at least on Arduino and for this example, as you do not char about unsigned/signed values).
(see also the comment of the busybee below, for using the cleaner C++ cast).

But if they are the same, why is it complaining?

@user88434 Because C++ is a language with a kind of stronger type system, and by purpose the warning is enabled during compilation. You as the programmer need to make clear that you change the interpretation of the bytes. -- BTW, the clean solution would not use a C cast, but a C++ cast, for example Wire.write(reinterpret_cast<uint8_t*>(message), 4);.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
How to send multiple bytes with Wire without copying
When I need to send multiple bytes via Wire, for example a long int, I cast it to a byte array and specify a length
long int i;
Wire.write((byte*)&i, 4);

But if I want to send bytes from more than 1 variable I need to create a buffer
byte i;
byte j;
byte message[2] = {i, j};
Wire.write(message, 2);

If I want to send them without copying the data I can put them in a struct
struct message {
  byte i;
  byte j;
};
Wire.write((byte*)&message, 2);

But this would require me to refactor existing code.
Is there any c voodoo that I can perform to send bytes of different places of my code over Wire without copying them in a buffer and without refactoring the code?

No, this function overwrite of Wire.write() is meant for buffers, meaning connected spaces in memory, which can be covered by simply incrementing the buffer. That is not the case for distinct variables.
But that begs the question, why you want to do that in one call to Wire.write() in the first place. This function does not do any communication on the I2C lines, it just writes to the libraries internal buffer. The data gets actually send in Wire.endTransmission() or in the onRequest interrupts in the background (depending on where you have those write statements). Thus you already have a buffer and don't need another one. Just call Wire.write() multiple times, once for each variable. That will build up the data sequentially inside the internal buffer.

Well my device is operating in slave mode and my Wire.write() gets called (perhaps not directly but down the line) from an onRequest handler. In my experiments I found that once I call Wire.write() I can not call it again or I get rubbish. Is it possible to use multiple writes in my case?

I got to the bottom of it! But it was too long for a comment so I added an answer. Thanks again!

// Written by Nick Gammon
// May 2012

template <typename T> unsigned int I2C_writeAnything (const T& value)
  {
  Wire.write((byte *) &value, sizeof (value));
  return sizeof (value);
  }  // end of I2C_writeAnything

template <typename T> unsigned int I2C_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = Wire.read();
    return i;
  }  // end of I2C_readAnything

Then in the body of your code you can:
I2C_writeAnything(message);

Similarly your other end can I2C_readAnything.
There is a small amount of refactoring required, changing the function call.

I think there may be issues with struct padding or endianness mismatch in this code if you are unlucky, but maybe it works most of the time.

No, you cannot.
C does not guarantee any allocation properties of variables. Even if you write one variable definition right after another, both variables can have addresses assigned that have other memory in between.
So, if you want a "packet" sent via Wire that contains values of multiple variables, you need to fill a buffer with these values.
Even though C maintains the order of members of a structure, please be aware that depending on the target's architecture there can be gaps between the members for alignment. However, some compilers have language extensions to tackle this issue.

As @chrisl said, there is an internal buffer so the best I can do is just use multiple Wire.write calls, but in my case that wasn't working. I got only the last written value or rubbish data.
I dug through the source of the Wire library and found that the version in github (as of this writing) makes it possible to use multiple writes by appending to the buffer:
// set length and copy data into tx buffer
for(i = 0; i < length; ++i){
  twi_txBuffer[twi_txBufferLength+i] = data[i];
}
twi_txBufferLength += length;

But the one I have installed locally looks like this:
// set length and copy data into tx buffer
twi_txBufferLength = length;
for(i = 0; i < length; ++i){
  twi_txBuffer[i] = data[i];
}

So that explains a lot.
In case someone else also has this problem, you just need to update.
I was even too lazy to update, so I just replaced the function. Probably not the best decision, but it works!
Thanks!

fixed 6 years ago

@Juraj yeah I got curious and checked it too. Probably someone else was also as lazy as me and didn't update! I can't remember where I got my arduino sdk from but it was about 2 years ago, so definitely plenty of time has been had for updates, lol.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Cannot communicate with software serial on particular devices (SIM7600G-H)
I have 3 devices:

An UNO (non-genuine)

An SMS hat/shield device SIM7600G-H to communicate with via UART

A USB UART controller for debugging purposes

I'm using the UNO to talk to the SMS device via UART at 9600 baud to send and receive SMS commands. I need the hardware port open to debug, and I am trying to use a software port to talk to the SMS device via it's TX RX pins.
But I cannot get the software port to talk to the SMS device at all.
This is the success I've had trying to talk to and from devices. The bold boxes are needed to be solved for this setup to work. ✅ = working coms, ❌ = nothing on coms at all. Read left to right, HAT serial (SMS DEVICE) can communicate with UNO hardware serial.

And I'm using this code to just relay inputs and outputs between the hardware and software ports for testing.
// Must be same on mock and serial
const int baud = 9600;

// Communication with mock hat
SoftwareSerial mockPort(2, 3);

void setup()
{
  Serial.begin(baud);

  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  mockPort.begin(baud);
  Serial.println("Mock port has started @ " + String(baud));
}

void loop()
{

  while (mockPort.available() > 0)
  {
    char inByte = mockPort.read();
    // and send to the hardware serial port:
    Serial.write(inByte);
  }

  // while there is data coming in FROM SERIAL, read it and send it back to mock
  while (Serial.available() > 0)
  {
    char inByte = Serial.read();
    // and send to the mock serial port:
    mockPort.write(inByte);
  }
}

Why can't I communicate to the SMS device with the software ports? (or the USB UART as well?) When testing, I can see the UNO's RX light turn on, but I never receive any data back from the SMS device (the serial monitor is just black).

Notes:

I've tried the AltSoftSerial library as well
I've set the SMS hat's baud rate default to 9600
I've tried different communication pins
I've got the TX pins on RX pins and vice versa

I am using simcom7600gh but with esp32.
are you sure you are sending the correct AT Commands to the modem?

@AhmadFirdausIdris All i'm sending is at. I've tried with an ESP32 as well. I can't even get the boot message from the hat.

The TX and RX labels mirror the Raspberry Pi. So I swapped the RX and TX wires to connect as RX->RX and TX->TX and now it works


text:
Can an Arduino and an NI USB-6009 DAQ board interfere with each other's signals when they are simultaneously reading signals from different sensors?
Hello dear Arduino SE community.
I have 5 sensors. I read 4 of them with an NI USB-6009 DAQ board and I read the fifth one with an Arduino UNO R3. Though, with the fifth sensor not only I read a signal from it, but I also send a signal to it.
Both the Arduino and the NI board are connected to a computer via two different USB ports and send the signals to the computer simultaneously. Also - simultaneously - the Arduino sends a signal to the fifth sensor.
I noticed a strange behavior with the signal from one of the sensors read by the NI board. It starts with giving me a signal that is clearly wrong and over the course of, approximately, 5 minutes gradually changes to a correct reading.
That hadn't happened when I didn't have Arduino connected to the computer at the same time.
Thus, I'm wondering if it is possible that an Arduino and an NI board can interfere with each other's signals when connected to the computer simultaneously. If it is possible, is it something widespread and is there a working solution?
Thank you in advance.
Ivan
P.S. I deliberately don't provide the specs of my system because the point of my question is not to resolve the issue but to learn if what I described is possible theoretically and if such cases have been encountered.

anything is possible ... please ask a focused question that is actually answerable

I have found a solution to my problem.
The sensor that was giving me the wrong signal was plugged to the same electrical circuit with "heavy" equipment (two DC laboratory power supplies). It is well known that one shouldn't do it because "heavy" equipment sends noise back to the circuit which, ultimately, causes noise in the signal generated by the sensor.
Thus, my issue had nothing to do with the Arduino interfering with the USB-6009 through the computer.
To make sure, I disconnected the Arduino from the computer and still got the same wrong signal from the problematic sensor. Then, I plugged the problematic sensor to another electrical circuit, connected the Arduino back to the computer and got the right signal.
Thus, I conclude that one can safely use an Arduino and a USB-6009 with the same computer.


text:
How to increase pinout switching?
Consider this code:
void loop() {
    digitalWrite(pinTest, HIGH);
    digitalWrite(pinTest, LOW);
}

On an Arduino Mega 2560, running 16MHz (=0.06us), I would expect the width of the pulse to be somewhere around 0.1us.
However, when measuring with my oscilloscope, I get around 4us high and 5-6 us low. I understand it could take some cycles to run the digitalWrite code, but this seems quite a lot.
How is that difference explained?

digitalWrite is not optimized to translate the value of pinTest to the proper port/bit combination.  If you need that, do it once in advance. Your code will be hardware-specific for avr-gcc targets.

@DataFiddler any resources on how to do that in advance?

Watch this youtube Why I’m switching over from the awesome Arduino IDE to Atmel Studio

Thanks all. Too bad, I am on Linux, so Atmel Studio is not an option, but I found a wait to build assembly code using arduino-cli and Visual Studio Code.

You do not need to go all the way down to assembly in order to get that
speed. You can do direct port access from your .ino file:
void setup() {
    DDRA |= _BV(PA0);  // pin 22 = PA0 as output
    for (;;) {
        PINA |= _BV(PA0);  // toggle PA0
    }
}

void loop(){}

This compiles to something that is almost equivalent to your assembly
code. Actually, it is a bit faster, as it uses rjmp instead of the
slower jmp instruction.
Edit: A few notes

As pointed out by timemage in a comment, you can save another CPU
cycle by writing PINA = instead of PINA |=.

This code, as well as your two examples, will exhibit a glitch every
1,024 µs. This is caused by the periodic timer interrupt used
by the Arduino core for timekeeping (millis(), micros() and
delay()). You can avoid the glitch by disabling interrupts before
going into the tight loop. Alternatively, if you do not use the
Arduino core at all, you can define a function called main()
instead of setup() and loop(): this will completely remove the
Arduino core initialization for your compiled program.

arduino-cli is useful for sparing you the complexity of the Arduino
build system (automatic installation of the cores and libraries,
libraries in multiple places that depend on the core you use...). If
you do not use the Arduino core, arduino-cli is of little use: a
very simple Makefile that calls avr-gcc and avrdude is all you
need for basic AVR development.

PINA = rather than PINA |=.  I'm not 100% certain what will happen with the SBI that PINA |= expr appears to be generating; but it if actually behaves as PINA = PINA | expr it is trying to toggle port pins in part based on the current read value of the port. In any case, PINA =  is sufficient and winds up generating an OUT which is 1 cycle compared to SBI's two cycles. It's peanuts. But then they are going for speed.

@timemage: You are right, PINA = is faster here. sbi is safe, as it is a real bitwise access, not a bytewise read-modify-write. PINA |=, on the other hand, is only safe when you know PINA lives in the bit-addressable part of the I/O space.

I suspected that about sbi simply because it would be much less useful otherwise.  Re. I/O space: Yeah I didn't spell it out, but PINH/PINJ/PINK/PINL (curiously no PINI; perhaps it looks too much like a 1) all result lds,ori,sts

I fixed it by using assembly code to run the program. Because I am using Linux, I couldn't use Atmel Studio, but you can easily use AVR assembly with arduino-cli.
Make your .ino like this:
extern "C" void myAssemblyMain();

void setup() {
    myAssemblyMain();
}
void loop() {
}

then add a pulse.S file with the assembly code:
#define __SFR_OFFSET 0

#include "avr/io.h"

.global myAssemblyMain

myAssemblyMain:
  sbi   DDRA, 0     ; Set PA0 as output

blink:
  sbi   PINA, 0     ; Toggle PINB
  jmp   blink

Using this code, I get a ~400ns pulse. Which is more than enough for my needs.

you can do the same with the Arduino IDE. no need for CLI

please update your question, because this does not answer the question you asked

@jsotola agreed it didn't answer the exact question, but it does give another way of reaching the same goal.

@Juraj thanks, I'll check that out. But I work a lot with Visual Studio Code, so staying within the same tool is preferable.


text:
ESP32 HTTP Update and x-MD5 header
https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPUpdate
I found out that this library can read x-MD5 header but looks like it's going through with the update no matter what MD5 I set. I thought it's for verifying the update, I do md5sum of my bin file on the server and then ESP32 checks the hash of downloaded bin to confirm the file wasn't corrupted during download. Am I wrong here? What's the purpose of this x-MD5 header if not for this?
If it has another purpose, how do I make sure that the bin with the update wasn't corrupted during download so I don't brick ESP32?

there is in Update.cpp a condition if(strlen(expected_md5) != 32)


text:
Arduino Output Panel Font Color Change
I am using Arduino IDE 2.0.3.  When compiling code if there is an error it shows on a black background with a red font, that is hard for me to read.  Can I change either the background or the font?  Looking within the IDE I don't see how and not seeing anything on the internet.  TIA

Does it help if you select another theme? You can change the theme from the preferences. Open the Preferences dialog with Ctrl/Cmd+, and choose another theme, press OK.

Wow, now I feel stupid.  Themes did not even enter my mind.  Thank you for the suggestion and thank you for not point out that my question was pretty stupid.

Great! Suppose you or anybody else wants to install additional themes into the Arduino IDE, reference this excellent guide. The IDE does not yet support custom themes natively, but it's possible to install them as VS Code extensions manually. For the install guide, the credit goes to in0.

custom themes in v2.0.3 appear to be broken ... use 2.0.1 or nightly build

Thank you dankeboy36 for pointing out "Themes".  Fixed it right up.


text:
Unable to use RF M4 Receiver with servo motor
I am trying to control a servo motor with the following code:
#include <Servo.h>

Servo servo;

int const inputPin = 3;

void setup() {
  Serial.begin(9600);
  servo.attach(9);
  pinMode(inputPin, INPUT);
  servo.write(0);
}

void loop() {
  if (digitalRead(inputPin)) {
    Serial.println("HIGH");
    servo.write(40);
  } else {
    Serial.println("LOW");
    servo.write(0);
  }
}

It takes input from pin 3 and controls the servo with pin 9. When pin 3 is connected to a pushbutton, as shown in the following image, it works exactly as expected; for as long as the button is held down, the servo stays at 40° and when the button is released the servo returns to 0°.
It's a little difficult to see in the images, but the resistor on row 24 is connected to ground, not power.

However, if I replace the button with an Adafruit RF M4 Receiver, as shown in the following image, the servo behaves differently. When I hold the button on the remote down, the servo attempts to move to 40°, but returns to 0° before trying again. From the serial output, I can see that the pin is in fact oscillating between HIGH and LOW.

If I remove the commands to the servo and just use the buttons to control the serial output, the code behaves correctly. With both the pushbutton and the RF M4 Receiver, the output says HIGH when the button is held down and LOW when it is released. So the issue only occurs when I use both the receiver and a servo motor, but not one or the other.
int const inputPin = 3;

void setup() {
  Serial.begin(9600);
  pinMode(inputPin, INPUT);
}

void loop() {
  if (digitalRead(inputPin)) {
    Serial.println("HIGH");
  } else {
    Serial.println("LOW");
  }
}

I am using an Arduino Uno R3, this receiver, and this remote.
Edit: The schematic, as requested. I'm new to Arduino, so I apologize if the schematic is a little sloppy.

simulate this circuit – Schematic created using CircuitLab

I will guess you probably have RF feedback getting into the control loop. No idea of how it gets there. Please post an annotated schematic.

@Gil, I'm working on making the schematic. Do you think I need the pull down resistor for the RF receiver? Can that be causing the issue?

No sure, I am not familiar with the parts or circuit you are using.  If that is connected to an Arduino port pin that can switch it low or high.

remove the servo and the servo code... light an LED instead

@jsotola It works as expected with an LED. I'm only having an issue when I'm using the receiver to control a servo.

@Gil, I've added a schematic. It's a little messy, but it's about the best I can do at this point. Let me know if this helps.

"From the serial output, I can see that the pin is in fact oscillating between HIGH and LOW." - Sounds like the receiver is not outputting a HIGH signal the entire time the button is being pressed, or maybe, the current requirement of both loads exceeds the Uno's available current.

@VE7JRO, The receiver normally outputs a HIGH signal the entire time the button is pressed except for when I use it with a servo, so the load requirement explanation sounds plausible. As a beginner, what would be some steps I can take to troubleshoot this? Would powering the servo with a separate battery fix the issue? I'm new to this, so I'm still not quite sure how to manipulate voltages and currents.

Powering the servo with a separate battery MAY solve the problem. Remember to connect the external power supply's ground with your Arduino's ground connection.

@VE7JRO I just tried it out and it worked. I connected the servo to a 9V battery and it operated correctly. I thought it might also work if I power the Arduino and the servo with the same 9V battery, since the voltage is higher that the Arduino's 5V, but the issue persisted when I did that, so I guess for now I just have to run them with different power sources. Is it standard practice to power servos with a separate power source? I know that that's the standard with DC motors, but the starter book I'm using didn't say anything about servos.

"Is it standard practice to power servos with a separate power source?" - Yes. If you look at the servo's power consumption under certain conditions, you'll see it can reach 730mA. Here is a chart for the SG90 servo: https://arduino.stackexchange.com/a/49755/37523 A 9 volt battery may not last very long, so you may want to switch to larger batteries or perhaps a wal-wart (AC to DC converter).

@VE7JRO Thank you for your help. As with the user in the question you linked to, I've been following official Arduino tutorials from the starter kit, and in all the projects that use a servo they connect it directly to the Arduino's power. They only discuss separate power sources for DC motors. For some reason, the tutorials are just not making this clear at all for beginners.


text:
How does Arduino handle passing this union?
I'm unsure how this will be handled by the Arduino compiler. If anyone can explain what and why, I'd appreciate it. This is obviously very simplified, but it does contain the actual issue.
At the module level I have this union. I understand that this is strictly speaking not correct C++, but it does work for me, at least when used directly and not passed as a argument to a function.
  union _TAT {          // access as bytes or uint32
    uint32_t wide = 0;
    uint8_t bytes[4];
  };

  _TAT oneTAT;        // a variable of _TAT

Suppose I also have a function that works on these:
  void fix_Term(_TAT atat) {
    atat.wide = 0;
    atat.bytes[3] = 17;
  }

...and I invoke it with:
  fix_Term(oneTAT);

As I understand it, passing AnArray[] is equivalent to passing *AnArray, so the function might/should see atat.bytes[3] as a pointer to that byte of the variable. But what about atat.wide? I haven't explicitly passed oneTAT by reference, so...?
What might actually happen here? It does compile without complaint but I can't test it because the hardware it depends on isn't available yet. Besides, even if it works, I'd like to know why.
And of course, if it's just wrong, how do I best accomplish passing and modifying a variable like this?

you can test your native code in tinkercad's Arduino simulator. Arduino is usually about the same as plain c++, so compiler explorer is another online option.

It is confusing in C and C++ that arrays are passed as pointers but an instance of class, struct or union is always passed by value (so as a copy) including the arrays which are part of the memory space of the structure as in the case of your union.
If you want to pass by reference, declare the function's parameter as a reference 'type'. For example void fix_Term(_TAT& atat) {.

Thanks, this seems to be the missing piece for me. I do want to pass by reference but was confused (as you note) by the * / [] .

Yes passing AnArray[] is equivalent to passing *AnArray. But declaring uint8_t *anarray1 is not equivalent to declaring uint8_t anarray2[4] in a struct/class/union definition. The former includes a pointer to a byte in the struct, the later actually includes 4 bytes in the struct. So in the later case, anarray2 already points to data, and using variable.anarray2[0] correctly gets you the value in the structure, while calling variable.anarray1[0] would result in undefined behavior, because the pointer just points anywhere.
So your code is compiling and executing without error, but since you're passing the union by value, the effect of your fix_term function is discarded, much like if you had passed in an ordinary value type instead (such as int).

However he can pass it by reference:  void fix_Term(_TAT & atat) + call is the same and then it'll change the original union variable.

@KIIV Sure, but the question was about the existing code, I think.

Yes, the question was about what the original code is doing, but it also solicited advice on making it work. Got it now, I think, thanks to you and Juraj


text:
Multiplexing three VFD tubes — why are the segments and the display timing incorrect?
I'm using an Arduino Nano, a UNL2803 IC, and three 2N3904 transistors to drive three seven-segment vacuum fluorescent display tubes (IV-6) in a multiplex configuration. The UNL2803 is used to drive the segments: when an Arduino pin is pulled low, 25V is sent to the corresponding segment. The 2N3904 transistors are used to drive each of the digits: when the Arduino pin is high, 25V is sent to the digit's grid, thereby activating the digit.
The problem: the tubes aren't showing the correct segments, and the displays aren't being activated with correct timing. I have checked each segment connection to make sure it is connected to the correct segment. By slowing down the time interval between digits, I can see that the second and third digits (the 10s and 1s) are being displayed sequentially with the correct interval, but the first digit (the 100s) comes on with the second digit and stays on for twice the interval time. It also appears that some of the digits are attempting to display more than one number (sequentially) while activated.
The code:
// Pin assignments for segments
const int SEG_A = 2;
const int SEG_B = 3;
const int SEG_C = 4;
const int SEG_D = 6;
const int SEG_E = 5;
const int SEG_F = 7;
const int SEG_G = 8;

// Pin assignments for digits
const int DIG1 = 9;
const int DIG2 = 10;
const int DIG3 = 11;

int digit = 1;
int dig_number = 0;
unsigned int number = 321;

void setup() {

  Serial.begin(9600);

  // Set segment pins as outputs
  pinMode(SEG_A, OUTPUT);
  pinMode(SEG_B, OUTPUT);
  pinMode(SEG_C, OUTPUT);
  pinMode(SEG_D, OUTPUT);
  pinMode(SEG_E, OUTPUT);
  pinMode(SEG_F, OUTPUT);
  pinMode(SEG_G, OUTPUT);

  // Set digit pins as outputs
  pinMode(DIG1, OUTPUT);
  pinMode(DIG2, OUTPUT);
  pinMode(DIG3, OUTPUT);

  // Turn off digits
  digitalWrite(DIG1, LOW);
  digitalWrite(DIG2, LOW);
  digitalWrite(DIG3, LOW);
}

void loop() {
      if (digit == 1) {
        digitalWrite(DIG1, HIGH);
        digitalWrite(DIG2, LOW);
        digitalWrite(DIG3, LOW);
        dig_number = number / 100;
        if (number < 100) {      // to disable the digit if it's not being used
          dig_number == 99;      // triggers 'default' in switch/case
          display_number(dig_number);
        } else {
          display_number(dig_number);
        }
        digit = 2;
        Serial.println("The first digit is: ");
        Serial.print(dig_number);
        delay (250);
      }

      if (digit == 2) {
        digitalWrite(DIG1, LOW);
        digitalWrite(DIG2, HIGH);
        digitalWrite(DIG3, LOW);
        dig_number = (number / 10) % 10;
        if (dig_number == 0 && number < 10) {       // to disable the digit if it's not being used
          dig_number == 99;        // triggers 'default' in switch/case
          display_number(dig_number);
        } else {
          display_number(dig_number);
        }
        digit = 3;
        Serial.println("The second digit is: ");
        Serial.print(dig_number);
        delay (250);
      }

      if (digit == 3) {
        digitalWrite(DIG1, LOW);
        digitalWrite(DIG2, LOW);
        digitalWrite(DIG3, HIGH);
        dig_number = number % 10;
        display_number(dig_number);
        digit = 1;
        Serial.println("The third digit is: ");
        Serial.print(dig_number);
        delay (250);
      }
}

void display_number(int dig_number) {

    switch (dig_number) {
        case 0:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, HIGH);
        break;

    case 1:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
        break;

    case 2:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, LOW);
        break;

    case 3:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, LOW);
        break;

    case 4:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
        break;

    case 5:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
        break;

    case 6:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
        break;

    case 7:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
        break;

    case 8:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
        break;

    case 9:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
        break;

    default:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
        break;
    }
}

The circuit diagram:

I have heard rumor that using delay() instead of millis() for multiplexing can be problematic. Is that what's going on here?
Many thanks in advance for considering this problem!

The way you have wired ìt, when you are switching a digit on, you need to send a LOW to its corresponding pin and a HIGH to the other two digit pins. You have this inverted. I'm guessing that the wire connecting R9, R10 and R11 goes all the way to 25 volts. Base resistors on the transistors would be nice.

Thank you. My understanding of using the 2N3904 transistor as a switch is that a high pin is needed on the base in order to "open" the switch and allow current to flow from collector to emitter. Please help me understand the need for a low pin on the base for this to work. I am new to transistors. :)

This is correct but, in your case, switching the transistors on pulls the grids to ground thus switching off the displays. I have added a more complete explanation below as an answer.

For future searchers, you can check out the final project here. Many thanks to those who commented——your feedback was extremely helpful.

Your code appears to invert the switching pattern of the digits. Instead of switching the  selected digit on and the other two off, you are doing the opposite.
The grid of a VFD tube has to have a voltage applied to it to illuminate the selected segments. Those segments are also selected by having a voltage applied. The circuit you have shown, by default, powers both the grids and the segments via 10k resistors connected to the 25 volt power rail. The transistors, also in the uln2803, when switched on, pull the grids and segments to ground, thus switching those elements off. This arrangement reduces the complexity of the circuit by eliminating the need for high side switching but "wastes" power.
A simple code correction should solve the problem:
// Turn off digits
   digitalWrite(DIG1, HIGH);  // high turns the grid off.
   digitalWrite(DIG2, HIGH);
   digitalWrite(DIG3, HIGH);
 }

if (digit == 1) {
   digitalWrite(DIG1, LOW);  // digit one ON
   digitalWrite(DIG2, HIGH); // digit two OFF
   digitalWrite(DIG3, HIGH); // digit three OFF
}

Do the equivalent for digits 2 and 3.
Use resistors (say 1k) in series with the transistor bases to limit the current and protect the arduino pins. See https://learn.sparkfun.com/tutorials/transistors/applications-i-switches
You still have to confirm if the wire connecting R9, R10 and R11 goes to all the way to the +25 volt rail. This is not clear from the schematic.

Thanks so much for this explanation! I eventually replaced the 2N3904 transistors with a ULN2803, and that fixed the problem. All is working as it should now, except for one small quirk: I have set up a simple counter to cycle through numbers, and I can see very faint illumination on segments that are not energized while the count is underway. A "ghosting" effect, so to speak, on all the digits. Very low voltage is somehow getting to pins that are not selected. Any idea where this might be coming from?

@ThomasBurns If you get ghosting, then before switching one digit on, first switch the other two off, then set up the segments (by calling display_number() ) and wait say 1ms. Then switch the selected digit on.  Also, speed up your multiplexing. Probably display each digit for about 5ms to avoid noticeable flicker but without incurring too much of a switching loss penalty. This means a small restructuring of your code.

Yes this worked (had to tinker with it for a few minutes). Many thanks for the feedback!

I made a VFD clock using some really cool old DG10B tubes from an early calculator a year or so ago. I had a heck of a time getting it to work, until I decided try tackling one problem at a time, and then put it all together.
In my clock I used the MAX6921 VFD driver IC, a DS3231 RTC with super cap, and a XIAO for the brains. The VFD driver chip is controlled by pwm/serial (data, load, clock) and the RTC is over I2c.
Instead of trying to multiplex them, I just got them all working at once, I did a nice slow count of all digits being on and displaying the same digits. This helped me detect a couple wiring faults, and helped me figure out which segments needed to be lit for each number I wanted displayed. (the digits on my tubes are quite unique!)

once I had my "fonts" figured out and a case for each digit, I created a simple loop that counted through 0-9 on all digits with all four of them on. 4444, 5555, etc
Then I started trying to get just one digit lit at a time.  (this helped me find another wiring issue)
// [pihgfedcba------1234}; //this is what the data stream looks like when sent to the driver
// ...where the first 10 digits are the segments, and the last 4 are the grids for each digit from left to right 1-4.
// The rest are currently unused and should be padded with zero's or 1's)
Next I made a loop that would check the time, and print out the digits. I DO use delay() in my code, in order to deliberately flicker my tubes (for the antique steampunk effect)
But here's the thing, I believe my code checks the time for each individual digit.
the loop says for each digits 1-4 (check time, display digit)
there was a lot more involved, and it's been a while since I worked on it so I am not sure I am being helpful here.  I just wanted to suggest you follow a good troubleshooting process. (smaller problems are easier to solve)

This was extremely helpful. Your approach led me to discover that I was using an incorrect pinout for the UNL2803 chip. Correcting this solved my segment problems. Still working on figuring out what's going on with the digits. Thank you! Also wanted to quickly say that your breadboard technique is inspiring—mine looks considerably less organized.

Haha, yeah, my bread boarding is a little obsessive.   -and I'm  glad I was able to help.  Vfd displays are so fascinating. Hope your project turns out how your want envision it. :)

I'd love to get my hands on some of those VFD tubes with their rough, handwritten style  fonts. But, I know, such odd ball displays are difficult to get hold of and probably well outside any reasonable hobby budget.

For future searchers, I finally got this circuit going using two ULN2803 transistor arrays, instead of discrete transistors for the digit connections. Here's the final schematic:

You can check out more about the final project here. Many thanks to those who commented——your feedback was very helpful!

your final schematic has still errors.
You fixed the missing GND to the ULN2803 drivers.
But the COM inputs (pin 10) and the three resistors for the grid shall be connected to +24V!

@Landroval Thanks for pointing this out! I've exchanged the schematic for the corrected version.


text:
Can an ethernet shield function as an adapter?
I want to communicate with my Arduino over a long distance so I decided to use an Ethernet cable between my computer and Arduino. Searching up a few tutorials I've found them all mentioning IP addresses and establishing a network.
Simply put my question is can an Ethernet shield make the Arduino function basically the same as with a direct USB connection into its port(with Serial and all) without having to establish a network/other things. If so, is it as simple as saying something like "Ethernet.begin()" and then continuing?
Thank you, and please note that I (clearly) do not have much TCP/IP experience (but am more than willing to learn).

No, you cannot do that. Ethernet is very different from a serial link.
You will have to deal with IP addresses, port numbers, the notions of
client and server, and so on. Note that, once you manage to establish a
TCP connection through Ethernet, that connection does behave pretty
much like a (somewhat virtualized) serial link. But you have to
establish the connection first. So you will have to study a bit, read
documentations, etc.
Alternatively, if you only need a short-distance link (say, a couple of
km), you can try RS-485 instead of Ethernet. RS-485 is a physical layer
commonly used to transmit regular serial data. From the software point
of view, it is pretty much a regular serial link, save for the fact that
you usually cannot speak and listen at the same time (you could, with
more expensive cabling).

Thanks, your answer was very illuminating. A quick question, to establish the TCP connection between computer and Arduino would I need any components other than the Arduino, Ethernet shield, and my computer?

@iceninja21: You well need a network cable. All the rest is software.

can't you use a crossover cable and a manual IP to connect 2 devices w/o a network?

@dandavis: If you use IP, you are doing networking, even with only two devices.


text:
Using multiple ultrasonic sensors simultanously with the same trigger
I want to use three ultrasonic sensors together and would prefer to use as few pins as possible, so I was thinking of using one trigger for all 3 sensors. The sensors will have an angle of 90 degrees between them. I was wondering if this would still cause false readings? Since they are a large angle (and some distance) apart?

I think this isn't really answerable, since it greatly depends on your environment. You might get stray reflections into the other sensors. I suggest you just try it out.

If you're using the usual HC-SR04 sensor you should check if there's an ECHO pulse without a prior TRIG pulse output at all. (Otherwise, you can feed all TRIG pins from the same Arduino OUTPUT pin). And keep in mind that pulseIn blocks, so you cannot use it to  get multiple more or less simultaneous signals.

I was looking into this a while back using HC-SR04 sensors and did have some issues with bad (well, strange) readings. but I was just fiddling around with it and haven't gone back to it.
That being said, if you connect the triggers together, but the echo lines individually, and put at least 60ms delay between triggering and reading each sensor, then it might work for your application.
This thread briefly touches on how the time it takes for a ping to decay is part of the issue.
https://forum.arduino.cc/t/multiple-ultrasonic-sensors-close-together/410358
My understanding of it suggests that if you send out a ping in multiple directions, the ping going right echoes off a surface, then echoes off a surface on the left side, which returns to the sensor on the other side, so the sensor might receive a lot of noise.
The datasheet on the HC-SR04 indicates that the cycle time of a single measurement should be 60ms, so a trigger signal doesn't align with an echo...
https://forum.arduino.cc/uploads/short-url/961oW5W0LoHZ6t5XOP40HryBlZK.pdf
In any case, these sensors are cheap and I find that throwing a few bits on a proto board and testing experimenting with them is the best way to learn.
Start with two sensors opposing each other with a surface at 2 inches in front of one, and at 4 inches from the other. trigger them together, see if you can get a clean read from either one. Experiment with different distances to objects (like within an inch on each side, etc). Then repeat the process with a third at the front, and with surface objects at odd angles.
I hope this is helpful, if not encouraging at least :)


text:
Problem with Time Interrupts in ESP8266 with water proof depth sensor
I am trying to use an edited version of waterproof depth sensor code from the Arduino blog. It works well on my Arduino Uno board; however, it doesn't work with my ESP8266 board. Is there a way to adjust it? I understand that the problem is with Arduino clock module and time interrupts. On the other hand, I can't know where to find their counterparts in the ESP libraries.
Code is here:
#include <SPI.h>
const int clock = 4;
float initial = 0;
void resetsensor()
{
  SPI.setDataMode(SPI_MODE0);
  SPI.transfer(0x15);
  SPI.transfer(0x55);
  SPI.transfer(0x40);
}
float read_pressure(){
  TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
  analogWrite (clock, 128) ;
  resetsensor();
  unsigned int result1 = 0;
  unsigned int inbyte1 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x50);
  SPI.setDataMode(SPI_MODE1);
  result1 = SPI.transfer(0x00);
  result1 = result1 << 8;
  inbyte1 = SPI.transfer(0x00);
  result1 = result1 | inbyte1;
  resetsensor();
  unsigned int result2 = 0;
  byte inbyte2 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x60);
  SPI.setDataMode(SPI_MODE1);
  result2 = SPI.transfer(0x00);
  result2 = result2 <<8;
  inbyte2 = SPI.transfer(0x00);
  result2 = result2 | inbyte2;
  resetsensor();
  unsigned int result3 = 0;
  byte inbyte3 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0x90);
  SPI.setDataMode(SPI_MODE1);
  result3 = SPI.transfer(0x00);
  result3 = result3 <<8;
  inbyte3 = SPI.transfer(0x00);
  result3 = result3 | inbyte3;
  resetsensor();
  unsigned int result4 = 0;
  byte inbyte4 = 0;
  SPI.transfer(0x1D);
  SPI.transfer(0xA0);
  SPI.setDataMode(SPI_MODE1);
  result4 = SPI.transfer(0x00);
  result4 = result4 <<8;
  inbyte4 = SPI.transfer(0x00);
  result4 = result4 | inbyte4;
  long c1 = (result1 >> 1) & 0x7FFF;
  long c2 = ((result3 & 0x003F) << 6) | (result4 & 0x003F);
  long c3 = (result4 >> 6) & 0x03FF;
  long c4 = (result3 >> 6) & 0x03FF;
  long c5 = ((result1 & 0x0001) << 10) | ((result2 >> 6) & 0x03FF);
  long c6 = result2 & 0x003F;
  resetsensor();
  unsigned int presMSB = 0; //first byte of value
  unsigned int presLSB = 0; //last byte of value
  unsigned int D1 = 0;
  SPI.transfer(0x0F); //send first byte of command to get pressure value
  SPI.transfer(0x40); //send second byte of command to get pressure value
  delay(35); //wait for conversion end
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  presMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
  presMSB = presMSB << 8; //shift first byte
  presLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
  D1 = presMSB | presLSB; //combine first and second byte of value
  resetsensor(); //resets the sensor
  unsigned int tempMSB = 0; //first byte of value
  unsigned int tempLSB = 0; //last byte of value
  unsigned int D2 = 0;
  SPI.transfer(0x0F); //send first byte of command to get temperature value
  SPI.transfer(0x20); //send second byte of command to get temperature value
  delay(35); //wait for conversion end
  SPI.setDataMode(SPI_MODE1); //change mode in order to listen
  tempMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
  tempMSB = tempMSB << 8; //shift first byte
  tempLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
  D2 = tempMSB | tempLSB; //combine first and second byte of value
  const long UT1 = (c5 << 3) + 20224;
  const long dT = D2 - UT1;
  const long TEMP = 200 + ((dT * (c6 + 50)) >> 10);
  const long OFF  = (c2 * 4) + (((c4 - 512) * dT) >> 12);
  const long SENS = c1 + ((c3 * dT) >> 10) + 24576;
  const long X = (SENS * (D1 - 7168) >> 14) - OFF;
  long PCOMP = ((X * 10) >> 5) + 2500;
  float TEMPREAL = TEMP/10;
  float PCOMPHG = PCOMP * 750.06 / 10000; // mbar*10 -> mmHg === ((mbar/10)/1000)*750/06
  long T2 = 0;
  float P2 = 0;
  if (TEMP < 200)
    {
      T2 = (11 * (c6 + 24) * (200 - TEMP) * (200 - TEMP) ) >> 20;
      P2 = (3 * T2 * (PCOMP - 3500) ) >> 14;
    }
  else if (TEMP > 450)
    {
      T2 = (3 * (c6 + 24) * (450 - TEMP) * (450 - TEMP) ) >> 20;
      P2 = (T2 * (PCOMP - 10000) ) >> 13;
    }
  if ((TEMP < 200) || (TEMP > 450))
  {
    const float TEMP2 = TEMP - T2;
    const float PCOMP2 = PCOMP - P2;
    float TEMPREAL2 = TEMP2/10;
    float PCOMPHG2 = PCOMP2 * 750.06 / 10000; // mbar*10 -> mmHg === ((mbar/10)/1000)*750/06
    return PCOMPHG2;
  }
}
void initialialize()
{
  Serial.print("Setting initial");
  for (int i = 0; i < 10; i++)
  {
    initial += read_pressure();
    Serial.print(".");
    delay(1000);
  }
  initial /= 10;
  Serial.println();
  Serial.print("initialial Pressure: ");
  Serial.println(initial);
}
void setup() {
  Serial.begin(9600);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  pinMode(clock, OUTPUT);
  delay(100);
  initialialize();
  delay(5000);
}
void loop()
{
  float reading = (read_pressure() - initial) * 1.3595474315191;
  Serial.print("Water is: ");
  Serial.print(reading);
  Serial.println("cm");
  delay(500);
}

I get errors with both the clock variable and TCCR1B.


text:
Arudino receiving interrupt command BEFORE entering sleep mode causing it not to receive any interrupt commands in order to wake up
I've written code for an Arduino Nano that when a button is pressed, it sends an IR command. It is set so that if no button press has been received for a period of 10 seconds, it will enter sleep mode until a button press is received. The button to send the IR command is the same button being used to send the wake up interrupt (button connected to pin D2). When testing the code the Arduino is able to go to sleep and wake up from the interrupt 1-3 times before it will suddenly receive an interrupt signal just before entering sleep mode. When this happens it gets stuck in sleep mode and will no longer accept the wake up interrupt. I am currently using Serial Monitor outputs and the built-in LED to determine when the Arduino is in sleep mode or not.
#include <IRLib.h>
#include <avr/sleep.h>
#define interruptPin 2

IRsend My_Sender;

const int button = 2;
int buttonState = 0;
int timeSinceCommand = 0;
const unsigned long eventInterval = 1000;
unsigned long previousTime = 0;

void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);         //delete once code finalized and working
  pinMode(interruptPin, INPUT_PULLUP);
  digitalWrite(LED_BUILTIN, HIGH);      //delete once code finalized and working
  Serial.println("---------------------------New Run---------------------------");
}

void loop() {
  while (timeSinceCommand < 10) {
    unsigned long currentTime = millis();
    buttonState = digitalRead(button);
    if (buttonState == HIGH) {
      My_Sender.send(SONY, 0xC90, 12);
      timeSinceCommand = 0;
      previousTime = currentTime;
    }
    if (currentTime - previousTime >= eventInterval) {
      timeSinceCommand++;
      previousTime = currentTime;
    }
  }
  if (timeSinceCommand >= 10) {
    Going_To_Sleep();
    timeSinceCommand = 0;
  }
}

void Going_To_Sleep() {
  sleep_enable();
  attachInterrupt(0, wakeUp, RISING);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  digitalWrite(LED_BUILTIN, LOW);             //delete once code finalized and working
  Serial.println("Arudino going to sleep!");  //delete once code finalized and working
  delay(1000);                                //delete once code finalized and working
  sleep_cpu();
  Serial.println("Arudino has waken up!");    //delete once code finalized and working
  digitalWrite(LED_BUILTIN, HIGH);            //delete once code finalized and working
}

void wakeUp() {
  Serial.println("Interrupt received!");      //delete once code finalized and working
  sleep_disable();
  detachInterrupt(0);
}

Here is the Serial Monitor output from a couple of tests:
---------------------------New Run---------------------------
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Interrupt received!
Arudino going to sleep!
---------------------------New Run---------------------------
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Interrupt received!
Arudino going to sleep!

Try clearing the interrupt flag before executing attachInterrupt(). For the pin 2 external interrupt on a Uno class board it will be something like: EIFR = bit (INTF0);

I copied that line of code and put it right before attachInterrupt() and it seems to have fixed my issue. Everything is working properly now. Thanks!

There are a couple of tricky things going on here... First, you should
be aware of a few facts:

Buttons are prone to mechanical bounce. You press a button once, and
quite often the microcontroller senses multiple transitions on the
input pin.

When INT0 is configured to sense rising edges, any rising edge on the
pin will set the INTF0 interrupt flag, whether the interrupt is
enabled or not. Once the flag is set, it will fire an interrupt
request as soon as the interrupt is enabled.

When the CPU receives an interrupt request, it finishes executing the
current instruction before servicing the request.

With that in mind, here is an explanation of what goes on:
When you wake up the Arduino with the push button, it often triggers
multiple signal transitions. The first rising edge wakes up the Arduino
and triggers the interrupt. The second rising edge only sets the INTF0
interrupt flag: the interrupt is “on hold”, because interrupts are not
themselves interruptible. However, before exiting, wakeUp() disables
servicing that interrupt, which means the flags just stays set. It is a
pending interrupt of sorts.
Some time later, Going_To_Sleep() is called again. attachInterrupt()
enables the interrupt and, since the flag is still set, the (pending)
interrupt fires immediately. That's when you see the message “Interrupt
received!” printed right before the Arduino goes to sleep. The problem
is that the interrupt is disabled by wakeUp(). One second later,
sleep_cpu() puts the CPU to sleep, and now our wake-up source is
disabled, so the Arduino is just locked into its dreams.
There is still one issue with this scenario. The interrupt handler
supposedly disabled sleeping, so how come the Arduino went to sleep
anyway? The answer is that sleeping was accidentally re-enabled by
set_sleep_mode() because of a data-race. Here is a disassembly of
set_sleep_mode():
in   r24, 0x33 ; read SMCR (Sleep Mode Control Register) into r24
andi r24, 0xF1 ; clear the Sleep Mode Select bits
ori  r24, 0x04 ; select the Power Down mode
out  0x33, r24 ; write back SMCR

The first instruction in this sequence comes right after the instruction
in attachInterrupt() that enables the INT0 interrupt. When that
instruction generates an interrupt request (because the interrupt flag
was already set), the interrupt request reaches the CPU while it is
already executing the in instruction above, and this instruction is
completed before servicing the interrupt request. This means that we
have now in register r24 a copy of the Sleep Mode Control Register from
before the interrupt is serviced. In this copy, the SE bit (Sleep
Enable) is set. Even though wakeUp() clears that bit in the actual
SMCR register, it stays set in our copy in r24. Then, the out
instruction re-enables sleeping. I experimented putting a single nop
instruction right before set_sleep_mode() and that was enough to
prevent the data race.
So here you have an explanation of the observed behavior. I may come
up with some suggestions for fixing the problem, but it need
to take some sleep before that (do not worry, I will make double sure I
have one interrupt source enabled before executing sleep).

Nice explanation especially about the data race risk which I hadn't thought about. When I use sleep mode, with wakeup on either external or pin change interrupt, I usually, if compatible with the application, (a) have an empty interrupt service routine and (b) don't detach the interrupt which is anyway attached in setup(). The sleep_disable() command immediately follows the sleep_cpu() command then any other code to respond to the wake up.

I'm taking this opportunity to include a simple basic sleep sketch which eliminates the possible race condition risk that Edgar Bonet identified in the standard approach to using the sleep mode for AVR class MCUs. See the reference in the sketch to further optimise, if required, to switch off the ADC, Brown out detection etc.
/*
   Sleep mode demonstration (Uno/Nano ATmega328P)
   based on https://www.gammon.com.au/power Sketch J
   but stripped down for demonstration purposes to exclude some optimisation (BOD and ADC etc.)
   See also: https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html

   Connect a button switch between pin 2 and ground
   Press the button. It wakes, blinks the led and then sleeps.

*/

#include <avr/sleep.h>

const byte LED = 13;  // built in led

void wake()
{
  // nothing here. All done in the loop
}

void setup()
{
  Serial.begin( 115200 ) ;
  pinMode( LED, OUTPUT );
  pinMode( 2, INPUT_PULLUP ) ;
  attachInterrupt ( digitalPinToInterrupt(2), wake, FALLING);
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
}

void loop()
{
  Serial.println( "waking . . . ") ;

  // your own code could go here instead

  for ( int i = 0; i < 4; i++ ) {
    digitalWrite (LED, HIGH);
    delay (50);
    digitalWrite (LED, LOW);
    delay (50);
  }
  delay(3000) ;

  Serial.println( "Sleeping. . . " ) ;
  Serial.flush() ;
  delay(20) ; // allow message to be written

  sleep_mode();
  // *** we wake here ***
}

Note that the calls to sleep_enable(), sleep_cpu() and sleep_disable() can be replaced by a single call to sleep_mode(). The three functions you used are most useful when you want to atomically test some condition before going to sleep.

@EdgarBonet. Good point. I've updated to include these because the objective was to provide a "simple as possible" but working example.


text:
Lilygo T-Wristband code not working (DRV2605 Motor version)
I am new to this and I have purchased the Lilygo T-Wristband to prototype a watch that will vibrate upon receiving a 1-bit bluetooth signal from an android app. The goal is to allow the user to set the intensity of vibration (hence i am using the Real Time Playback, RTP, mode) that varies from 0-255. My device seems to not be working whenever i have the Wire1 code and I really am stuck at this point trying to make the motor work. I have attached the code below
#include <pcf8563.h>
#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
#include <SPI.h>
#include <Time.h>
#include <Wire.h>
#include <WiFi.h>
#include "sensor.h"
#include "esp_adc_cal.h"
#include "avas.h.c"
#include "charge.h"
#include "BluetoothSerial.h"
#include <Adafruit_DRV2605.h>
// init Class:
BluetoothSerial ESP_BT;
Adafruit_DRV2605 drv;

#define TP_PIN_PIN          33
#define I2C_SDA_PIN         21
#define I2C_SCL_PIN         22
#define RTC_INT_PIN         34
#define BATT_ADC_PIN        35
#define VBUS_PIN            36
#define TP_PWR_PIN          25
#define LED_PIN             4
#define CHARGE_PIN          32
#define DRV_SDA             15
#define DRV_SCL             13

TFT_eSPI tft = TFT_eSPI();  // Invoke library, pins defined in User_Setup.h
PCF8563_Class rtc;

char buff[256];
bool rtcIrq = false;
bool initial = 1;
bool otaStart = false;
RTC_DATA_ATTR int boots = 0;

uint8_t func_select = 0;
uint8_t omm = 99;
uint8_t xcolon = 0;
uint32_t targetTime = 0;       // for next 1 second timeout
uint32_t colour = 0;
int vref = 1100;

bool pressed = false;
uint32_t pressedTime = 0;
bool charge_indication = false;
uint8_t hh, mm, ss ;

void setupWire() {
  tft.init();
    tft.setRotation(1);
    tft.setSwapBytes(true);
    tft.pushImage(0, 0,  160, 80, avas);
    delay(2000);
  Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
  Wire.setClock(400000);
}
void setupPins() {
  pinMode(TP_PIN_PIN, INPUT);
  pinMode(TP_PWR_PIN, PULLUP);
  //! Must be set to pull-up output mode in order to wake up in deep sleep mode
  digitalWrite(TP_PWR_PIN, HIGH);
  pinMode(LED_PIN, OUTPUT);
  pinMode(CHARGE_PIN, INPUT_PULLUP);
  attachInterrupt(CHARGE_PIN, [] {
      charge_indication = true;
  }, CHANGE);
  if (digitalRead(CHARGE_PIN) == LOW) {
      charge_indication = true;
  }

}
void setupTFT() { //set-up fonts
  tft.init();
  tft.setRotation(1);
  tft.setSwapBytes(true);
  tft.fillScreen(TFT_WHITE);
  tft.setTextColor(TFT_YELLOW, TFT_WHITE); // Note: the new fonts do not draw the background color
}
void setupVolt() { //set-up battery monitoring
    esp_adc_cal_characteristics_t adc_chars;
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize((adc_unit_t)ADC_UNIT_1, (adc_atten_t)ADC1_CHANNEL_6, (adc_bits_width_t)ADC_WIDTH_BIT_12, 1100, &adc_chars);
    //Check type of calibration value used to characterize ADC
    if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
//        Serial.printf("eFuse Vref:%u mV", adc_chars.vref);
        vref = adc_chars.vref;
    } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
//        Serial.printf("Two Point --> coeff_a:%umV coeff_b:%umV\n", adc_chars.coeff_a, adc_chars.coeff_b);
    } else {
//        Serial.println("Default Vref: 1100mV");
    }
}
void setupRTC() { //set-up RTC for time
    rtc.begin(Wire);
    //Check if the RTC clock matches, if not, use compile time
    rtc.check();
    RTC_Date datetime = rtc.getDateTime();
    hh = datetime.hour;
    mm = datetime.minute;
    ss = datetime.second;
}
void setupDRV(){

   Wire1.begin(DRV_SDA, DRV_SCL);
    Wire1.beginTransmission(DRV2605_ADDR);
    if (Wire1.endTransmission() != 0) {
        tft.setTextColor(TFT_RED, TFT_WHITE);
        tft.fillScreen(TFT_WHITE);
        tft.setCursor(0, 0);
        tft.println("Failed to connect DRV2605");
        delay(5000);
        esp_restart();
    }
    drv.begin(&Wire1);
    drv.setMode(DRV2605_MODE_REALTIME);

}
void setup(void) {
  // WiFi.mode(WIFI_OFF);

  Serial.begin(9600);
  setCpuFrequencyMhz(80);         // scaling it back saves so much of the precious battery life
  btStop();
  ESP_BT.begin("AVAS");
  setupDRV();
  setupWire();
  setupTFT();
  setupRTC();
  setupVolt();
  while (ESP_BT.available() == false)
        {
          tft.setTextColor(TFT_BLUE, TFT_WHITE);
          tft.fillScreen(TFT_WHITE);
          tft.setCursor(0, 0);
          tft.println("Bluetooth not connected");
          delay(3000);
        }

  while (ESP_BT.available() == true){
          tft.setTextColor(TFT_RED, TFT_WHITE);
          tft.fillScreen(TFT_WHITE);
          tft.setCursor(0, 0);
          tft.println("Bluetooth connected");
          delay(5000);
          break;
  }

  if(boots == 0) //Run this only the first time
  {
    targetTime = millis() + 1000 ;  //adds 1 min to compiler time
    boots ++;
  }
  setupPins();
}
String Volt() {
    uint16_t v = analogRead(BATT_ADC_PIN);
    float battery_voltage = ((float)v / 4095.0) * 2.0 * 3.3 * (vref / 1000.0);
    return String(battery_voltage) + "V";
}
void RTC() {

    if (targetTime < millis()) {
        RTC_Date datetime = rtc.getDateTime();
        hh = 11;
        mm = datetime.minute;
        ss = datetime.second;
        // Serial.printf("hh:%d mm:%d ss:%d\n", hh, mm, ss);
        targetTime = millis() + 1000;
        if (ss == 0 || initial) {
            initial = 0;
            tft.setTextColor(TFT_GREEN, TFT_WHITE);
            tft.setCursor (8, 60);
            tft.print(__DATE__); // This uses the standard ADAFruit small font
        }
        tft.setTextColor(TFT_BLUE, TFT_WHITE);
        tft.drawCentreString(Volt(), 120, 60, 1); // Next size up font 2
        // Update digital time
        uint8_t xpos = 6;
        uint8_t ypos = 0;
        if (omm != mm) { // Only redraw every minute to minimise flicker
            // Uncomment ONE of the next 2 lines, using the ghost image demonstrates text overlay as time is drawn over it
            tft.setTextColor(0x39C4, TFT_WHITE);  // Leave a 7 segment ghost image, comment out next line!
            //tft.setTextColor(TFT_BLACK, TFT_BLACK); // Set font colour to black to wipe image
            // Font 7 is to show a pseudo 7 segment display.
            // Font 7 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 0 : .
            tft.drawString("88:88", xpos, ypos, 7); // Overwrite the text to clear it
            tft.setTextColor(0xFBE0, TFT_WHITE); // Orange
            omm = mm;

            if (hh < 10) xpos += tft.drawChar('0', xpos, ypos, 7);
            xpos += tft.drawNumber(hh, xpos, ypos, 7);
            xcolon = xpos;
            xpos += tft.drawChar(':', xpos, ypos, 7);
            if (mm < 10) xpos += tft.drawChar('0', xpos, ypos, 7);
            tft.drawNumber(mm, xpos, ypos, 7);
        }

        if (ss % 2) { // Flash the colon
            tft.setTextColor(0x39C4, TFT_WHITE);
            xpos += tft.drawChar(':', xcolon, ypos, 7);
            tft.setTextColor(0xFBE0, TFT_WHITE);
        } else {
            tft.drawChar(':', xcolon, ypos, 7);
        }
    }
}

void loop() {
  if (charge_indication) {
      charge_indication = false;
      if (digitalRead(CHARGE_PIN) == LOW) {
          tft.pushImage(140, 55, 16, 16, charge);
      } else {
          tft.fillRect(140, 55, 16, 16, TFT_WHITE);
      }
  }
  if (digitalRead(TP_PIN_PIN) == HIGH) {
      if (!pressed) {
          initial = 1;
          targetTime = millis() + 1000;
          tft.fillScreen(TFT_WHITE);
          omm = 99;
          func_select = func_select + 1 > 2 ? 0 : func_select + 1;
          pressed = true;
          pressedTime = millis();
      } else {
          if (millis() - pressedTime > 3000) {
              esp_restart();
          }
      }
  } else {
      pressed = false;
  }
        RTC();
   if (ESP_BT.available())
        {
          byte pwm = ESP_BT.read(); //Read what we receive
          // drv.setRealtimeValue(pwm);
          // drv.go();
          tft.setTextColor(TFT_RED, TFT_WHITE);
          tft.fillScreen(TFT_WHITE);
           tft.setCursor(0, 0);
          tft.println(pwm);
        }
  }

start with simple code that runs the motor for one second, stops the motor for one second and repeats


text:
ESP32DevkitC-V4 interfacing ADS8698 (18 bit ADC)
I am currently working on an SPI interface to measure the voltage of an amplified sensor bridge signal. I am using an ESP32 module to control the device. Since I am logging the data to an SD card, I chose to connect the ADS8698  (Datasheet) via the default HSPI interface (see below). Unfortunately I am receiving zero readings only - no matter what commands I send. I tried to illustrate my setup as detailled as possible down below - if you think that I am missing something, do not hesitate to remind me ;).
My Question is: Do you have any ideas on things that I missed facing this issue? - Thanks in advance!
Related Topics
I know that there are related topics in Source A, Source B and Source C, from which however none does lead to a final answer. My research in the last couple of days showed, that several people face issues with this ADC, which lead me to start a new thread to reactive this topic and collect all referenced ressources without creating a duplicate.
Research
One possible reason for the communication problem could be, that I am not using DMA to interface via SPI which might lead to timing problems. I wasn't able to test any ESP32 spi dma library, since the only library I found (https://github.com/hideakitai/ESP32DMASPI) does not compile. Furthermore I found discussions, whether DMA is actually more precise with respect to timing or not, which did not lead to a verified result (the multi-core structure of the ESP32 might even be faster).
Hardware Setup & Wiring

The ADS8698 circuit is shown above, it is connected to the ESP32 as follows:
| ESP32DevKitCV4 | ADS8698IDBT|
| -------- | -------------- |
| 12 (HSPI_MISO)   | SDO|
| 13 (HSPI_MOSI)   | SDI|
| 14 (HSPI_SCK)   | SCK |
| 15 (HSPI_CS)   | CS |
Current Software State
#include <Arduino.h>
#include <SPI.h>

//ADC Settings
#define CHANNEL 0
#define SCLK_SPEED 18e6
#define BUFFER_SIZE 5
#define CS_PIN 15
#define RST_PIN 32
#define SPI_MODE SPI_MODE0

//objects
SPIClass * hspi = NULL;
uint8_t receivedBytes[3];

void setup() {
  Serial.begin(115200);                 //initialize serial communication

  pinMode(CS_PIN, OUTPUT);              //set pinmode
  pinMode(RST_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);           //no communication
  digitalWrite(RST_PIN, HIGH);          //normal operation

  hspi = new SPIClass(HSPI);
  hspi->begin();
  hspi->beginTransaction(SPISettings(SCLK_SPEED,MSBFIRST, SPI_MODE));

  digitalWrite(CS_PIN,LOW);
  hspi->transfer(0xC0);                 //manual read Ch0
  hspi->transfer(0x00);
  Serial.println(hspi->transfer(0x00));
  digitalWrite(CS_PIN,HIGH);
}

void loop() {
  digitalWrite(CS_PIN,LOW);
  hspi->transfer(0);                    // wait 16 clk cycles for conversion, 0x00 = continue Operation
  hspi->transfer(0);
  receivedBytes[0] = hspi->transfer(0); //read 3 bytes
  receivedBytes[1] = hspi->transfer(0);
  receivedBytes[2] = hspi->transfer(0);
  digitalWrite(CS_PIN,HIGH);

  for(int i=0;i<3;i++)
  {
    Serial.print(receivedBytes[i],BIN);
    Serial.print(":");
  }
  Serial.println();
  delay(1000);
}```

Based on the page 48-49 of the datasheet, your implementation does not follow the timing and signalling of the READ operation.

Thank you vor your reply!
Could you please specify in which regards I misunderstood the read signaling? I assume you refer to table 8 and figure 92 on page 49 of the datasheet. Since I have put the ADC in MANUAL_READ_CH0 mode in the setup, an address / cmd of 0x00 should be fine in terms of continued operation. I thought that the manual read command would lead to an SDO signal output according to table 14 on page 54. The latter starts after the 16th falling clk cycle whereas the read command outputs data following the first byte transferred. Maybe that lead to confusion.

Table 14 describes the detail of the received data. But the table 8 and figure 92 shows how the command should be sent and when the data will arriving. The timing diagram shows that data start to coming in on 3rd byte, and DS line won't be drop until data has been received. Your code send the command 0xC000, then drop the CS line. What it should be according the time timing diagram should be digitalWrite(CS_PIN,LOW); hspi->transfer(0xC0); hspi->transfer(0x00); receivedBytes[0] = hopi->trnasfer(0); ... digitalWrite(CS_PIN,HIGH); .

Read the first program of 8.5.2.1, "The program register is a 16-bit read or write register. There must be a minimum of 24 SCLKs after the CS falling edge for any read or write operation to the program registers".

Thank you for your explanation. You are right, I did not consider the accurate timing for the command register write sequence. I updated my code and added a line in void setup to read back the value written to the register - which is obviously zero. Unfortunately I am still getting exclusively zero readings in my main loop. Did I miss something else you mentioned?


text:
Why are ATTiny so expensive compared to ESP modules compared to features they offer?
I was looking for a cheap MCU solution for a project, apart from being compact, ATTiny doesn't seem to provide much value. I was hoping it is cheaper but nope, They are mostly above 1.5 USD in any shop. Whereas I can easily get an ESP module for a comparable price if not cheaper, added WiFi, and optionally Bluetooth, and they are not too huge for my use cases. Am I missing something?

$1.50 is very cheap

I gave a comparison with an ESP module, which can be bought for around the same price, with a hell lot of more features and speed and everything superior.

manufacturer pricing questions are not on topic here ... prices are set to whatever the buyers will pay

Understandable why the question might seem out of scope for the community, but I really struggled to get an answer to the question. And The first answer actually solved my problem, good that it got in before the question was closed. Hope this thread will help others too.

You can get ATTINYs for much less than $1.50.
For example, right now you can order the ATTINY202 from stock in single unit quantiles from Microchip for $0.48 each. They drop to $0.35 each at 5K units (also in stock).
https://www.microchipdirect.com/product/search/all/ATTINY202
If you are really price sensitive then you can sometimes get the smaller ATTINYs for even less when buying in reels at a time, but you have to shop around.
Anytime you pick a part you have to trade-off purchase price, availability (both now and in the future), and suitability. The AVR parts can often be the best choice- but all depends on what you are using it for!

Thanks @bigjosh that was really helpful. I was looking at older versions like attiny85/84 etc which is probably expensive because they are no more in production. I started looking for new ones and ended up in Digikey website where I could find lots of 0, 1 and 2 series ATTinys. Thanks a lot for the answer.

Just FYI if other folks find themselves here from Google looking for attiny85 alternatives: As far as I can tell, the newer chips (the 0, 1, and 2 series) aren't available in PDIP packaging, so they may not be an appropriate replacement for the attiny85 if someone were looking for a breadboard-compatible device.


text:
ESP8266 - error after board update to 3.1.1
I'm using a Ubuntu 22.04 and Arduino IDE 1.8.19 for my ESP8266 Projects.
Yesterday I upgraded to 3.1.1 (using board library manager), and right after that - I got the following message (few seconds after compilation start):
Traceback (most recent call last):
  File "/home/guy/snap/arduino/85/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/tools/mkbuildoptglobals.py", line 846, in <module>
    sys.exit(main())
  File "/home/guy/snap/arduino/85/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/tools/mkbuildoptglobals.py", line 759, in main
    if time.time_ns() < os.stat(commonhfile_fqfn).st_mtime_ns:
AttributeError: module 'time' has no attribute 'time_ns'
exit status 1
Error compiling for board LOLIN(WEMOS) D1 R2 & mini.

Steps done to find the reason:

Empty Sketch - occurs.
Any other ESP8266 board - occurs.
Going back to prior version, 3.1.0 - occurs.
Going back to 3.0.2 - OK!
Checking 3.1.1 on Mac, same IDE version - OK!

Any ideas why ?
Am I the only one ?
Guy

The error tells you, that the time.time_ns() python function does not exist. This function was added to the python time lib with Python3 version 3.7. The most likely scenario I can imagin here is, that a python 3.6 or lower version is installed on your ubuntu and therefor the board software does not find the requiered function. Open a terminal and enter python --version or python3 --version, and make sure you have at least python V 3.7 installed. I would recommend to install 3.10+ to have the newest version and avoid missing other libs and language features.

@PeterPaulKiefer Typing guy@linux:~$ python3 --version returned
Python 3.10.6

i have the same problem
Ubuntu 22.04
IDE 1.8.19
Python 3.10.6
Error occurs after upgrading board esp8266 to 3.1.1

Sorry for my late answer. You installed the Arduino IDE with snap?!  It is possible, that Snap has its own python dependencies. I often had such problems when using snap instead of installing the software with apt or manually with a tarball. Now I always install Arduino using the tarball. There are many doc in the internet, here is one example: https://linuxopsys.com/topics/install-arduino-ide-on-ubuntu-20-04

@PeterPaulKiefer yes, from Snap

I had the same problem, although having python 3.8 installed, and I also installed Arduino through Snap. After removing the Snap installation and installing the one from arduino's website (the .AppImage file) - the issue with time_ns went away. Tnx@PeterPaulKiefer. You transform your comment into an answer and I'd gladly vote for it.

@PeterPaulKiefer please post it as an answer

The error tells you, that the time.time_ns() python function does not exist. This function was added to the python time lib with Python3 version 3.7.
The most likely scenario I can imagin here is, that a python 3.6 or lower version is installed on your ubuntu and therefore the board software does not find the required function.
Depending on how the ARDUINO IDE is configured, the globally installed python or a special installation of python is used. We dicussed these two possibilities in the chat and realized that in your case, snap installs its own dependency of python. I assume that the version of this python was below 3.7 and therefore the plugin was unable to find the required time function.
If the Arduino IDe would have been depent on the global python installation, it would have been enough to install a newer python (e.g. 3.10+) globally.
In you case (dependency defined by snap), the only solution I have, is to install the IDE not with snap but with the manual installation or by using apt. There are instruction in the internet like https://www.computingpost.com/how-to-install-arduino-ide-on-ubuntu-22-04-lts/.
Please check the comment of @userfuser (about usíng an .AppImage file) in the dicussion below the question also.