text:
READ 433mhz DEVICES
I have an issue with 433mhz reading. I have two cheap transmitter and receiver boards, the most known ones :
I followed several tutorials, and I'm using the rc switch library.
I'm trying to read the signal sent by a remote control, (stores), as I would like to duplicate it, to control the store. I firstly tried with the basic code to read 433mhz signals, but it didn't work. Assuming that there is an encryption between the two devices, (I'm not sure if that this is the case, but internet didn't help to find if it's usually the cases for those devices, and how to tell if mine has encryption, It would be nice if I can get some help on that too), I decided to upload a code to get raw data, sent by any transmissions.
The problem is that there is absolutely no data coming out from the receptor when I use the rc switch library. I have another Arduino constantly sending float values with a transmitter, and it works if I use virtualwires, but it doesn't show anything on the serial monitor with rc switch. I also tried with my store remote control, and a garage remote control, but nothing is showing up.
Here is the code of the receiver :
/*
  Example for analyzing and proposing unknown new protocols

  https://github.com/Martin-Laclaustra/rc-switch/

  Requires modified rc-switch branch "protocollessreceiver"
  with ReceivedInverted() function exposed.
*/

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
  // Use mySwitch.enableReceive(D2); for ESP8266
  Serial.println("beginned");
}

void loop() {
  if (mySwitch.available()) {

    int value = mySwitch.getReceivedValue();

    if (value == 0) {
      Serial.print("Unknown encoding");
    } else {

      int databuffer[64]; // get a copy of the received timings before they are overwritten
      int numberoftimings = 2 * mySwitch.getReceivedBitlength() + 2;
      if (numberoftimings > 64) numberoftimings = 64;
      for (int i = 0; i < numberoftimings; i++) {
        databuffer[i] = mySwitch.getReceivedRawdata()[i];
      }

      Serial.print("Received ");
      Serial.print( mySwitch.getReceivedValue() );
      Serial.print(" / ");
      Serial.print( mySwitch.getReceivedBitlength() );
      Serial.print("bit ");
      Serial.print("Protocol: ");
      Serial.println( mySwitch.getReceivedProtocol() );

      unsigned int databitsoffset = abs( (int)mySwitch.getReceivedLevelInFirstTiming() - (int)mySwitch.getReceivedInverted());
      //Serial.println( mySwitch.getReceivedLevelInFirstTiming() );
      //Serial.println( mySwitch.getReceivedInverted() );
      //Serial.println( databitsoffset );
      unsigned long dataduration = 0;
      for (unsigned int i = 1 + databitsoffset; i < numberoftimings - 1 + databitsoffset; i++) {
        dataduration += databuffer[i];
      }
      Serial.print("data bits of pulse train duration: ");
      Serial.println( dataduration );
      unsigned int averagebitduration = (int)(0.5 + ((double)dataduration) / mySwitch.getReceivedBitlength());
      unsigned int protocolratio = (unsigned int)(0.5 + ((double)(averagebitduration - mySwitch.getReceivedDelay())) / (double)mySwitch.getReceivedDelay());
      Serial.print("proposed protocol: { ");
      Serial.print(mySwitch.getReceivedDelay());
      Serial.print(", { ");
      Serial.print( (databitsoffset == 0) ?
                    (int) (0.5 + (double)databuffer[2 * mySwitch.getReceivedBitlength() + 1] / (double)mySwitch.getReceivedDelay())
                    :
                    (int) (0.5 + (double)databuffer[0] / (double)mySwitch.getReceivedDelay())
                  );
      Serial.print(", ");
      Serial.print( (databitsoffset == 0) ?
                    (int) (0.5 + (double)databuffer[0] / (double)mySwitch.getReceivedDelay())
                    :
                    (int) (0.5 + (double)databuffer[1] / (double)mySwitch.getReceivedDelay())
                  );
      Serial.print(" }, { ");
      Serial.print("1");
      Serial.print(", ");
      Serial.print(protocolratio);
      Serial.print(" }, { ");
      Serial.print(protocolratio);
      Serial.print(", ");
      Serial.print("1");
      Serial.print(" }, ");
      Serial.print((mySwitch.getReceivedInverted()) ? "true" : "false" );
      Serial.println(" }");

      // raw signal
      Serial.println("====");
      Serial.print("first level ");
      Serial.println((mySwitch.getReceivedLevelInFirstTiming() == 0) ? "down" : "up" );
      for (int i = 0; i < 2 * mySwitch.getReceivedBitlength() + 2 - 1 + databitsoffset; i++) {
        Serial.print(databuffer[i]);
        Serial.print(" ");
        if ((i - databitsoffset) % 16 == 0) Serial.println("");
      }
      if ((2 * mySwitch.getReceivedBitlength() + 2 - 1 + databitsoffset - 1) % 16 != 0) Serial.println("");
      if (databitsoffset != 1) Serial.println(databuffer[2 * mySwitch.getReceivedBitlength() + 1]);
      // plot signal in spreadsheet
      Serial.println("====");

    }

    mySwitch.resetAvailable();
  }
}

I am aware that interruptPin(0) = pin #2 on Arduino
Here is the layout :

Does anyone have an idea of why I can't get anything on my serial monitor ?, I'll take any help !

there is no encryption ... it's just a wireless wire ... connect a switch to the transmitter and an LED to the receiver ... otherwise, connect a GPIO output to the transmitter and a GPIO input to the receiver

For stores i don't think there is, but I read that garage door have that system, but don't know how to check. For the setup this is exactly what i have done : Data is going out from a GPIO to the transmitter, and reversed for the receiver. What's wrong ?

try to read with SimpleScanner, you can find sketch here:
https://github.com/sui77/SimpleRcScanner/blob/master/htdocs/Sketchbook/SimpleRcScanner.ino


text:
What is the ideal way to check if time on ESP8266 via NTP is ready?
With ESP8266, I noticed that for the first 1 or 2 loops, localtime returns Unix epoch (1970 date) until it has finished getting the actual time from NTP, after which point I see the real date. Sometimes it can take 10 seconds or so before NTP is available, depending on what time server I use and how frequently I make requests to it (most time servers have request throttling, it seems).
Right now, I'm checking whether the date is valid by testing if the year is 70 but this seems weird and hacky. Is there a better way? For instance, is there a function that returns true if the NTP update has been successful or -1 if not?
All of the examples of localtime that I have found so far don't seem to check if the date is valid, and if I run their code, it almost always prints the 1970 Unix epoch date on the first loop.
#define TIME_SERVER_1 "time.google.com"
#define TIME_SERVER_2 "time.nist.gov"
#define TIME_SERVER_3 "pool.ntp.org"
#define TIMEZONE TZ_Europe_London

void setup() {

// ..

  configTime(TIMEZONE, TIME_SERVER_1, TIME_SERVER_2, TIME_SERVER_3);

// ..

}

void loop() {

// ..

      time_t now;
      time(&now);
      struct tm* timeinfo = localtime(&now);

      // TODO: maybe there's a better way to check unknown time?
      if (timeinfo->tm_year == 70) {
        TRACE_LN(F("ntp not yet available"));
      } else {
        epoch = mktime(timeinfo);
      }

//..

}

Doesn't time() return −1 if it cannot get the time? At least that is what it is supposed to do.

Unfortunately, it doesn't seem to return -1. When the year is 70, the result from time is 18 (I guess that's how many seconds the device has been online). When the year is valid, it returns expected epoch, e.g. 1670274493.

I guess, localtime even starts at 31-Dec-1969 afternoon in a western time zone. Thus comparing the local year with 70 is really a strange approach. Rather test the raw time_t value.

You can define a call back function which is triggered when SNTP updates the system time. There is an example of it on the GitHub esp8266/Arduino project with a short description in the comments. The call back function is registered by the example function call settimeofday_cb(time_is_set) where time_is_set() is a user defined funtion.
I have an application (a timeswitch) which maintains an indicator to show how 'fresh' the current time status is. If it is stale, the time source reverts to an RTC until a new time can be fetched. It uses this callback mechanism for that purpose.

Oh awesome!! Nice find.

Eventually tested this today, settimeofday_cb works great.

If time() doesn't return -1 as expected when it doesn't know, then I
have nothing cleaner (less “hacky”) to suggest. That being said,
converting the scalar time to a broken-down representation is a
relatively expensive operation. I suggest avoiding it and just comparing
the returned time to an arbitrary threshold:
// May we consider this valid as the "current" time?
// If it is too far in the past, it is centainly not valid.
static bool is_time_valid(time_t t) {
    const time_t old_past = 1577836800;  // 2020-01-01T00:00:00Z
    return t >= old_past;
}

Yes! Checking if year is 70 did feel really strange indeed; I wasn't convinced that I could guarantee 1970 being Epoch, and as you rightly say in the comments, Epoch could be 1969 in a western time zone.

The following code snippet is most likely the best way of ensuring valid time from NTP. If the call to timeSetup(...) is made after already connected to the internet, then that connection will be used, otherwise the setup will connect to internet, using passed in credetials, and when finished getting NTP time, will disconnect. The code has been cut/pasted from a much bigger project and has not been tested, so there might be some syntax errors.
The SNTP stuff:
#include "sntp.h"
#include "time.h"
#include <sys/time.h>
#include <WiFi.h>

int WiFiconnectedhere = 0;
int timeIsSet = 0;

// timeavailable() cannot be in a class has to be static
//callback function when time has been set
void timeavailable(struct timeval *t)
{
  struct tm timeinfo;
  Serial.println("NTP notification that time is set");

  if (!getLocalTime(&timeinfo)){
    Serial.println("Using getLocalTime()No time available (yet)");
    return;
  }
  Serial.println(&timeinfo, "using getLocalTime() = %A, %B %d %Y   H:%M:%S");

  if (WiFiconnectedhere == 1) {
    WiFi.disconnect(true, true);  //WiFi off, erase AP
    WiFiconnectedhere = 0;
    Serial.println("WiFi has been disconnected");
  }
  timeIsSet = 1;
}

void ESP32Time::timeSetup(
    char *ssid,
    char *password,
    char *ntpServer1,
    char *ntpServer2,
    char *timezone)
{
  timeIsSet = 0;
  //connect to WiFi if not already connected
  if (! WiFi.isConnected()) {  //standard WiFi call to check if connected
    sntp_servermode_dhcp(1);    // (optional)
    Serial.printf("Connecting to %s in time module\r\n", ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.printf(" CONNECTED to internet %s\r\n", ssid);
    WiFiconnectedhere = 1; // so we know to disconnect after done with it
  }
  else {
    Serial.println("WiFi is already connected");
  }

  // get a callback when time has been received locally
  sntp_set_time_sync_notification_cb( timeavailable );

  configTzTime(timezone, ntpServer1, ntpServer2);
  Serial.println("Getting localtime");
  setenv("TZ", timezone, 1);
  tzset();

}

Usage:
ESP32Time esptime;  // Instantiate the class

In arduino setup()
//initialise the time.
esptime.timeSetup(ssid, password, ntpserver1, ntpserver2, timezone);

Retrieve local time:
  struct tm timeinfo;
  time_t now;
  time(&now);
  localtime_r(&now, &timeinfo);
  time_t tt = mktime (&timeinfo);

The timezones in a program usable array (sorry it is so long):
#ifndef TZDB_H
#define TZDB_H

typedef struct {
  char tzlit[35];
  char tzzone[45];
} tTimezones;

#ifndef TZARRAY
#define TZARRAY

tTimezones tz[470] =
{
{"TZ_Africa_Abidjan ","GMT0"},
{"TZ_Africa_Accra   " , "GMT0"},
{"TZ_Africa_Addis_Ababa ","EAT-3"},
{"TZ_Africa_Algiers ","CET-1"},
{"TZ_Africa_Asmara  ","EAT-3"},
{"TZ_Africa_Bamako  ","GMT0"},
{"TZ_Africa_Bangui  ","WAT-1"},
{"TZ_Africa_Banjul  ","GMT0"},
{"TZ_Africa_Bissau  ","GMT0"},
{"TZ_Africa_Blantyre    ","CAT-2"},
{"TZ_Africa_Brazzaville ","WAT-1"},
{"TZ_Africa_Bujumbura   ","CAT-2"},
{"TZ_Africa_Cairo   ","EET-2"},
{"TZ_Africa_Casablanca  ","<+01>-1"},
{"TZ_Africa_Ceuta   ","CET-1CEST,M3.5.0,M10.5.0/3"},
{"TZ_Africa_Conakry ","GMT0"},
{"TZ_Africa_Dakar   ","GMT0"},
{"TZ_Africa_Dar_es_Salaam   ","EAT-3"},
{"TZ_Africa_Djibouti    ","EAT-3"},
{"TZ_Africa_Douala  ","WAT-1"},
{"TZ_Africa_El_Aaiun    ","<+01>-1"},
{"TZ_Africa_Freetown    ","GMT0"},
{"TZ_Africa_Gaborone    ","CAT-2"},
{"TZ_Africa_Harare  ","CAT-2"},
{"TZ_Africa_Johannesburg    ","SAST-2"},
{"TZ_Africa_Juba    ","CAT-2"},
{"TZ_Africa_Kampala ","EAT-3"},
{"TZ_Africa_Khartoum    ","CAT-2"},
{"TZ_Africa_Kigali  ","CAT-2"},
{"TZ_Africa_Kinshasa    ","WAT-1"},
{"TZ_Africa_Lagos   ","WAT-1"},
{"TZ_Africa_Libreville  ","WAT-1"},
{"TZ_Africa_Lome    ","GMT0"},
{"TZ_Africa_Luanda  ","WAT-1"},
{"TZ_Africa_Lubumbashi  ","CAT-2"},
{"TZ_Africa_Lusaka  ","CAT-2"},
{"TZ_Africa_Malabo  ","WAT-1"},
{"TZ_Africa_Maputo  ","CAT-2"},
{"TZ_Africa_Maseru  ","SAST-2"},
{"TZ_Africa_Mbabane ","SAST-2"},
{"TZ_Africa_Mogadishu   ","EAT-3"},
{"TZ_Africa_Monrovia    ","GMT0"},
{"TZ_Africa_Nairobi ","EAT-3"},
{"TZ_Africa_Ndjamena    ","WAT-1"},
{"TZ_Africa_Niamey  ","WAT-1"},
{"TZ_Africa_Nouakchott  ","GMT0"},
{"TZ_Africa_Ouagadougou ","GMT0"},
{"TZ_Africa_PortomNovo  ","WAT-1"},
{"TZ_Africa_Sao_Tome    ","GMT0"},
{"TZ_Africa_Tripoli ","EET-2"},
{"TZ_Africa_Tunis   ","CET-1"},
{"TZ_Africa_Windhoek    ","CAT-2"},
{"TZ_America_Adak   ","HST10HDT,M3.2.0,M11.1.0"},
{"TZ_America_Anchorage  ","AKST9AKDT,M3.2.0,M11.1.0"},
{"TZ_America_Anguilla   ","AST4"},
{"TZ_America_Antigua    ","AST4"},
{"TZ_America_Araguaina  ","<-03>3"},
{"TZ_America_Argentina_Buenos_Aires ","<-03>3"},
{"TZ_America_Argentina_Catamarca    ","<-03>3"},
{"TZ_America_Argentina_Cordoba  ","<-03>3"},
{"TZ_America_Argentina_Jujuy    ","<-03>3"},
{"TZ_America_Argentina_La_Rioja ","<-03>3"},
{"TZ_America_Argentina_Mendoza  ","<-03>3"},
{"TZ_America_Argentina_Rio_Gallegos ","<-03>3"},
{"TZ_America_Argentina_Salta    ","<-03>3"},
{"TZ_America_Argentina_San_Juan ","<-03>3"},
{"TZ_America_Argentina_San_Luis ","<-03>3"},
{"TZ_America_Argentina_Tucuman  ","<-03>3"},
{"TZ_America_Argentina_Ushuaia  ","<-03>3"},
{"TZ_America_Aruba  ","AST4"},
{"TZ_America_Asuncion   ","<-04>4<-03>,M10.1.0/0,M3.4.0/0"},
{"TZ_America_Atikokan   ","EST5"},
{"TZ_America_Bahia  ","<-03>3"},
{"TZ_America_Bahia_Banderas ","CST6"},
{"TZ_America_Barbados   ","AST4"},
{"TZ_America_Belem  ","<-03>3"},
{"TZ_America_Belize ","CST6"},
{"TZ_America_BlancmSablon   ","AST4"},
{"TZ_America_Boa_Vista  ","<-04>4"},
{"TZ_America_Bogota ","<-05>5"},
{"TZ_America_Boise  ","MST7MDT,M3.2.0,M11.1.0"},
{"TZ_America_Cambridge_Bay  ","MST7MDT,M3.2.0,M11.1.0"},
{"TZ_America_Campo_Grande   ","<-04>4"},
{"TZ_America_Cancun ","EST5"},
{"TZ_America_Caracas    ","<-04>4"},
{"TZ_America_Cayenne    ","<-03>3"},
{"TZ_America_Cayman ","EST5"},
{"TZ_America_Chicago    ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Chihuahua  ","CST6"},
{"TZ_America_Costa_Rica ","CST6"},
{"TZ_America_Creston    ","MST7"},
{"TZ_America_Cuiaba ","<-04>4"},
{"TZ_America_Curacao    ","AST4"},
{"TZ_America_Danmarkshavn   ","GMT0"},
{"TZ_America_Dawson ","MST7"},
{"TZ_America_Dawson_Creek   ","MST7"},
{"TZ_America_Denver ","MST7MDT,M3.2.0,M11.1.0"},
{"TZ_America_Detroit    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Dominica   ","AST4"},
{"TZ_America_Edmonton   ","MST7MDT,M3.2.0,M11.1.0"},
{"TZ_America_Eirunepe   ","<-05>5"},
{"TZ_America_El_Salvador    ","CST6"},
{"TZ_America_Fortaleza  ","<-03>3"},
{"TZ_America_Fort_Nelson    ","MST7"},
{"TZ_America_Glace_Bay  ","AST4ADT,M3.2.0,M11.1.0"},
{"TZ_America_Godthab    ","<-02>2"},
{"TZ_America_Goose_Bay  ","AST4ADT,M3.2.0,M11.1.0"},
{"TZ_America_Grand_Turk ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Grenada    ","AST4"},
{"TZ_America_Guadeloupe ","AST4"},
{"TZ_America_Guatemala  ","CST6"},
{"TZ_America_Guayaquil  ","<-05>5"},
{"TZ_America_Guyana ","<-04>4"},
{"TZ_America_Halifax    ","AST4ADT,M3.2.0,M11.1.0"},
{"TZ_America_Havana ","CST5CDT,M3.2.0/0,M11.1.0/1"},
{"TZ_America_Hermosillo ","MST7"},
{"TZ_America_Indiana_Indianapolis   ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Indiana_Knox   ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Indiana_Marengo    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Indiana_Petersburg ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Indiana_Tell_City  ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Indiana_Vevay  ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Indiana_Vincennes  ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Indiana_Winamac    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Inuvik ","MST7MDT,M3.2.0,M11.1.0"},
{"TZ_America_Iqaluit    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Jamaica    ","EST5"},
{"TZ_America_Juneau ","AKST9AKDT,M3.2.0,M11.1.0"},
{"TZ_America_Kentucky_Louisville    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Kentucky_Monticello    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Kralendijk ","AST4"},
{"TZ_America_La_Paz ","<-04>4"},
{"TZ_America_Lima   ","<-05>5"},
{"TZ_America_Los_Angeles    ","PST8PDT,M3.2.0,M11.1.0"},
{"TZ_America_Lower_Princes  ","AST4"},
{"TZ_America_Maceio ","<-03>3"},
{"TZ_America_Managua    ","CST6"},
{"TZ_America_Manaus ","<-04>4"},
{"TZ_America_Marigot    ","AST4"},
{"TZ_America_Martinique ","AST4"},
{"TZ_America_Matamoros  ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Mazatlan   ","MST7"},
{"TZ_America_Menominee  ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Merida ","CST6"},
{"TZ_America_Metlakatla ","AKST9AKDT,M3.2.0,M11.1.0"},
{"TZ_America_Mexico_City    ","CST6"},
{"TZ_America_Miquelon   ","<-03>3<-02>,M3.2.0,M11.1.0"},
{"TZ_America_Moncton    ","AST4ADT,M3.2.0,M11.1.0"},
{"TZ_America_Monterrey  ","CST6"},
{"TZ_America_Montevideo ","<-03>3"},
{"TZ_America_Montreal   ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Montserrat ","AST4"},
{"TZ_America_Nassau ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_New_York   ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Nipigon    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Nome   ","AKST9AKDT,M3.2.0,M11.1.0"},
{"TZ_America_Noronha    ","<-02>2"},
{"TZ_America_North_Dakota_Beulah    ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_North_Dakota_Center    ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_North_Dakota_New_Salem ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Nuuk   ","<-02>2"},
{"TZ_America_Ojinaga    ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Panama ","EST5"},
{"TZ_America_Pangnirtung    ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Paramaribo ","<-03>3"},
{"TZ_America_Phoenix    ","MST7"},
{"TZ_America_PortmaumPrince ","EST5EDT,M3.2.0,M11.1.0"},
{"TZ_America_Port_of_Spain  ","AST4"},
{"TZ_America_Porto_Velho    ","<-04>4"},
{"TZ_America_Puerto_Rico    ","AST4"},
{"TZ_America_Punta_Arenas   ","<-03>3"},
{"TZ_America_Rainy_River    ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Rankin_Inlet   ","CST6CDT,M3.2.0,M11.1.0"},
{"TZ_America_Recife ","<-03>3"},
{"TZ_America_Regina ","CST6"},
{"TZ_America_Resolute   ","CST6CDT,M3.2.0,M11.1.0"},

Continuation of timezones:
        {"TZ_America_Santarem   ","<-03>3"},
        {"TZ_America_Santiago   ","<-04>4<-03>,M9.1.6/24,M4.1.6/24"},
        {"TZ_America_Santo_Domingo  ","AST4"},
        {"TZ_America_Sao_Paulo  ","<-03>3"},
        {"TZ_America_Scoresbysund   ","<-01>1<+00>,M3.5.0/0,M10.5.0/1"},
        {"TZ_America_Sitka  ","AKST9AKDT,M3.2.0,M11.1.0"},
        {"TZ_America_St_Barthelemy  ","AST4"},
        {"TZ_America_St_Johns   ","NST3:30NDT,M3.2.0,M11.1.0"},
        {"TZ_America_St_Kitts   ","AST4"},
        {"TZ_America_St_Lucia   ","AST4"},
        {"TZ_America_St_Thomas  ","AST4"},
        {"TZ_America_St_Vincent ","AST4"},
        {"TZ_America_Swift_Current  ","CST6"},
        {"TZ_America_Tegucigalpa    ","CST6"},
        {"TZ_America_Thule  ","AST4ADT,M3.2.0,M11.1.0"},
        {"TZ_America_Thunder_Bay    ","EST5EDT,M3.2.0,M11.1.0"},
        {"TZ_America_Tijuana    ","PST8PDT,M3.2.0,M11.1.0"},
        {"TZ_America_Toronto    ","EST5EDT,M3.2.0,M11.1.0"},
        {"TZ_America_Tortola    ","AST4"},
        {"TZ_America_Vancouver  ","PST8PDT,M3.2.0,M11.1.0"},
        {"TZ_America_Whitehorse ","MST7"},
        {"TZ_America_Winnipeg   ","CST6CDT,M3.2.0,M11.1.0"},
        {"TZ_America_Yakutat    ","AKST9AKDT,M3.2.0,M11.1.0"},
        {"TZ_America_Yellowknife    ","MST7MDT,M3.2.0,M11.1.0"},
        {"TZ_Antarctica_Casey   ","<+11>-11"},
        {"TZ_Antarctica_Davis   ","<+07>-7"},
        {"TZ_Antarctica_DumontDUrville  ","<+10>-10"},
        {"TZ_Antarctica_Macquarie   ","AEST-10AEDT,M10.1.0,M4.1.0/3"},
        {"TZ_Antarctica_Mawson  ","<+05>-5"},
        {"TZ_Antarctica_McMurdo ","NZST-12NZDT,M9.5.0,M4.1.0/3"},
        {"TZ_Antarctica_Palmer  ","<-03>3"},
        {"TZ_Antarctica_Rothera ","<-03>3"},
        {"TZ_Antarctica_Syowa   ","<+03>-3"},
        {"TZ_Antarctica_Troll   ","<+00>0<+02>-2,M3.5.0/1,M10.5.0/3"},
        {"TZ_Antarctica_Vostok  ","<+06>-6"},
        {"TZ_Arctic_Longyearbyen    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Asia_Aden  ","<+03>-3"},
        {"TZ_Asia_Almaty    ","<+06>-6"},
        {"TZ_Asia_Amman ","<+03>-3"},
        {"TZ_Asia_Anadyr    ","<+12>-12"},
        {"TZ_Asia_Aqtau ","<+05>-5"},
        {"TZ_Asia_Aqtobe    ","<+05>-5"},
        {"TZ_Asia_Ashgabat  ","<+05>-5"},
        {"TZ_Asia_Atyrau    ","<+05>-5"},
        {"TZ_Asia_Baghdad   ","<+03>-3"},
        {"TZ_Asia_Bahrain   ","<+03>-3"},
        {"TZ_Asia_Baku  ","<+04>-4"},
        {"TZ_Asia_Bangkok   ","<+07>-7"},
        {"TZ_Asia_Barnaul   ","<+07>-7"},
        {"TZ_Asia_Beirut    ","EET-2EEST,M3.5.0/0,M10.5.0/0"},
        {"TZ_Asia_Bishkek   ","<+06>-6"},
        {"TZ_Asia_Brunei    ","<+08>-8"},
        {"TZ_Asia_Chita ","<+09>-9"},
        {"TZ_Asia_Choibalsan    ","<+08>-8"},
        {"TZ_Asia_Colombo   ","<+0530>-5:30"},
        {"TZ_Asia_Damascus  ","<+03>-3"},
        {"TZ_Asia_Dhaka ","<+06>-6"},
        {"TZ_Asia_Dili  ","<+09>-9"},
        {"TZ_Asia_Dubai ","<+04>-4"},
        {"TZ_Asia_Dushanbe  ","<+05>-5"},
        {"TZ_Asia_Famagusta ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Asia_Gaza  ","EET-2EEST,M3.4.4/50,M10.4.4/50"},
        {"TZ_Asia_Hebron    ","EET-2EEST,M3.4.4/50,M10.4.4/50"},
        {"TZ_Asia_Ho_Chi_Minh   ","<+07>-7"},
        {"TZ_Asia_Hong_Kong ","HKT-8"},
        {"TZ_Asia_Hovd  ","<+07>-7"},
        {"TZ_Asia_Irkutsk   ","<+08>-8"},
        {"TZ_Asia_Jakarta   ","WIB-7"},
        {"TZ_Asia_Jayapura  ","WIT-9"},
        {"TZ_Asia_Jerusalem ","IST-2IDT,M3.4.4/26,M10.5.0"},
        {"TZ_Asia_Kabul ","<+0430>-4:30"},
        {"TZ_Asia_Kamchatka ","<+12>-12"},
        {"TZ_Asia_Karachi   ","PKT-5"},
        {"TZ_Asia_Kathmandu ","<+0545>-5:45"},
        {"TZ_Asia_Khandyga  ","<+09>-9"},
        {"TZ_Asia_Kolkata   ","IST-5:30"},
        {"TZ_Asia_Krasnoyarsk   ","<+07>-7"},
        {"TZ_Asia_Kuala_Lumpur  ","<+08>-8"},
        {"TZ_Asia_Kuching   ","<+08>-8"},
        {"TZ_Asia_Kuwait    ","<+03>-3"},
        {"TZ_Asia_Macau ","CST-8"},
        {"TZ_Asia_Magadan   ","<+11>-11"},
        {"TZ_Asia_Makassar  ","WITA-8"},
        {"TZ_Asia_Manila    ","PST-8"},
        {"TZ_Asia_Muscat    ","<+04>-4"},
        {"TZ_Asia_Nicosia   ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Asia_Novokuznetsk  ","<+07>-7"},
        {"TZ_Asia_Novosibirsk   ","<+07>-7"},
        {"TZ_Asia_Omsk  ","<+06>-6"},
        {"TZ_Asia_Oral  ","<+05>-5"},
        {"TZ_Asia_Phnom_Penh    ","<+07>-7"},
        {"TZ_Asia_Pontianak ","WIB-7"},
        {"TZ_Asia_Pyongyang ","KST-9"},
        {"TZ_Asia_Qatar ","<+03>-3"},
        {"TZ_Asia_Qyzylorda ","<+05>-5"},
        {"TZ_Asia_Riyadh    ","<+03>-3"},
        {"TZ_Asia_Sakhalin  ","<+11>-11"},
        {"TZ_Asia_Samarkand ","<+05>-5"},
        {"TZ_Asia_Seoul ","KST-9"},
        {"TZ_Asia_Shanghai  ","CST-8"},
        {"TZ_Asia_Singapore ","<+08>-8"},
        {"TZ_Asia_Srednekolymsk ","<+11>-11"},
        {"TZ_Asia_Taipei    ","CST-8"},
        {"TZ_Asia_Tashkent  ","<+05>-5"},
        {"TZ_Asia_Tbilisi   ","<+04>-4"},
        {"TZ_Asia_Tehran    ","<+0330>-3:30"},
        {"TZ_Asia_Thimphu   ","<+06>-6"},
        {"TZ_Asia_Tokyo ","JST-9"},
        {"TZ_Asia_Tomsk ","<+07>-7"},
        {"TZ_Asia_Ulaanbaatar   ","<+08>-8"},
        {"TZ_Asia_Urumqi    ","<+06>-6"},
        {"TZ_Asia_UstmNera  ","<+10>-10"},
        {"TZ_Asia_Vientiane ","<+07>-7"},
        {"TZ_Asia_Vladivostok   ","<+10>-10"},
        {"TZ_Asia_Yakutsk   ","<+09>-9"},
        {"TZ_Asia_Yangon    ","<+0630>-6:30"},
        {"TZ_Asia_Yekaterinburg ","<+05>-5"},
        {"TZ_Asia_Yerevan   ","<+04>-4"},
        {"TZ_Atlantic_Azores    ","<-01>1<+00>,M3.5.0/0,M10.5.0/1"},
        {"TZ_Atlantic_Bermuda   ","AST4ADT,M3.2.0,M11.1.0"},
        {"TZ_Atlantic_Canary    ","WET0WEST,M3.5.0/1,M10.5.0"},
        {"TZ_Atlantic_Cape_Verde    ","<-01>1"},
        {"TZ_Atlantic_Faroe ","WET0WEST,M3.5.0/1,M10.5.0"},
        {"TZ_Atlantic_Madeira   ","WET0WEST,M3.5.0/1,M10.5.0"},
        {"TZ_Atlantic_Reykjavik ","GMT0"},
        {"TZ_Atlantic_South_Georgia ","<-02>2"},
        {"TZ_Atlantic_Stanley   ","<-03>3"},
        {"TZ_Atlantic_St_Helena ","GMT0"},
        {"TZ_Australia_Adelaide ","ACST-9:30ACDT,M10.1.0,M4.1.0/3"},
        {"TZ_Australia_Brisbane ","AEST-10"},
        {"TZ_Australia_Broken_Hill  ","ACST-9:30ACDT,M10.1.0,M4.1.0/3"},
        {"TZ_Australia_Currie   ","AEST-10AEDT,M10.1.0,M4.1.0/3"},
        {"TZ_Australia_Darwin   ","ACST-9:30"},
        {"TZ_Australia_Eucla    ","<+0845>-8:45"},
        {"TZ_Australia_Hobart   ","AEST-10AEDT,M10.1.0,M4.1.0/3"},
        {"TZ_Australia_Lindeman ","AEST-10"},
        {"TZ_Australia_Lord_Howe    ","<+1030>-10:30<+11>-11,M10.1.0,M4.1.0"},
        {"TZ_Australia_Melbourne    ","AEST-10AEDT,M10.1.0,M4.1.0/3"},
        {"TZ_Australia_Perth    ","AWST-8"},
        {"TZ_Australia_Sydney   ","AEST-10AEDT,M10.1.0,M4.1.0/3"},
        {"TZ_Europe_Amsterdam   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Andorra ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Astrakhan   ","<+04>-4"},
        {"TZ_Europe_Athens  ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Belgrade    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Berlin  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Bratislava  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Brussels    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Bucharest   ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Budapest    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Busingen    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Chisinau    ","EET-2EEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Copenhagen  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Dublin  ","IST-1GMT0,M10.5.0,M3.5.0/1"},
        {"TZ_Europe_Gibraltar   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Guernsey    ","GMT0BST,M3.5.0/1,M10.5.0"},
        {"TZ_Europe_Helsinki    ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Isle_of_Man ","GMT0BST,M3.5.0/1,M10.5.0"},
        {"TZ_Europe_Istanbul    ","<+03>-3"},
        {"TZ_Europe_Jersey  ","GMT0BST,M3.5.0/1,M10.5.0"},
        {"TZ_Europe_Kaliningrad ","EET-2"},
        {"TZ_Europe_Kiev    ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Kirov   ","<+03>-3"},
        {"TZ_Europe_Lisbon  ","WET0WEST,M3.5.0/1,M10.5.0"},
        {"TZ_Europe_Ljubljana   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_London  ","GMT0BST,M3.5.0/1,M10.5.0"},
        {"TZ_Europe_Luxembourg  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Madrid  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Malta   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Mariehamn   ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Minsk   ","<+03>-3"},
        {"TZ_Europe_Monaco  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Moscow  ","MSK-3"},
        {"TZ_Europe_Oslo    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Paris   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Podgorica   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Prague  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Riga    ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Rome    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Samara  ","<+04>-4"},
        {"TZ_Europe_San_Marino  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Sarajevo    ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Saratov ","<+04>-4"},
        {"TZ_Europe_Simferopol  ","MSK-3"},
        {"TZ_Europe_Skopje  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Sofia   ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Stockholm   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Tallinn ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Tirane  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Ulyanovsk   ","<+04>-4"},
        {"TZ_Europe_Uzhgorod    ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Vaduz   ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Vatican ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Vienna  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Vilnius ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Volgograd   ","<+03>-3"},
        {"TZ_Europe_Warsaw  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Zagreb  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Europe_Zaporozhye  ","EET-2EEST,M3.5.0/3,M10.5.0/4"},
        {"TZ_Europe_Zurich  ","CET-1CEST,M3.5.0,M10.5.0/3"},
        {"TZ_Indian_Antananarivo    ","EAT-3"},
        {"TZ_Indian_Chagos  ","<+06>-6"},
        {"TZ_Indian_Christmas   ","<+07>-7"},
        {"TZ_Indian_Cocos   ","<+0630>-6:30"},
        {"TZ_Indian_Comoro  ","EAT-3"},
        {"TZ_Indian_Kerguelen   ","<+05>-5"},
        {"TZ_Indian_Mahe    ","<+04>-4"},
        {"TZ_Indian_Maldives    ","<+05>-5"},
        {"TZ_Indian_Mauritius   ","<+04>-4"},
        {"TZ_Indian_Mayotte ","EAT-3"},
        {"TZ_Indian_Reunion ","<+04>-4"},
        {"TZ_Pacific_Apia   ","<+13>-13"},
        {"TZ_Pacific_Auckland   ","NZST-12NZDT,M9.5.0,M4.1.0/3"},
        {"TZ_Pacific_Bougainville   ","<+11>-11"},
        {"TZ_Pacific_Chatham    ","<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45"},
        {"TZ_Pacific_Chuuk  ","<+10>-10"},
        {"TZ_Pacific_Easter ","<-06>6<-05>,M9.1.6/22,M4.1.6/22"},
        {"TZ_Pacific_Efate  ","<+11>-11"},
        {"TZ_Pacific_Enderbury  ","<+13>-13"},
        {"TZ_Pacific_Fakaofo    ","<+13>-13"},
        {"TZ_Pacific_Fiji   ","<+12>-12"},
        {"TZ_Pacific_Funafuti   ","<+12>-12"},
        {"TZ_Pacific_Galapagos  ","<-06>6"},
        {"TZ_Pacific_Gambier    ","<-09>9"},
        {"TZ_Pacific_Guadalcanal    ","<+11>-11"},
        {"TZ_Pacific_Guam   ","ChST-10"},
        {"TZ_Pacific_Honolulu   ","HST10"},
        {"TZ_Pacific_Kiritimati ","<+14>-14"},
        {"TZ_Pacific_Kosrae ","<+11>-11"},
        {"TZ_Pacific_Kwajalein  ","<+12>-12"},
        {"TZ_Pacific_Majuro ","<+12>-12"},
        {"TZ_Pacific_Marquesas  ","<-0930>9:30"},
        {"TZ_Pacific_Midway ","SST11"},
        {"TZ_Pacific_Nauru  ","<+12>-12"},
        {"TZ_Pacific_Niue   ","<-11>11"},
        {"TZ_Pacific_Norfolk    ","<+11>-11<+12>,M10.1.0,M4.1.0/3"},
        {"TZ_Pacific_Noumea ","<+11>-11"},
        {"TZ_Pacific_Pago_Pago  ","SST11"},
        {"TZ_Pacific_Palau  ","<+09>-9"},
        {"TZ_Pacific_Pitcairn   ","<-08>8"},
        {"TZ_Pacific_Pohnpei    ","<+11>-11"},
        {"TZ_Pacific_Port_Moresby   ","<+10>-10"},
        {"TZ_Pacific_Rarotonga  ","<-10>10"},
        {"TZ_Pacific_Saipan ","ChST-10"},
        {"TZ_Pacific_Tahiti ","<-10>10"},
        {"TZ_Pacific_Tarawa ","<+12>-12"},
        {"TZ_Pacific_Tongatapu  ","<+13>-13"},
        {"TZ_Pacific_Wake   ","<+12>-12"},
        {"TZ_Pacific_Wallis ","<+12>-12"},
        {"TZ_Etc_GMT    ","GMT0"},
        {"TZ_Etc_GMTm0  ","GMT0"},
        {"TZ_Etc_GMTm1  ","<+01>-1"},
        {"TZ_Etc_GMTm2  ","<+02>-2"},
        {"TZ_Etc_GMTm3  ","<+03>-3"},
        {"TZ_Etc_GMTm4  ","<+04>-4"},
        {"TZ_Etc_GMTm5  ","<+05>-5"},
        {"TZ_Etc_GMTm6  ","<+06>-6"},
        {"TZ_Etc_GMTm7  ","<+07>-7"},
        {"TZ_Etc_GMTm8  ","<+08>-8"},
        {"TZ_Etc_GMTm9  ","<+09>-9"},
        {"TZ_Etc_GMTm10 ","<+10>-10"},
        {"TZ_Etc_GMTm11 ","<+11>-11"},
        {"TZ_Etc_GMTm12 ","<+12>-12"},
        {"TZ_Etc_GMTm13 ","<+13>-13"},
        {"TZ_Etc_GMTm14 ","<+14>-14"},
        {"TZ_Etc_GMT0   ","GMT0"},
        {"TZ_Etc_GMTp0  ","GMT0"},
        {"TZ_Etc_GMTp1  ","<-01>1"},
        {"TZ_Etc_GMTp2  ","<-02>2"},
        {"TZ_Etc_GMTp3  ","<-03>3"},
        {"TZ_Etc_GMTp4  ","<-04>4"},
        {"TZ_Etc_GMTp5  ","<-05>5"},
        {"TZ_Etc_GMTp6  ","<-06>6"},
        {"TZ_Etc_GMTp7  ","<-07>7"},
        {"TZ_Etc_GMTp8  ","<-08>8"},
        {"TZ_Etc_GMTp9  ","<-09>9"},
        {"TZ_Etc_GMTp10 ","<-10>10"},
        {"TZ_Etc_GMTp11 ","<-11>11"},
        {"TZ_Etc_GMTp12 ","<-12>12"},
        {"TZ_Etc_UCT    ","UTC0"},
        {"TZ_Etc_UTC    ","UTC0"},
        {"TZ_Etc_Greenwich  ","GMT0"},
        {"TZ_Etc_Universal  ","UTC0"},
        {"TZ_Etc_Zulu   ","UTC0"},
        {"EOF", "eof"}
        };

        char *getTimeZoneLit(int tzindex) {
          return(tz[tzindex].tzlit);
        }
        char *getTimeZone(int tzindex) {
          return(tz[tzindex].tzzone);
        }

        #endif // TZDB_H
        #endif

Why the markdown. This database is the authoritative database. Please note that the array starts in the previous post. I don't know how to add it as a downloadable file and had to split it to fit the post size limitations.

source: Stack Exchange

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

sort: votes


text:
Problem cleaning string read from serial buffer
I am trying to move a stepper motor when a specific command is send to Arduino Mega 2560. This command is read character by character and stored in a string variable. Whenever a new command is sent, an act should be performed. However, it is not happening and I believe that the problem is in reading the sent command. I tried clearing the character and string variables, but to no avail. The sketch should run a loop that moves the motor clockwise or counterclockwise according to the command sent, which can be "crx*" for clockwise or "clx*" for anticlockwise, where "*" is the reading stop criterion of the characters.
Any suggestions what to do?
The script:
void(* resetFunc) (void) = 0;//Reset turn

// Stepper Motor X
const int stepPinX = 2; //X.STEP
const int dirPinX = 5; // X.DIR
const int pinEnable = 8;

// String read
char c;
String readString; //main captured String

// Unit steps
double av_len = 1.029; //medium length
double interval;
int cnt_steps = 0;
const int num_d = 200;//parameterized step
int fact = int(num_d / av_len);
int unit_len = fact * 1;//unit length (1mm)

void setup()
{
  // Sets pins as Outputs
  pinMode(stepPinX, OUTPUT);
  pinMode(dirPinX, OUTPUT);
  pinMode(pinEnable, OUTPUT);

  digitalWrite(pinEnable, HIGH);//lock driver on cnc shield

  Serial.begin(115200);
  Serial.setTimeout(1);

  while (1) {

    while ( (Serial.available() == 0) )
    {

    }

    if (Serial.available())  {
      c = Serial.read();  //gets one byte from serial buffer
      //Serial.println(readString);
      if (c == '*') {
        Serial.println(readString);//test response
        if (readString == "crx") {
          cnt_steps = cnt_steps + 1;
          Serial.println(cnt_steps);
          digitalWrite(pinEnable, LOW);
          digitalWrite(dirPinX, HIGH);
          for (int x = 0; x < unit_len; x++) {
            digitalWrite(stepPinX, HIGH);
            delayMicroseconds(500);
            digitalWrite(stepPinX, LOW);
            delayMicroseconds(500);
          }

        }
        else if (readString == "clx") {
          cnt_steps += -1;
          Serial.println(cnt_steps);
          digitalWrite(pinEnable, LOW);
          digitalWrite(dirPinX, LOW);
          for (int x = 0; x < unit_len; x++) {
            digitalWrite(stepPinX, HIGH);
            delayMicroseconds(500);
            digitalWrite(stepPinX, LOW);
            delayMicroseconds(500);
          }
        }
         digitalWrite(pinEnable, HIGH);//lock driver on cnc shield
         c = (char)0;
         Serial.flush();
         readString = "";
         //resetFunc();
      }

      else {
        readString += c; //makes the string readString

      }
    }
  }
}

void loop() {

}

What are you sending to to your sketch? What does it print back on the serial port?

@EdgarBonet I send the commands "crx*" for clockwise rotation and "cry*" counterclockwise and "*" is the criterion for stopping character reading. The sketch should not print anything, but I asked it to print the commands sent to see if the reading was correct

This sketch will not understand "cry*": it expects either "crx*" or "clx*". 2. Re “The sketch should not print anything”: It should. It has some Serial.println() here and there. Let me ask again: what does it print to the serial port?

@EdgarBonet Ignore the "cry*". It was a typo. The correct one is "clx*". When receiving one of the aforementioned commands, the sketch must perform the loops contained within the conditions, as shown in the script. The Serial.println() are exclusively for making sure that the serial reading of the characters is being done. Can be commented. Depending on the conditions, the sketch acts on digital ports 2, 5 and 8 through the loops.

@EdgarBonet What happens is that the sketch executes the loops only after the first command is sent via serial. If I try a second time, nothing happens. It's as if the serial read doesn't match any of the "crx*" or "clx*" conditions.

How are you sending the commands to the sketch? Are you using the Arduino's serial monitor? If so, did you configure a line ending?

@EdgarBonet The problem is the line ending. Your guess was correct. Thanks a lot!

When sending text commands to an Arduino, it is common to define a
“line-oriented protocol”: each command is transmitted as a single line,
with the line ending signifying the end of the command. Common line
endings are carriage return (CR = '\r' = 0x0d = 13), line feed (LF =
'\n' = 0x0a = 10) and the sequence CR+LF.
The Arduino serial monitor is designed to support this convention by
automatically appending a line ending when you press “Send”. This line
ending can be configured to one of the following options:

No line ending
Newline (meaning “line feed”)
Carriage return
Both NL & CR (but CR is actually sent before LF)

In your case, you have chosen to use '*' as a command termination
character. For this to work, you have to choose “No line ending” and add
the “*” explicitly to the command. Alternatively, you may consider
changing your sketch so that it expects '\r' or '\n', which is a
more standard way of ending a command.

In addition to the good responses you have already received, I offer this.
For the Arduino, know the differences between String string and char arrays - there is much on this e.g., https://forum.arduino.cc/t/string-vs-string-vs-char-arrays-correct-approach/537468 . Many do not want to deal with the vagaries of String, but their use can be convenient.
Run this code:
String readstring = "xxx";

void setup() {
  Serial.begin(115200);
}

void loop() {
  if (Serial.available()) {
    readstring = Serial.readStringUntil('/n');
    Serial.print(readstring);
    Serial.println(" received");
    if (readstring.equals("crx")) {
      // move counter clockwise
      Serial.println("moving counter clockwise");
      // counterclockwise() <-- your function
    }
    else if (readstring.equals("clx") ) {
      // move clockwise
      Serial.println("moving clockwise");
      // clockwise() <-- your function
    }
    else {
      // bad command
      Serial.println("Bad command received - no action");
      // badcommand() <-- your function
    }
  }
}

If you add functions for the stepper, it may do what you want within a limited context and with using the Arduino serial monitor for input. Take a look at the output.

Note that the serial monitor is set to "no line ending". The terminating character '/n' is provide by your input in the serial monitor. It will do what you want, but again, many advise you stay away from String.

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


text:
TMRpcm not compatible incompatible with current board
My goal is to play sounds with my Arduino Nano Every. I tried the example sketch that comes with the library but I get the error:
**WARNING: library TMRpcm-master claims to run on avr architecture(s) and may be incompatible with your current board which runs on megaavr architecture(s).**

Is there such a big difference between the Nano and Nano every?

All the peripherals (timers, comms, programming etc. etc) have changed so code which directly accesses hardware registers (say to configure a timer) may fail. Some libraries already have some compatibility. Others may never be updated. If you have to get the MCU data sheet out to solve low level device access/control issues, you'll find yourself in a new world. You could try opening an incompatibility issue for this particular library here: https://github.com/TMRh20/TMRpcm/issues

I opened a issue on GitHub and the result is: tmrpcm only runs on avr architecture so it is incompatible with megaavr architecture(s).


text:
Forget WiFi ESP32
How can you make ESP32 forget all the Wi-Fi networks it was connected to? Or at least forget the one to which the board is currently connected?

WiFi.disconnect()

It only disables Wi-Fi, but when the ESP32 is turned on, it connects again automatically

connect to another network

https://docs.espressif.com/projects/arduino-esp32/en/latest/api/wifi.html#disconnect

or erase the flash memory

Thank you! Use WiFi.disconnect(false, true)


text:
Reply from the SIM800l module is being cut short
I have a sim800l module connected to the Rpi pico hardware UART
/*
SIM800       RPi Pico
5v           *External 2A 5v supply*
GND          GND
VDD          3v3
TXD          GP1
RXD          GP0
*/

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

  while (!Serial)
    ;

  Serial1.begin(9600);

  Serial.print("Initializing");
  delay(1000);
  Serial.print(".");
  delay(1000);
  Serial.print(".");
  delay(1000);
  Serial.println(".");

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial1.println("AT"); //Once the handshake test is successful, it will back to OK
  updateSerial();
  delay(3000);

  Serial1.println("ATI"); //Returns the module name and revision.
  updateSerial();
  delay(3000);

  Serial1.println("AT+CCID"); //Read SIM information to confirm whether the SIM is plugged
  updateSerial();
  delay(3000);

  Serial1.println("AT+COPS?"); //Checks which network you are connected to
  updateSerial();
  delay(3000);

  Serial1.println("AT+COPS=?"); //Returns the list of operators present in the network.
  updateSerial();
  delay(3000);

}

void loop()
{
  updateSerial();
}

void updateSerial()
{
  delay(200);
  while (Serial.available())
  {
    Serial1.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while (Serial1.available())
  {
    Serial.write(Serial1.read());//Forward what Software Serial received to Serial Port
  }

}

terminal response
AT
OK
ATI
SIM800 R14.18

OK
AT+CCID
XXXXXXXXXXXXXXXXXXXX
AT+COPS?
+COPS: 0,0,"Vodaa TelAT+COPS=?
+COPS: (2,"Vodaa Telecom","Ver

From what i know so far the SIM800L always ends its response with an "OK" but there are some commands that are cut short and not end with OK.  such as AT+CDID and AT+COPS. I do not know if the problem is with the pico or with sim800l. The sim800l seems to be working fine so i suspect its with the pico but if so, it might be a problem with the internal libraries which is beyond me.  To supoort that theory the number of characters that is being cut is about 20 characters, so it might be a setting i have to adjust

hint:   always ends its response with an "OK" ... there is more than OK in the response ... count the number of characters that are actually received

the 115200 baud is slow. there are gaps between bytes so while (Serial1.available()) can end before the complete response is read

@jsotola im sorry i dont get it.. I counted how many serial1.read() pe command.  AT=9 character, ATI = 27 , AT+CCID=31, AT+COPS? = 31,  AT+COPS=? is 9 followed by a long pause then responded with another 31.  looks like 31 is the limit,

@Juraj i dont think i can go any higher than that, i tried to explore that end thinking it was a baud rate issue, according to this thread 115200 is the highest it can go

I didn't suggest higher baud rate but proper reading of the input

Took me quite a while, but upon reading the pico's documentation

The size of the receive FIFO may also be adjusted from the default 32
bytes by using the setFIFOSize call prior to calling begin()
Serial1.setFIFOSize(128);
Serial1.begin(baud);

settinng it to a much higher value like 256 solves the problem


text:
ESP8266 RTC memory (for bootcount)
I'm using an ESP8266 with deep sleep + wake up when RST pin goes low.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
WiFiClient client;
HTTPClient http;
RTC_DATA_ATTR int bootcount = 0;

void setup() {
    bootcount ++;
    WiFi.begin("MySSID", "password");
    while (WiFi.status() != WL_CONNECTED) {
        delay(20);
    }
    // here I send "bootcount" with HTTP request
    ESP.deepSleep(0);
}
void loop() {
}

Here RTC_DATA_ATTR int bootcount = 0; fails with RTC_DATA_ATTR unknown.
How to get the number of times the ESP8266 has woke up from deep sleep?

RTC_DATA_ATTR is for esp32

Thanks @Juraj, you're right, I think you can post this as an answer. Does this mean it's not possible to count the number of times the ESP8266 has resumed/rebooted from deep sleep? How to save/restore a number in RTC memory?

The ESP8266 RTC has 512 bytes of RAM that persist across restarts but not during power outages. While this RAM isn't persistent across power outages it also doesn't have the write limitations that flash memory has, making it appropriate for frequent writes which don't need to survive power loss.
The ESP32's compiler and software framework make it easy to access similar memory on it using the RTC_DATA_ATTR attribute; unfortunately as you found and @Juraj pointed out, the ESP8266's doesn't.
Thankfully the Arduino core for the ESP8266 includes support for reading and writing this area of memory using methods in the ESP object.
ESP.rtcUserMemoryRead() reads RTC memory and ESP.rtcUserMemoryWrite() writes RTC memory. In your case you could do something like this:
void setup() {
  uint32_t bootcount;

  if(!ESP.rtcUserMemoryRead(0, &bootcount, sizeof(bootcount))) {
    Serial.println("RTC read failed!");
    while(1)
      yield();
  }

  bootcount++;

  if(!ESP.rtcUserMemoryWrite(0, &bootcount, sizeof(bootcount))) {
    Serial.println("RTC write failed!");
    while(1)
      yield();
  }

  Serial.begin(115200);
  Serial.print("boot count is ");
  Serial.println(bootcount);
}

void loop() {
}

Not quite as convenient as the RTC_DATA_ATTR attribute but it still gets the job done.
I changed the type of bootcount from your example to uint32_t because it should never be negative, and the size of uint32_t is independent of the size of int.
Because the Arduino core is open source, you can read the implementation of these functions if you want to know how they work.


text:
Error resolving FQBN (Fully Qualified Board Name)
In Arduino IDE, I get this error "Error resolving FQBN: getting", when compiling a sketch. Can anyone help me get around this problem?
I am using the Arduino IDE. I have installed the M5Stack official 2.0.5-1.0 boards in Board Manager and the STAMP-PICO 0.0.2 library in Library Manager.
I get the following Compile error with ALL sketches, even the STAMP-PICO Basics IO example sketch.
"Error resolving FQBN: getting Error compiling for board STAMP-PICO."
Strangely ... in Arduino IDE v2.0.3, on the same computer using the same libraries and boards, the sketch compiles ok.
Sounds like something specific to Arduino IDE v1

@MG1 What board exactly do you have?

OK - I resolved the issue, myself.
The Boards Manager installations became confused, probably because I was using both Arduino 1.8.19 and Arduino IDE 2.0.3 on the same computer.
Somehow, the folder ~/Library/Arduino15/packages/m5stack/hardware/esp32/ contained more than one version of the esp32 board libraries, v2.0.5 as well as v2.0.5-1.0 and c2.0.5+1.0.
My fix involved uninstalling the M5 esp32 board library altogether and making sure that all sub-folder versions had been deleted too. Then, reinstalling the latest board version and restarting the Arduino IDE app.


text:
Single Method for 2 Ultrasonic Sensor is not working as expected
So I have created a method to read and return Ultrasonic Sensor Data. I have 2 Ultrasonic Sensors.
Below is my code.

    // Ultrasonic Pins
    #define T1 2
    #define E2 4
    #define E1 3
    #define T2 5
    // Motor Pins
    #define M1 7
    #define M2 8
    #define M3 9
    #define M4 10
    // Motor Movements Definition
    enum MOTOR
    {
        FORWARD,
        BACKWARD,
        LEFT,
        RIGHT,
        STOP
    };

    long duration1, distance1, duration2, distance2;

    void setup()
    {
        Serial.begin(9600);
        pinMode(E1, INPUT);
        pinMode(E2, INPUT);
        pinMode(T1, OUTPUT);
        pinMode(T2, OUTPUT);
        pinMode(M1, OUTPUT);
        pinMode(M2, OUTPUT);
        pinMode(M3, OUTPUT);
        pinMode(M4, OUTPUT);
        Motor(STOP);
    }

    void loop()
    {

        // If Both Sensors detect object then go in backward Direction
        while (DetectObject(T1,E1,1) < 10 && DetectObject(T2,E2,2) < 10)
        {
            Serial.println("Backward");
            Motor(BACKWARD);
            delay(200);
            Motor(STOP);
            delay(50);
        }
        // If Left Sensor detect object then go in Right Direction
        while (DetectObject(T1,E1,1) < 10 && DetectObject(T2,E2,2) > 10)
        {
            Serial.println("Right");
            Motor(RIGHT);
            delay(200);
            Motor(STOP);
            delay(50);
        }
        // If Right Sensor detect object then go in Left Direction
        while (DetectObject(T1,E1,1) > 10 && DetectObject(T2,E2,2) < 10)
        {
            Serial.println("Left");
            Motor(LEFT);
            delay(200);
            Motor(STOP);
            delay(50);
        }
        // If Both Sensors detect no object then go in Forward Direction
        while (DetectObject(T1,E1,1) > 10 && DetectObject(T2,E2,2) > 10)
        {
            Serial.println("Forward");
            Motor(FORWARD);
            delay(200);
            Motor(STOP);
            delay(50);
        }
    }

    void Motor(MOTOR motor)
    {
        switch (motor)
        {
        case STOP:
            digitalWrite(M1, LOW);
            digitalWrite(M2, LOW);
            digitalWrite(M3, LOW);
            digitalWrite(M4, LOW);
            break;
        case FORWARD:
            digitalWrite(M1, HIGH);
            digitalWrite(M2, LOW);
            digitalWrite(M3, HIGH);
            digitalWrite(M4, LOW);
            break;
        case BACKWARD:
            digitalWrite(M1, LOW);
            digitalWrite(M2, HIGH);
            digitalWrite(M3, LOW);
            digitalWrite(M4, HIGH);
            break;
        case LEFT:
            digitalWrite(M1, HIGH);
            digitalWrite(M2, LOW);
            digitalWrite(M3, LOW);
            digitalWrite(M4, HIGH);
            break;
        case RIGHT:
            digitalWrite(M1, LOW);
            digitalWrite(M2, HIGH);
            digitalWrite(M3, HIGH);
            digitalWrite(M4, LOW);
            break;
        default:
            break;
        }
        delay(100);
    }

    long DetectObject(uint8_t trigPin, uint8_t echoPin, int sensorNo)
    {
        digitalWrite(trigPin, LOW);
        delayMicroseconds(2);
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);
        Serial.print("Distance Sensor");
        Serial.print(sensorNo);
        Serial.print(": ");
        Serial.print(pulseIn(echoPin, HIGH) * 0.034 / 2);
        Serial.println(" cm");
        return pulseIn(echoPin, HIGH) * 0.034 / 2;
    }

I am getting continuously getting Backward in the Serial monitor.
Output of Serial Monitor -
Distance Sensor1: 20 cm
Distance Sensor2: 15 cm
Backward
Distance Sensor1: 17 cm
Distance Sensor2: 21 cm
Backward
Distance Sensor1: 24 cm
Distance Sensor2: 9 cm
Backward

But when I created 2 different methods for each Ultrasonic Sensor. It is working fine.
I want to have a single method for N number of Ultrasonic Sensors.
Thanks in Advance!

@jsotola I have added the output of Serial Monitor.

I think you should try restructuring your loop(). At the start of the loop(), get a value for DetectObject(T1,E1,1) and DetectObject(T2,E2,2) called say Det1 and Det2 respectively. Then change your while statements to if statements, say if (Det1 < 10 && Det2 < 10 ) . . .

@6v6gt Already tried it is not working.

The problem lies in the function, that does the ultrasonic detection. First I would suggest to not do Serial printing between the trigger pulse and pulseIn(), since the Serial transmission might take longer (for example when the buffer is full) and then your reading is garbage. Execute pulseIn() directly after the trigger pulse part and save the result in a local variable, which you can later print and return. If you do that, your problem is also solved.
For understanding what actually happens with your code, I annotated the function with some comments:
long DetectObject(uint8_t trigPin, uint8_t echoPin, int sensorNo)
    {
        // Create Trigger pulse
        digitalWrite(trigPin, LOW);
        delayMicroseconds(2);
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);

        // Do some printing
        Serial.print("Distance Sensor");
        Serial.print(sensorNo);
        Serial.print(": ");

        // Read a pulse and print it directly to Serial
        Serial.print(pulseIn(echoPin, HIGH) * 0.034 / 2);
        Serial.println(" cm");

        // Read ANOTHER pulse and return it
        return pulseIn(echoPin, HIGH) * 0.034 / 2;
    }

As you can see, you are trying to read 2 pulses. But there is only one echo pulse. That one pulse is read by the first execution of pulseIn() and you print the result to Serial, so in the Serial Monitor you are seeing the correct value.
After that you are executing pulseIn() again and returning the result. pulseIn() will wait for a pulse to begin (so it can start counting the time). But there is no second pulse on the echo line, so pulseIn() will exit after a timeout (by default 1s). On timeout this function returns zero. So every time you execute this function, it will return zero.
If you then look at the logic in loop(), you can easily see why you are only getting backwards. The code is stuck in the first while loop, because the value returned from the function is always zero, which is smaller than 10.
Here is a pseudo code version of how your function really should work:
execute trigger pulse
execute pulseIn function and save result in local variable
print whatever you want to Serial
return the value of the local variable

Thanks alot. It's working now. Learned something new.


text:
Confusion regarding PID library?
PID library is available(built in) in standard installation  of arduino IDE or do we have to download it additionaly after installing our IDE?
How can i check which of libraries are available in my standard installation?

Open the Library Manager and search for the library you want. You will
see a list of libraries matching your query. Under the name of each of
those libraries, you will see a line showing the author and the version
number.

if this lines stats with “Built-in”, then it is a library that comes
with the standard installation of the IDE

if the line ends with “INSTALLED”, then this library is installed in
your system.

Can you please name any famoous/common library which is "installed" and also any "library" that is built in?


text:
control 12v motor with NPN transistor via arduino

i want to control this 12v motor via arduino:

Power source is 12v 5A
motor will work 5 seconds in every 5 minutes and will be activated throught arduino mega
i will try to use bd679a darlington transistor:

Collector - Base Voltage (Vcbo)  80 V
Collector - Emitter Voltage (Vceo)   80 V
Collector Current (Ic)   4 A
Power Dissipation (Pd) [Tcase≤25°C]  40 W
Transition Frequency (fТ)    10 MHz
Min. DC current gain (β) 750
Integrated diode Yes
Case    TO-126
Package type    -14h

Do i need to add diode(and will that drop voltage ) ?
also do i need any ressistors and why?

what research have you done? ... there are many tutorials about DC motor control on the web

someone tell they use 12k on DC- and arduino   but no one tell why and how much W resistor should be

also they use 330k resistor from arduino pin to transistor and when i go to buy it ask me to chose 1/4W 1/2W 1W ...  which one should i chose

any of those would work

transistor has Integrated diode , do i need do add any other diode to this diagram

here is one of the tutorials ... https://docs.arduino.cc/learn/electronics/transistor-motor-control

Looks like a relative simple answer is needed but I do not do well with word problems and pictures. Please post a real schematic as you have wired it.

You are missing 2 things:

You should add a resistor between the Arduino digital IO pin and the base of the transistor. Bipolar transistors are current amplifiers. Normally for driving motors with a microcontroller you want the transistor to operate in saturation anyway, so there is no need to fine tune the resistor. It is there for protecting the output pin of the Arduino from over current. The calculation is easy: Resistance is voltage divided by current R = U / I. The voltage is 5V for an Arduino Mega (output voltage of the digital IO pins is equal to the operating voltage of the Mega, thus 5V). The current here is the max current, that the output pin can withstand (you find such information in the datasheet of the microcontroller). It is 20mA for continuous load.
So R = 5V / 20mA = 250 Ohm. Thus you need a resistor with at least 250 Ohm. 330 Ohm is normally readily available, so often people use one of these.
You also asked about how many wants it should withstand. This is also easy to calculate: Power (in Watts) is voltage multiplied by current. So P = U * I = 5V * 20mA = 0.1W. So in this configuration the resistor will not ever need to withstand more than 0.1W. So 1/4W is enough.

When driving motors you should include a flyback diode. This is a diode in reverse direction connected across the terminals of the motor. A motor is an inductive load (since it basically consists of some coils and magnets). Driving it with a varying voltage (like you need for controlling the motors speed or just to start and stop the motor) will induce reverse voltage spikes. These might damage your transistor and/or the Arduino. With the flyback diode connnected these voltage spikes can safely dissipate through that diode and not causing any harm.

So the circuit looks like this:

simulate this circuit – Schematic created using CircuitLab

This is an emitter follower circuit, you will only get the base voltage ~ -0.70 volts depending on the gain, it will not switch. You need to either go to a low side switch or a PNP transistor and the emitter would go to +12. A P-Channel MOSFET would also work. Check your calculations on the 1N4148, under stall condition I believe it will fail.

im using bd679a darlington transistor , can it damage  the arduino   if i dont add 330ohm resistor . is that a MUST or optional?

@wuqnyqow: The base resistor is not optional.


text:
i need help on how to use busy pin in df player to arduino
i need help on how to use busy pin in df player to arduino.... while playing one sound or df player is busy, i don't want to trigger df player by ultrasound sensors to play another song. here is my code without busy pin use in df player
#include "Arduino.h"
#include "SoftwareSerial.h"

#include "DFRobotDFPlayerMini.h"

const byte SENSOR_COUNT = 5;
byte triggerPins[SENSOR_COUNT] = {2,4,6,8,10};
byte echoPins[SENSOR_COUNT]    = {3,5,7,9,11};

SoftwareSerial mySoftwareSerial(12, 13); // RX, TX

DFRobotDFPlayerMini myDFPlayer;

void printDetail(uint8_t type, int value);

void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);

  for( byte i=0; i<SENSOR_COUNT; i++ )
  {
    pinMode(triggerPins[i], OUTPUT);
    pinMode(echoPins[i], INPUT);
  }

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(10);  //Set volume value. From 0 to 30

}

int currentSound = -1;
void loop()
{

  for( byte i=0; i<SENSOR_COUNT; i++ ) // loop through all distance sensors
  {
    if( detectPresence(i) ) // check if there is an object near it
    {
      if(currentSound!=i) // check that it's a different sensor than the one that was last triggered
      {
        Serial.print("play song number ");
        Serial.println(i);
        myDFPlayer.play(i+1); // play song nr `i+1`
      }
      currentSound = i;
    }
  }

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }

}

// detectPresence will return TRUE if there is an object close to it.
bool detectPresence(byte sensorNr)
{
  if( sensorNr>=SENSOR_COUNT )
    return false;
  long duration, distance;
  //digitalWrite(triggerPins[sensorNr], LOW);  // Added this line
  //delayMicroseconds(10); // Added this line
  digitalWrite(triggerPins[sensorNr], HIGH);
  delayMicroseconds(15); // Added this line
  digitalWrite(triggerPins[sensorNr], LOW);
  duration = pulseIn(echoPins[sensorNr], HIGH);
  distance = duration/58;

  return distance<30;// choose your own value here, from which distance it should trigger a sound
}

void printDetail(uint8_t type, int value){

  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

what help do you need? ... what is your specific question?

The busy pin is just a pin, that gets driven LOW, when a song is playing, and HIGH when nothing is playing. So connect it to a free digital IO pin on your Arduino and set that pin to input with:
pinMode(busy_pin, INPUT);

(Note: You yourself need to define busy_pin, since I don't know where you will connect it). Then just read this pin in the if statement together with detectPresence(i):
if(!digitalRead(busy_pin) && detectPresence(i))

The ! is to make the expression true, when digitalRead(busy_pin) returns 0 (LOW). This way the code will not even check for presence, when there is currently a song playing.


text:
I need help with creating a menu using u8g2 library
I want to make a project with a (Nokia 5110) display using u8g2 library.
Here I have the code for my program:
#include <Arduino.h>
#include <U8g2lib.h>
#include <TM1637Display.h>
#include <EEPROM.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#define LED_PIN 5
#define BUTTON_PIN 6
#define BUZZ_PIN 7
#define BUTTON_L 2
#define BUTTON_R 3
#define BUTTON_START 4

//48x84 disp.
U8G2_PCD8544_84X48_F_4W_SW_SPI u8g2(U8G2_R2, 13, 11, 10, 12, 8); //rotate, clk, DIN, CE, DC, RST //

byte lastButtonState = 0;
byte ledState;
float cpu_gauge = 0.0;
char buffer[40];
int move = 7;
float cpu_gauge_step = 0.5;
byte eeprom_led;

void set_led(){
  if( digitalRead(LED_PIN) == 1 ) ledState = 1;
      if( digitalRead(LED_PIN) == 0 ) ledState = 0;}

void backlight(){
byte buttonState = digitalRead(BUTTON_PIN);  //monitor button state
  if (buttonState != lastButtonState) {  //check if not equal
    lastButtonState = buttonState;       //if prev. true, make equal
      if (buttonState == HIGH) {
        ledState = (ledState == HIGH) ? LOW : HIGH;
          digitalWrite(LED_PIN, ledState);    }}}

void status_bar(){
  if (cpu_gauge > cpu_gauge_step*1) u8g2.drawBox(2,13,6,8); //x, y , size in x, size in y
    if (cpu_gauge > cpu_gauge_step*2) u8g2.drawBox(2 + 1*move,13,6,8);
      if (cpu_gauge > cpu_gauge_step*3) u8g2.drawBox(2 + 2*move,13,6,8);
        if (cpu_gauge > cpu_gauge_step*4) u8g2.drawBox(2 + 3*move,13,6,8);
          if (cpu_gauge > cpu_gauge_step*5) u8g2.drawBox(2 + 4*move,13,6,8);
            if (cpu_gauge > cpu_gauge_step*6) u8g2.drawBox(2 + 5*move,13,6,8);
              if (cpu_gauge > cpu_gauge_step*7) u8g2.drawBox(2 + 6*move,13,6,8);
                if (cpu_gauge > cpu_gauge_step*8) u8g2.drawBox(2 + 7*move,13,6,8);
                  if (cpu_gauge > cpu_gauge_step*9) u8g2.drawBox(2 + 8*move,13,6,8);
                    if (cpu_gauge >= cpu_gauge_step*10) u8g2.drawBox(2 + 9*move,13,6,8);
}

void setup(void) {
  pinMode(LED_PIN, OUTPUT);
    pinMode(BUTTON_PIN, INPUT);
      pinMode(BUZZ_PIN, OUTPUT);
       pinMode(BUTTON_L, INPUT);
        pinMode(BUTTON_R, INPUT);
          pinMode(A7, INPUT);
            pinMode(BUTTON_START, INPUT);
              eeprom_led = EEPROM.read(0);
                digitalWrite(LED_PIN, eeprom_led);
                  set_led(); //sets the led state to 1 or 0 depending on digital write
            Serial.begin(9600);
            u8g2.begin();

}

void loop(void) {

    EEPROM.update(0,ledState);
    /*pomiar = EEPROM[ 0 ];
    delay(2500);//
    Serial.println(pomiar);//
    Serial.println(cpu_gauge);
    int pomiar = digitalRead(BUTTON_START);
    Serial.println(pomiar);*/

  backlight();
  cpu_gauge = analogRead(A7) * (5.0/1022);

  u8g2.firstPage();
  do {
  u8g2.drawRFrame(0,12,74,10,3); //pos X,Y  length, width, corner
  status_bar();

  u8g2.setFont(u8g2_font_busdisplay8x5_tr);
    u8g2.setCursor(0,8);
      char pomiar_str[5];
        dtostrf(cpu_gauge,0,2, pomiar_str);
          sprintf(buffer, "LOAD: %sV", pomiar_str);
            u8g2.print(buffer);

  u8g2.setCursor(0,36);
    u8g2.print("bckgrnd_tsks:");
      u8g2.setCursor(48,48);
        sprintf(buffer, "led: %d", ledState);
          u8g2.print(buffer);
            u8g2.drawStr(0,48,"buzz:");

  if (cpu_gauge > 4.80){
    digitalWrite(7,1);
      u8g2.setCursor(0,48);
        u8g2.setFont(u8g2_font_busdisplay8x5_tr);
          u8g2.setFont(u8g2_font_open_iconic_play_1x_t);
          u8g2.drawGlyph(27, 48, 0x0040);}
  else
    digitalWrite(7,0);

  } while ( u8g2.nextPage() );}

I have succesfully made a program, that:
-Has a pushbutton, to turn off, and on the backlight with each press
-Writes to the EEPROM the state of the LED, and reads it at startup
-Displays an analogRead value, from the potentiometer and also displays a progress bar of the given value
-Displays the state of the backlight
-Turns on the buzzer, if the analogRead value exceedes some value
-Displays an indicator, if the buzzer is turned on
Now, let's assume that what this program does, is called option "A", and A in this example works all the time, because there is nothing else.
I want to create a menu, that would have option A, B, C, D. Assume that formatting and pushbutton actions, doesn't matter for now.
A: Is what was described before.
B: Clock. Just display a clock.
C: Stopwatch.
D: Setting the time.
I see two ways of creating such menu.
1: Is to build a selectable/scrollable menu that would have labels, and by choosing, and pressing a button, we would enter desired function.
2: Ditch the selectable menu. One pushbutton will switch from option A to D. Something like a casio watch.
I'd prefer the second option, I think it'll be easier to do
What I don't understand, is the U8G2 reference manual.
I don't really understand the concept of the buffer, sendBuffer, userInterfaceSelectionList, and some more stuff, that I can't name for now.
My understanding is, that i have to make some array, of functions.
Like:
Array [] = {default_display();, clock();, stopwatch();, setting();)

And with a button, I'd go thru this array like so:
Array = 0;
 If (digitalRead(some_button_pin) == High){
  Array + 1;}
If (Array > 3){
 Array = 0;}

And in those funtions, it would have implemented options, like the backlight turned on, or something else, whatever,
Now I don't know if that makes any sense. If it's transferable into code.
I don't know if I need to clear the display, and how do I do that only once before entering the option. How do I make it, so that all the variables related to clock, the stopwatch still work even if I'm not displaying it. I'm honestly lost, and I just need guidance with this, becuase I have only had C for 1 semester at Electrical Engineering. I'm not a programist, but I really want to make it work, but it just isn't explained in the way like I don't know, pulldown resistors, where you can make some assumptions, and with them explain how something works. No, it looks like this:
void u8g2_SetBufferPtr(u8g2_t *u8g2, uint8_t *buf)

And yeah, I just don't know how do I go around it, how do I navigate in it. Thank you for any help.

your code is very badly formatted ... for example, the if statements inside void status_bar() function are not nested, they should all be indented the same amount ... same with the program lines in the setup() function

I'm sorry, I wasn't teached/haven't studied coding ethics, in sense of formatting. Code was easily readable to me, and I could easily find the parts I needed :)
Next time I will use Autoformatting before posting

btw why do you use software SPI for the display?

Because it's a 5110 display, and it only supports SPI communication, as far as I know

I have figured it out.
First thing that has to be said. If you're used to creating function definitions before the setup, you can't do that with u8g2 library. You can create function definitions after calling u8g2.begin in setup. Now there are two ways how you can do it, in the "Casio watch" fashion, but first create a varaible that will read how many times you've clicked, and store that somewhere, and add a condition, that will revert it to 1 after some amount of clicks.
1st way: Create a switch case, where the variable will be your switch, and in the cases (x to n) write what you want, graphics, text, whatever. Now the problem that I've had, is that when I've pasted the same code, and changed only some minor text, the whole thing glitched. It went through 1 and 2, normally, and then everything from case 3 and 4 was merged toghether, and case 4 was empty, and so was the screen. I couldn't fix it, so I came up with the second approach. Create as many IF conditions, as you have menu option. So it goes like this:
If (menu_counter == 1){ //your input to the screen// }
And so for the rest. As far as I have tested this, it works, even if the code is the same for both IF statements. Now I'd have to implement the menu selection list on top. Leaving the answer to my own question, hopefully someone will find it useful.


text:
How do I stop my servo from repeating the loop and perform the rest of the functions?
The project has a makeshift meter (via a half circle cutout and a servo motor operated lever). On program start (button 2), the lever will move to the left hand side at the 9 o'clock position. Once in place, after a short delay, the program will accept input from the button 1 and keep a count while moving the lever toward the 3 o’clock position stopping at at 10-2 w 2 sec delay. When it reaches the position, it stops the count and remembers it.
Repeat same thing but with buttons 4 and 5 respectively. Really important that the count is saved for both buttons 1 and 5.
Pressing button 3 will measure the inputs of button 5 and display them on the meter as a ratio of button 5 presses over button 1 + button 5 presses. If it leans right, that means you had more presses in the first stage than second (for ease of understanding I’ll probably have instructions that say to start with right hand so that leaning right means right hand dominance and left is left handed). Below is a picture of my set up.
*I numbered the buttons 1-5 left to right not by the pin number.
The problem I have is that after button 2 or 4 get pushed the servo just keeps moving to the seven positions I have set as a timer over and over.
#include <Servo.h>

const int button1 = 2;   // button 1 pin/left hand main pin
const int button2 = 3;   // button 2 pin/left start pin
const int button3 = 4;   // button 3 pin/right hand main pin
const int button4 = 5;   // button 4 pin/right start pin
const int button5 = 6;   // button 5 pin/results pin
const int servoPin = 9;  // servo motor pin

int count1 = 0;          // counter for button 1
int count2 = 0;          // counter for button 5

Servo servo;             // servo motor object

void setup() {
  // set button pins as inputs
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);
  pinMode(button5, INPUT);

  servo.attach(servoPin); // attach servo motor to pin
}

void loop() {
  if (digitalRead(button2) == HIGH) {  // if button 2 is pressed
    // move servo motor to 9 o'clock position
    servo.write(180);
    delay(500);  // wait for servo to reach position

    // start accepting input from button 1
    while (digitalRead(button1) == LOW) {
      count1++;  // increment counter
      // move servo motor to 3 o'clock position
      servo.write(180);
      delay(2000);  // wait for servo to reach position
      servo.write(150);
      delay(2000);  // wait for servo to reach position
      servo.write(120);
      delay(2000);  // wait for servo to reach position
      servo.write(90);
      delay(2000);  // wait for servo to reach position
      servo.write(60);
      delay(2000);  // wait for servo to reach position
      servo.write(30);
      delay(2000);  // wait for servo to reach position
      servo.write(0);
      delay(2000);  // wait for servo to reach position

    }

    // repeat the same process for button 4
    while (digitalRead(button4) == LOW) {
      count2++;  // increment counter
      // move servo motor to 3 o'clock position
      servo.write(180);
      delay(2000);  // wait for servo to reach position
      servo.write(150);
      delay(2000);  // wait for servo to reach position
      servo.write(120);
      delay(2000);  // wait for servo to reach position
      servo.write(90);
      delay(2000);  // wait for servo to reach position
      servo.write(60);
      delay(2000);  // wait for servo to reach position
      servo.write(30);
      delay(2000);  // wait for servo to reach position
      servo.write(0);
      delay(2000);  // wait for servo to reach position
    }
  }

  if (digitalRead(button3) == LOW) {  // if button 3 is pressed
    // calculate ratio of button 4 presses to total button presses
    float ratio = (float)count2 / (count1 + count2);

    // Display ratio on meter
    servo.write(90 + (int)(ratio * 90));
  }
}

keep a count while moving the lever toward the 3 o’clock ... your code does not do any counting while the servo is moving

Could you explain please?

your code is move servo, pause, move servo, pause, etc.etc there is no other code while the servo is moving

You might want to learn about finite state machines and experiment with them. This approach will most probably be the appropriate one.

You won't correctly count the button presses unless you do some sort of debouncing. There are libraries that can handle that for you. Also, as pointed out by the busybee, you will have to learn about finite state machines. I recommend this tutorial by Majenko.

You have pulldown resistors on all your buttons, so all of your input pins are LOW when nobody is touching the buttons. When you press a button, the input goes HIGH. In your code, when you do
  if (digitalRead(button2) == HIGH) {  // if button 2 is pressed

it enters the if block, if the button is pressed, because the button2 input is high when the button is pressed. Then you move the servo to position 180 and wait a bit. The next line
    while (digitalRead(button1) == LOW) {

enters the while loop if the input pin is low. The input pin is that, when the button is NOT pressed, because of the pulldown resistor and that is why the servo starts moving when button2 is pressed, unless button1 is also pressed when you press button2. To stop that, change the LOW to HIGH in the while loop condition. Then it will only enter the while loop when the button is pressed and skip it if it is not pressed..
As suggested by the busybee, you might benefit from studying state machines.

Same problem in
while (digitalRead(button4) == LOW) {

and
if (digitalRead(button3) == LOW) {  // if button 3 is pressed


text:
Changing ESP8266 WiFi network via Access Point
I have an ESP8266 project that requires setting the SSID and password for a network via an Access Point.  Everything works fine, the only issue is if you send incorrect credentials to the access point, the server returns an empty response before the timeout period elapses, and the error message is never sent to the client.
If the connection is successful then the success message is appropriately sent to the client.  It's almost like the WiFi.begin() function detects the connection fails on its own, and something there is preventing me from sending my own response.
%  curl -X POST "http://192.168.1.1/authenticate?ssid=FakeNetworkpassword=87654321"
curl: (52) Empty reply from server

Did some research and saw some mentions to keep the loop running, so I attempted to do so below, but to no avail.  Would appreciate any ideas, thanks.
#include "ESP8266WiFi.h"
#include "ESP8266HTTPClient.h"
#include "ESP8266WebServer.h"

HTTPClient http;
WiFiClient client;

ESP8266WebServer server(80);
IPAddress ipAP(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

unsigned long previousMillisConnection = 0;
unsigned long startingMillisConnection = 0;
const unsigned long CONNECTION_PERIOD = 1000;
const unsigned long CONNECTION_TIMEOUT = 10000;

int DELAY = 40;

char ssid[64] = { 0 };
char password[64] = { 0 };

char ssidNew[64];
char passNew[64];

const int STATE_DEFAULT = 0;
const int STATE_CREDS = 1;
int state = STATE_DEFAULT;

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

  WiFi.softAPConfig(ipAP, gateway, subnet);
  WiFi.softAP("ESP8266", "12345678");
  delay(100);

  server.on("/authenticate", HTTP_POST, onSetCredentials);
  server.begin();

  performWifiConnect(ssid, password);
  WiFi.waitForConnectResult(CONNECTION_TIMEOUT);

  Serial.println("Initialization complete");
}

void loop() {
  if (state == STATE_DEFAULT) {
    server.handleClient();
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("Connected!");
    }
  }

  else if (state == STATE_CREDS) {
    whileConnecting();
  }

  delay(DELAY);
}

void performWifiConnect(char ssid[], char password[]) {
  Serial.println("Attempting to connect to " + String(ssid) + "...");
  WiFi.setAutoReconnect(false);
  WiFi.persistent(false);
  WiFi.begin(ssid, password);
}

void onWifiConnected() {
  Serial.println("WiFi connected " + WiFi.localIP().toString());
  WiFi.setAutoReconnect(true);
  WiFi.persistent(true);
}

void onSetCredentials() {
  Serial.println("onSetCredentials");

  server.arg("ssid").toCharArray(ssidNew, 64);
  server.arg("password").toCharArray(passNew, 64);

  if (String(ssidNew) == String(ssid) && WiFi.status() == WL_CONNECTED) {
    Serial.println("Already connected to " + String(ssidNew));
    server.send(200, "application/json", "{ \"success\": true, \"changed\": false }");
  } else {
    Serial.println("Switching from " + String(ssid) + " to " + String(ssidNew));
    state = STATE_CREDS;
    performWifiConnect(ssidNew, passNew);
    startingMillisConnection = millis();
  }
}

void whileConnecting() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillisConnection >= CONNECTION_PERIOD) {
    previousMillisConnection = currentMillis;

    Serial.println("checking connection...");

    // Success
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("Connected to " + String(ssidNew) + " successfully!");

      strcpy(ssid, ssidNew);
      strcpy(password, passNew);

      server.send(200, "application/json", "{ \"success\": true, \"changed\": true }");

      state = STATE_DEFAULT;
    }

    // Failure
    if (currentMillis - startingMillisConnection >= CONNECTION_TIMEOUT) {
      Serial.println("connection failed, attempting to reconnect to old network!");
      Serial.println("ssidOld: " + String(ssid));
      Serial.println("passOld: " + String(password));

      String errorMessage = "Timed out while attempting to connect to " + String(ssidNew);
      Serial.println(errorMessage);
      server.send(500, "application/json", "{\"errorMessage\":\"" + errorMessage + "\"}");

      performWifiConnect(ssid, password);

      WiFi.waitForConnectResult(CONNECTION_TIMEOUT);

      state = STATE_DEFAULT;

      if (WiFi.status() != WL_CONNECTED) {
        Serial.println("Could not return to old network!");
      }
    }
  }
}

I recommend you to use the WiFiManager library. It has the WiFi provisioning solved.

To join an AP esp8266 must change the WiFi radio channel to the channel of the AP. Since the esp8266 has only one radio, the SoftAP must change the channel too. This causes the SoftAP clients to disconnect.
The solution is respond to the configuration request before connecting to AP, then let the configuration page do a new request for the result.
To illustrate here is a simple example:
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif

void setup() {

  Serial.begin(115200);
  delay(500);

#ifdef ESP32
//  WiFi.begin(); // use SSID and password stored by SDK. commented out to test the Configuration AP
#else
//  WiFi.disconnect(); // forget the persistent connection to test the Configuration AP
#endif

  // waiting for connection to remembered  Wifi network
  Serial.println("Waiting for connection to WiFi");
  WiFi.waitForConnectResult();

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println();
    Serial.println("Could not connect to WiFi. Starting configuration AP...");
    configAP();
  } else {
    Serial.println("WiFi connected");
  }
}

void loop() {
}

void configAP() {

  WiFiServer configWebServer(80);

  WiFi.mode(WIFI_AP_STA); // starts the default AP (factory default or setup as persistent)

  Serial.print("Connect your computer to the WiFi network ");
#ifdef ESP32
  Serial.print("to SSID of you ESP32"); // no getter for SoftAP SSID
#else
  Serial.print(WiFi.softAPSSID());
#endif
  Serial.println();
  IPAddress ip = WiFi.softAPIP();
  Serial.print("and enter http://");
  Serial.print(ip);
  Serial.println(" in a Web browser");

  configWebServer.begin();

  while (true) {

    WiFiClient client = configWebServer.available();
    if (client) {
      char line[64];
      int l = client.readBytesUntil('\n', line, sizeof(line));
      line[l] = 0;
      client.find((char*) "\r\n\r\n");
      if (strncmp_P(line, PSTR("POST"), strlen("POST")) == 0) {
        l = client.readBytes(line, sizeof(line));
        line[l] = 0;

        // parse the parameters sent by the html form
        const char* delims = "=&";
        strtok(line, delims);
        const char* ssid = strtok(NULL, delims);
        strtok(NULL, delims);
        const char* pass = strtok(NULL, delims);

        // send a response before attemting to connect to the WiFi network
        // because it will reset the SoftAP and disconnect the client station
        client.println(F("HTTP/1.1 200 OK"));
        client.println(F("Connection: close"));
        client.println(F("Refresh: 10")); // send a request after 10 seconds
        client.println();
        client.println(F("
Configuration AP

connecting..."));
        client.stop();

        Serial.println();
        Serial.print("Attempting to connect to WPA SSID: ");
        Serial.println(ssid);
        WiFi.persistent(true);
        WiFi.setAutoConnect(true);
        WiFi.begin(ssid, pass);
        WiFi.waitForConnectResult();

        // configuration continues with the next request

      } else {

        client.println(F("HTTP/1.1 200 OK"));
        client.println(F("Connection: close"));
        client.println();
        client.println(F("
Configuration AP

"));

        int status = WiFi.status();
        if (status == WL_CONNECTED) {
          client.println(F("Connection successful. Ending AP."));
        } else {
          client.println(F("<form action='/' method='POST'>WiFi connection failed. Enter valid parameters, please.

"));
          client.println(F("SSID:
<input type='text' name='i'>
"));
          client.println(F("Password:
<input type='password' name='p'>

"));
          client.println(F("<input type='submit' value='Submit'></form>"));
        }
        client.println(F(""));
        client.stop();

        if (status == WL_CONNECTED) {
          delay(1000); // to let the SDK finish the communication
          Serial.println("Connection successful. Ending AP.");
          configWebServer.stop();
          WiFi.mode(WIFI_STA);
          return;
        }
      }
    }
  }
}

Using second request is such a nice, simple answer.  Works flawlessly!

There are several intertwined issues in this one.
Firstly, setup() has some code running before it should be.
That first problem is here:
  server.on("/authenticate", HTTP_POST, onSetCredentials);
  server.begin();

  performWifiConnect(ssid, password);
  WiFi.waitForConnectResult(CONNECTION_TIMEOUT);

You've already set ssid and password to be null, and server.begin() won't run the server yet (I'll get to that issue in a minute), so this is setting your credentials to be null at the start of the program. There's no point in running waitForConnectResult() then, because there is nothing to connect. There may be logic in setting performWifiConnect() though, since if you've ever set the Wi-Fi credentials with wifi.begin() before turning off persistent, those credentials are still remembered (it just won't remember new ones).
The next issue is that you're only handling server requests while the connection is not invalid. Thus, when there is an invalid credential for the network, the server doesn't run, and you don't get a response.
void loop() {
  if (state == STATE_DEFAULT) {
    server.handleClient();
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("Connected!");
    }
  }

  else if (state == STATE_CREDS) {
    whileConnecting();
  }

  delay(DELAY);
}

As you can see, server.handleclient() (the actual server; the ability to respond to requests) is only running while it does not have state == STATE_DEFAULT. That is then changed, state = STATE_CREDS;, during the callback for getting network credentials. You'll probably get a reply from the request handler that's currently running, but this will otherwise cause you problems since the server then never responds to any future requests. You must continually call server.handleclient() or nothing server-related will work.
But, something else is also wrong. You can only pass replies back from the server if you actually send them while the server is still processing a request.
else {
    Serial.println("Switching from " + String(ssid) + " to " + String(ssidNew));
    state = STATE_CREDS;
    performWifiConnect(ssidNew, passNew);
    startingMillisConnection = millis();
  }

As you can see, there is no server.send() in this branch, so you'll get no reply. This is likely the most immediate cause of your problem with an empty response.
Instead, you have that in the function whileConnecting(). As noted earlier, the server cannot send replies that aren't in the function it calls when it gets a request, or in functions called by that function. The server does not call whileConnecting(), loop() does. So it can't see or send that reply.
(Side note: This requirement of the server is implemented pretty weirdly, since you're calling server methods while one of its methods calls your code, only for the server to then ask itself what you told it while it was busy with your request, grab that buffer, and return it to the client. But it only does that check somewhere inside server.handleClient(), and other send() calls will either be ignored or get queued to send the next time the client makes a request.)
If you were to wait for a connection inside the server's request handler instead, and then send the error/success messages there too, this might work. It's still bad practice since the server (that part I said you always want to not hold up) and the entire rest of your code will be on hold while it waits to connect, but you'll probably have it work as long as there's nothing else time-critical or important going on.
The best approach would be to have your client poll a second address (or just the same address with no POST values, then have the server check whether there are no args) and have that say whether it is currently connected.
On that note, your connection checking code also has a problem. loop() has a delay in it, which is already going to bog things down. But you also have the whileConnecting function check for elapsed time. This is the proper way to coordinate multiple independent check-back-and-do-stuff operations, so you're aware of it, but this hasn't been transferred to the rest of the code.
Except, also in whileConnecting, you then call WiFi.waitForConnectResult(CONNECTION_TIMEOUT);. This will block that function until a result is present, which thus halts everything else for however long that timeout is. The only place you "should" use this (again, probably bad practice) is inside the server if you were trying to have it directly reply with the connection status or if there's not anything else important going on (which there is, so this is an issue). Since you're already running code periodically on a timer, just have this code check for the timeout directly (easiest method: call the connect function with the credentials, set the check-back time by timeout, then check again), and just reconnect then instead of forcing a wait. This will leave the server and the rest of your code responsive.
Now, with all (well, most) of that put together:
(NOTE: This code will need some changes made to the rest of your code, and may require adjustment itself, but it should get you very close. I suggest making a backup copy of your code first in case you need to reference or fix something. I also wrote this in a text editor, as I don't currently have access to the IDE to test this. There might be minor errors.)
Solution A (have the server wait and tell you the results):
(NOTE: also, delete whileConnecting() and all the state if you use this method; you want to make sure server.handleClient() is always being called until the connection is actually successful, or just plain always.)
void onSetCredentials() {
  Serial.println("onSetCredentials");

  server.arg("ssid").toCharArray(ssidNew, 64);
  server.arg("password").toCharArray(passNew, 64);

  if (String(ssidNew) == String(ssid) && WiFi.status() == WL_CONNECTED) {
    Serial.println("Already connected to " + String(ssidNew));
    server.send(200, "application/json", "{ \"success\": true, \"changed\": false }");
  } else {
    Serial.println("Switching from " + String(ssid) + " to " + String(ssidNew));
    performWifiConnect(ssidNew, passNew);
    startingMillisConnection = millis();
    //code to detect the server connection status and respond starts here//
    WiFi.waitForConnectResult(CONNECTION_TIMEOUT);
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("Connected to " + String(ssidNew) + " successfully!");

      strcpy(ssid, ssidNew);
      strcpy(password, passNew);

      server.send(200, "application/json", "{ \"success\": true, \"changed\": true }");
    }

    // Failure
    if (currentMillis - startingMillisConnection >= CONNECTION_TIMEOUT) {
      Serial.println("connection failed, attempting to reconnect to old network!");
      Serial.println("ssidOld: " + String(ssid));
      Serial.println("passOld: " + String(password));

      String errorMessage = "Timed out while attempting to connect to " + String(ssidNew);
      Serial.println(errorMessage);
      server.send(500, "application/json", "{\"errorMessage\":\"" + errorMessage + "\"}");
    }
  }
}

This solution (A) will probably give you the connection status back, assuming the Wi-Fi connection attempt times out before the cURL request/server does. I haven't actually tested this and I did mention it's kinda bad practice.
Solution B (Poll the server for connection status rather than waiting for a reply):
(Note: Again, delete any state logic and whileConnecting() from the other code.)
void onSetCredentials() {
  Serial.println("onSetCredentials");
  if (!server.hasArg("ssid")){ //check for no-arg request and return conn status//
    server.send("200", "text/plain", (WiFi.status() != WL_CONNECTED)? "Connected" : "Not Connected"); //or whatever other message(s) you want
    //You may also want to add some sort of Serial.print()-type logging here too, since I didn't.//
  }
  else{ //existing connection setup request handler resumes here//
    server.arg("ssid").toCharArray(ssidNew, 64);
    server.arg("password").toCharArray(passNew, 64);

    if (String(ssidNew) == String(ssid) && WiFi.status() == WL_CONNECTED) {
      Serial.println("Already connected to " + String(ssidNew));
    } else {
      Serial.println("Switching from " + String(ssid) + " to " + String(ssidNew));
      performWifiConnect(ssidNew, passNew);
      startingMillisConnection = millis();
    }
  }
}

With Solution B, you can call the cURL command to the ESP8266 without the ssid and password set, and you'll get a connection status back instead. This may take a few attempts while it's still in the process of connecting, but if it remains not connected, you know the credentials are wrong.

If you want to have a web page poll this server using solution B, I suggest the meta refresh HTML tag (note that this will also clear any forms on the current page when it refreshes, so use a frame or have this on a general status page without forms) or the JavaScript "setTimeout" function to run code later/on a schedule.

I'm not sure if all of this is true.  For example, I can indeed reply to the request from another function.  And I think the reason for this is precisely because I don't call handleClient() while the state is STATE_CREDS.  I do want this to be blocking.  The only reason I used the timer method is because, as I mentioned, some people suggested to leave this connection non-blocking, but it did not work either way.  Upvoted because I appreciate the time you took to write this all out, even though it didn't solve my issue.  I think @Juraj's 2-request method is the way to go.

That's quite fair. I hadn't seen the other solution (I had the page loaded the previous day, then worked on it at a more sane hour) and it is the "proper" solution to this without side effects. Hopefully the details help, though? Well, except for the part where I was wrong about being able to reply from another function; I'll have to look into that because I was unaware of that feature...

Yea I mean, if anything it confirms that there's really no way to do it, other than making multiple calls, one before the switch and one after.


text:
Can a three wire Electrical conductivity sensor (Sensorex CS 150) be used directly with arduino?
I am having an electrical conductivity sensor (Sensorex CS150 with three tinned wires Red, Black and white https://sensorex.com/product/sensorex-cs150-12-mm-graphite-contacting-conductivity-sensor/ ). I want to measure EC of nutrient soultion used in aquaponics. I have searched on internet for connection setup and everywhere sensor (with BNC connector) is connected to arduino via expansion board. Do I require this type of expansion board or can I directly connect sensor to analog pin of arduino.

unfortunately the product page doesn't state anything about what exactly each wire is for, nor how it would be connected. Can you link to the sites you found, where a connection to the Arduino is descriped?

EC electrodes is an active sensor that requires an excitation voltage to be applied to get the result. When A DC voltage is apply to the two conductors, it caused iron to be flow from one conductor to another, causing polarisation and chemical reaction. Therefore you can't use it directly with Arduino.
To measure EC you need a Wien bridge oscillator which is used to generate an alternative current(AC) waveform for the excitation of the EC electrode. In order to avoid polarization, an alternative current (AC) typically ranging from 1kHz to 20kHz is used to provide the exitation of the electrode. The AC current is read and converted back to a DC voltage as the measurement result.
You also need a precision amplifier in order to get a meaningful measurement.
The EC value is also subject to temperature changes, so it may also requires to measure the temperature of the liquid and adjust the result for temperature compensation.
I have an product review article where it describe how EC measurement works and what is required (both hardware and software) to measure EC, you might want to further read to understand more.
Other reference:
Conductive of a solution - Andy Connelly.
Conductivity Measurement Theory Guide - .
One-chip conductivity meter monitors salt concentration - Michael Ahmon Electronics/Sept 15, 1977.

Product Manual
Seem to be a simple conductivity measurement so applying a voltage direct from the Arduino via a suitable resistor and using an analog input to measure the voltage drop should work OK. You may need to experiment with the resistor value to get a good range of readings depending on the conductivity of the solution you are measuring