text:
NodeMCU Server side cannot send things to client side - multiple clients attached
I technically need your help, when I am working on my project, I found out that my server-side cannot send data to the client-side, my server-side is made with WiFiServer(80) so it is when my client-side do client.print, it can send to the server-side, and the server-side just easily send to the Python side with Serial, and Python can still send it to the server-side, but the server-side cannot send it to the client-side.  The basic code is from this page

Server Code

Here's the code:
#include <SPI.h>
#include <ESP8266WiFi.h>
#define led LED_BUILTIN
char ssid[] = "AP";
char pass[] = "Science_Fair";
WiFiServer server(80);
WiFiClient client;
IPAddress ip(10, 241, 241, 27);
IPAddress gateway(10, 241, 241, 254);
IPAddress subnet(255, 255, 255, 0);
int i;

void setup()
{
  Serial.begin(9600);
  WiFi.mode(WIFI_STA);
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
  }
  // Serial.println("Connected to WiFi");
  server.begin();
  pinMode(led, OUTPUT);
}

void loop()
{
  client = server.available();
  client.setTimeout(3000);
  Serial.setTimeout(2000);
  if (client)
  {

    // Serial.println("Available");
    if (client.connected())
    {
      Serial.println("Connected");
    }

    while (client.connected())
    {
      // Serial.println(".");

      String request = client.readStringUntil('e');
      if (request == "LR")
      {
        digitalWrite(led, LOW);
        Serial.println("LR");
        for (i = 0; i < 3; i++)
        {
          String reply = Serial.readStringUntil('e');
          if (reply == "WARN_B")
          {
            Serial.println("Confirm");
            client.print("WARN_Be");
            break;
          }
          yield();
        }
      }
      else if (request == "RR")
      {
        Serial.println("RR");
        for (i = 0; i < 3; i++)
        {
          String reply = Serial.readStringUntil('e');
          yield();
          if (reply == "WARN_A")
          {
            Serial.println("Confirm");
            client.print("WARN_Ae");
            break;
          }
          yield();
        }
        yield();
      }
      yield();
    }
  }
  // Serial.println("");
  client.stop();
}

Client A Code

#include <SPI.h>
#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
#define PIR_A D3
#define PIR_B D8
#define led LED_BUILTIN
const char ssid[] = "AP";
const char pass[] = "Science_Fair";
SoftwareSerial DFPlayer_Mini(D1, D2);
WiFiClient client;
IPAddress server(10, 241, 241, 27);
IPAddress ip(10, 241, 241, 28);
IPAddress gateway(10, 241, 241, 254);
IPAddress subnet(255, 255, 255, 0);

void setup()
{
    pinMode(PIR_A, INPUT);
    pinMode(PIR_B, INPUT);
    pinMode(led, OUTPUT);
    DFPlayer_Mini.begin(9600);
    mp3_set_serial(DFPlayer_Mini);
    mp3_set_volume(30);
    WiFi.mode(WIFI_STA);
    WiFi.config(ip, gateway, subnet);
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(100);
    }
    Serial.begin(9600);
}

void loop()
{
    int i;
    float time = 0;
    int PIR_A_VAL = digitalRead(PIR_A);
    int PIR_B_VAL = digitalRead(PIR_B);
    client.connect(server, 80);
    client.setTimeout(1500);
    if (PIR_A_VAL == HIGH)
    {
        while (1)
        {
            time += 1;
            delay(1);
            if (time >= 1000)
            {
                Serial.println("OFD");
                for (i = 0; i < 40; i++)
                {
                    delay(100);
                    yield();
                }
                break;
            }
            else if (PIR_B_VAL == HIGH)
            {
                if (time == 1)
                {
                    client.print("RRe");
                    client.flush();
                    for (i = 0; i < 40; i++)
                    {
                        delay(100);
                        yield();
                    }
                    break;
                }
                break;
            }
            PIR_B_VAL = digitalRead(PIR_B);
            yield();
        }
    }
    else if (PIR_B_VAL == HIGH)
    {
        String fromServer = client.readStringUntil('e');
        yield();
        if (fromServer == "WARN_A")
        {
            mp3_play();
        }
        Serial.println("B Triggered");
        for (i = 0; i < 2; i++)
        {
            delay(1250);
            yield();
        }
    }
    Serial.println("OFL");
    client.stop();
}

Client B Code

#include <SPI.h>
#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
#define PIR_A D7
#define PIR_B D8
#define led LED_BUILTIN
const char ssid[] = "AP";
const char pass[] = "Science_Fair";
SoftwareSerial DFPlayer_Mini(D1, D2);
WiFiClient client;
IPAddress server(10, 241, 241, 27);
IPAddress ip(10, 241, 241, 29);
IPAddress gateway(10, 241, 241, 254);
IPAddress subnet(255, 255, 255, 0);

void setup()
{
    pinMode(PIR_A, INPUT);
    pinMode(PIR_B, INPUT);
    pinMode(led, OUTPUT);
    DFPlayer_Mini.begin(9600);
    mp3_set_serial(DFPlayer_Mini);
    mp3_set_volume(30);
    WiFi.mode(WIFI_STA);
    WiFi.config(ip, gateway, subnet);
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(100);
    }
    Serial.begin(9600);
}

void loop()
{
    int i;
    float time = 0;
    int PIR_A_VAL = digitalRead(PIR_A);
    int PIR_B_VAL = digitalRead(PIR_B);
    client.connect(server, 80);
    client.setTimeout(1500);
    if (PIR_A_VAL == HIGH)
    {
        while (1)
        {
            time += 1;
            delay(1);
            if (time >= 1000)
            {
                Serial.println("OFD");
                for (i = 0; i < 40; i++)
                {
                    delay(100);
                    yield();
                }
                break;
            }
            else if (PIR_B_VAL == HIGH)
            {
                if (time == 1)
                {
                    client.print("LRe");
                    client.flush();
                    for (i = 0; i < 40; i++)
                    {
                        delay(100);
                        yield();
                    }
                    break;
                }
                break;
            }
            PIR_B_VAL = digitalRead(PIR_B);
            yield();
        }
    }
    else if (PIR_B_VAL == HIGH)
    {
        String warnStatus = client.readStringUntil('e');
        yield();
        if (warnStatus == "WARN_B")
        {
            mp3_play();
        }
        Serial.println("B Triggered");
        for (i = 0; i < 2; i++)
        {
            delay(1250);
            yield();
        }
    }
    Serial.println("OFL");
    client.stop();
}

I've tried:
 - Using client.print instead of client.printf
 - Using data with underlines instead of spaces
 - Added client.flush
 - Added client.stop
 - Changed NodeMCU
 - Checked wires
 - Checked power supply
 - Checked the data to send
 - Made the timeout longer
 - Checked speaker
But none of them is working
Please help me guys I'm in a rush, thank you!

try to create a minimal reproducible example without workaround attempts

@Juraj I already did that tho, it is working, but I couldn't solve the problem with that way

And it is almost the same tbh ( I found one, not coded one )

The link is here, I used this guy's example

the code in the instructable is nice and clean. why is yours so cluttered?

@Juraj uh technically I need to add a lot of things some HC-SR501 and a lot of things

I read through the instructable and found - hidden in the comments the following

Author of the instructable:  Would you like to send message to the
  four clients in the same time?
If it is right I can not support you. I am not a expert in this topic.
  My server sends message to the current client only which is triggering
  the server. Using my sketch you can send same message to the clients,
  but in different time. (Remark codebreaker007: which would not work anyway!)

So this solution you have in your code is supposed to work with only one client. So you have to implement yourself a kind of com-sequence wether sever triggered or client side.
Here a short how to add this functionality:
#define MAX_SRV_CLIENTS 4 // max clients connecting

WiFiClient serverClients[MAX_SRV_CLIENTS];

in the loop do the following:
  uint8_t i;
 for (i = 0; i < MAX_SRV_CLIENTS; i++) {
  //check if there are any new clients
  if (server.hasClient()) {
 //find free/disconnected client spot
  if (!serverClients[i] || !serverClients[i].connected()) {
    if (serverClients[i]) serverClients[i].stop();
    serverClients[i] = server.available();
    Serial.print("New client: "); Serial.print(i);
    break;
  }
 }

So you can differentiate between the clients and send with for loop to all or
 serverClients[2].print("WARN Client 2");

Hope this resolves the issue (And read also comments of instructables about problems - the author is actually a newbie)

Uh sorry I couldn't understand you, do you mean by that I need to give it a few more code to it so it can work with more than one client?

YES your solution is only for one client!

Oh man tks, this freacking problem has taken me over a month, deeply thank you

But I am at home now, I can only test at my lab, so I'll test it tmr, tks

I've already given you best answer!

WAIT! No need for WiFiServer?

#include <ESP8266WiFi.h>  look into the library examples, this lib supports client and server code

Sorry my brain was dead haha tks bro

the code in the instructable takes the current client, handles it, closes the connection and forgets the client. then it can handle the next client.

This does not help the OP if he wants to do Server initiated communication with two or more clients attached at the same time


text:
Copying String into another String
I have an array of Strings in my code:
String BitSequence [257];

Each string will have 23~64 characters. At one point in my code, I have to use "myString.remove()" command and I don't want to apply any changes to my original strings. I need to make a copy and perform my commands on the copied string. I did:
MycopyString = BitSequence [1];

but it doesn't work. What tricks do I need to do here to make a copy?

What does "it doesn't work" mean? What did you expect and what actually happened?

don't use String class at all. https://majenko.co.uk/blog/evils-arduino-strings

try strcpy......

@chrisl "What does "it doesn't work" mean? " resulting String is empty.

The Arduino Nano does not have enough RAM to store 257 single-character Strings.

@EdgarBonet I think you are wrong it has 256KB ram which is a lot and could successfully store 1500 Strings each having 64 characters.

"Arduino-Nano" is perhaps a confusing tag then, what device are you talking about?

@DataFiddler sorry for confusion mine is Nano 33 BLE

Edited the tag.

Do not work with the String class on Arduino. That said what to do?
Use char arrays (what an individual String is internally). Then you work with pointers or pointers to pointers. Guessing from the fragments (what type is MycopyString?) you gave, you create a pointer (?) to the element in the array.Working with String class has two disadvantages.

You have to look into the lib to see what a function really does and
by reserving and releasing memory it fractures on the long (most of the time short) run your heap causing your AVR/ESP to crash.

The possibility to create two dimensional arrays
i = 257;
char myTwoDimArray [i][64] = {'\0','\0'}// 64 ... 63 chars + 1 terminator(!)

and then you operate with pointers either to the entry (i) or in the specified char array itself.
How to remove an entry You just write:
i = 23;
myTwoDimArray [i][0] = '\0';

by writing a zero terminator to the first index (starts with 0) of the 24th (!) element (again the index starts with 0) its deleted.
Commands to look for when operating with chars
strcpy (targetChar, charToAdd); // Initializes the targetChar starts at index 0
strcat (targetChar, charToAdd); // Appends to the targetChar starts at current index

converting numeric values to chars:
  char numBuffer [16] = {'\0'}; // Helper buffer for conversions

 itoa (myNumberValue,numBuffer,10);  // converts an integer to a base 10 (decimal) char
itoa (myNumberValue,numBuffer,2);  // converts an integer to a base 2 (binary) char
itoa (myNuberValue,numBuffer,16);  // converts an integer to a base 16 (hex) char

itoa initilizes a char array so we need the helper array:
strcat (targetChar, numBuffer);

to convert float we use
dtostrf(floatVariable, StringLengthIncDecimalPoint, numVarsAfterDecimal, numBuffer);

to convert chars back to int use
int16_t myIntVar = atoi(numBuffer);

to convert chars back to floats use
float myFloatVar = atof(numBuffer, decimalsToShow); // using just atof(numBuffer)
gives you standard x.XX only 2 decimals

Hope this comprehensive intro to chars helps you for your current and future projects.

Ever checked  the result of 64 * 257 ? @Afshin mentions an Arduino Nano.
You're right: Strings are much worse, of course.

Yes I checked but the OP probably not and chars will make him aware ;-) -hopefully

Amazing explanation. It has been a week I started programming Arduinos for a project of mine, and I am kind naive. Thanks a lot.

I don't want to apply any changes to my original strings

You should read about PROGMEM and/or the __FlashStringHelper ( F-Macro ) . Probably you can even handle that vast amount of constant texts on your Nano controller, which is meant to be a controller, not a text processing computer.

You are right! but I need to receive a large file and then process it. I found using string provides me the fastest communication bit rate, maybe I am wrong since I am just a new programmer! Also, Nano BLE has 256KB of ram so, I thought,  this shouldn't be a problem.

Arduino String is never fastest nor least memory consuming. OK, Nano is an atmega328-based Arduino Nano for me (2kB RAM) so my concern might not apply here. Sorry

I had to clarify that I am using Nano 33 BLE. Sorry for confusion

Thank you for all the helpful answers.
I think also found a way to copy strings. Using "myString.substring(from,to)" I could resolve my problem. The command works on array strings as well.
mynewcopystring =mystring[2].substring(0,mystring[2].length());

String has a constructor that takes other strings.
String mycopyString(BitSequence[1]);

will create a new String object named mycopyString with its value initialized to the value of BitSequence[1].
See https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/ for more details

source: Stack Exchange

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

sort: votes


text:
How to respond dynamically by using File Containing Templates?
We are developing a Web Console and REST API for the NodeMCU V3 ESP8266, using ESPAsyncWebServer. We are facing some difficulties to serve dynamic pages using File Containing Templates! We're unable to replace REQ_HOST_ID with request->host() using Template Processor! The following code is working fine when a static host name is supplied.
// server->on("/", HTTP_GET, HomePage::index);

void HomePage::index(AsyncWebServerRequest *request) {
    Serial.println(request->host());
    auto processor = [](const String &var) -> String {
        if (var == "REQ_HOST_ID"){
        //  return F(request->host()); //FIXME
            return F("10.10.10.1");
        }
        return String();
    };
    AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/www/index.html", String(), false, processor);
    response->addHeader("Server", "Academia Web Server");
    request->send(response);
}

Edited:
Commented code causes a compile-time error and needs to be fixed to set the value of request->host(). request->host().c_str() causes the same error!
/Users/Chorke/Documents/Arduino/libraries/AcademiaCoreWeb/src/pages/HomePage.cpp: In lambda function:
/Users/Chorke/Documents/Arduino/libraries/AcademiaCoreWeb/src/pages/HomePage.cpp:16:22: error: 'request' is not captured
             return F(request->host()); //FIXME
                      ^
/Users/Chorke/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/WString.h:38:76: note: in definition of macro 'FPSTR'
 #define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
                                                                            ^
/Users/Chorke/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/WString.h:39:34: note: in expansion of macro 'PSTR'
 #define F(string_literal) (FPSTR(PSTR(string_literal)))
                                  ^
/Users/Chorke/Documents/Arduino/libraries/AcademiaCoreWeb/src/pages/HomePage.cpp:16:20: note: in expansion of macro 'F'
             return F(request->host()); //FIXME

Your help resolving this issue is highly appreciated.

Buggy in which way?

return F(request->host()); causes compile time error! Need to fix this and it belonging  issues. It's suppose to be there is two issue 1. request not accessible inside lambda expression and 2. directly belongs to the data type conversion

A compiler error is not a bug... please include the error message

Fixed:
auto processor = [request](const String &var) -> String {
    if (var == "REQ_HOST_ID"){
        return request->host().c_str();
    }
    return String();
};

Two mistake causes compile time error:

Needs to pass request to the Lambda expression
Need not to wrap the dynamic value with F() macro

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


text:
What is the difference betwen “ESP8266Wifi.h” and “WiFiEsp.h” libraries?
I'll start a project using NodeMCU V3 WiFi Module, which uses esp8266 chip. However, I am undecided as to which library to use. I don't want use a serial bridge with an arduino, I think it is better to use NodeMcu in Standalone mode.
So, here's my question: which library should I use? And, regarding the type of use, what is their difference? (both libraries reference looks like the same for me)
p.s.: I also heard about the "WiFi.h" library. Does it work only on WiFi shields for arduino or does it also work on esp8266?

It's quite simple:

ESP8266WiFi.h - Runs on the ESP8266 to control the WiFi.
WiFiEsp.h - Runs on an Arduino to communicate with an ESP8266 module with AT commands
WiFi.h - Runs on an Arduino to work with the Arduino WiFi shield.

So the one you want, which is part of the ESP8266 core, is ESP8266WiFi.h.

Thanks! But let me ask you one more question: is the syntax the same for both libraries? At least in the examples I saw, they looked the same.

No idea. Probably only superficially of at all.


text:
Serial read SSID and PASSWORD WiFI connection failed in ESP32
Trying to get Wifi SSID and password dynamically from serial monitor and connecting to WiFi, tried the below program, but wifi is always in Connecting state only, it is not getting connected after receiving input from serial monitor.
#include <WiFi.h>

#define BAUDRATE 115200

char ssid[50];
char pass[50];

void setup() {
  Serial.begin(BAUDRATE);
  Serial.println();
  Serial.print("Enter your WiFi credentials.\n");
  Serial.print("SSID: ");
  while (Serial.available() == 0) {
    // wait
  }
  Serial.readBytesUntil(10, ssid, 50);
  Serial.print(ssid);
Serial.print("donessid");

  Serial.print("PASS: ");
  while (Serial.available() == 0) {
    // wait
  }
  Serial.readBytesUntil(10, pass, 50);
  Serial.print(pass);
 Serial.print("donepass");

  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print("Connecting....");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
void loop()
{}

And what results do you actually get on the serial monitor?

Hi Majenko, I got a result like this image.see this screenshot..    https://imgdb.in/gJ6K

You really should learn to use println() so you don't get everything on one line. I suspect your problem is that you have your line ending set to CR & NL but you're only looking for NL (10) so you get extra character 13s in your strings.

Is your Serial Monitor setting set to "Both NL and CR"? Change it to "Newline" should works.
What happened is if your Serial Monitor has a setting of "Both NL and CR", when your press Enter, it generates a \r\n, the Serial.readBytesUntil(10, ssid, 50) picked up that \r at the end of the array, when you use it as SSID, it is not a valid SSID.

Thanks hcheung.. it worked.

Glad I this help. Appreciated if you could accept the answer by click on the tick on the left side of the answer.


text:
Weird behavior when 2 functions are trying(?) to run at the same time
So I just finished my weak project which is a remote controlled car.
My problem is that when I press the button for going reverse (as an example) while the opposite action is currently in progress, going forwards the built_in led flashes in the exact same pattern when the Arduino is restarted (you know, pressing the reset button) and the car just stops and becomes responsive again after the led stops doing it's thing.
I believe the problem might be with the functions that I made, those being Forward(), Reverse(), Left(), Right(), Stop();
Note that if i press 5 (which translates to Stop() in this case) it is behaving as expected.
Here's the code: (functions at the bottom)
#include <IRremote.h>

const int RECV_PIN = 7;
IRrecv irrecv(RECV_PIN);
decode_results results;

int IN1 = 12;
int IN2 = 11;
int IN3 = 10;
int IN4 = 9;

void setup()
{
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  Serial.begin(9600);

  irrecv.enableIRIn();
  irrecv.blink13(true);
}

void loop()
{
  if (irrecv.decode(&results)){
        Serial.println(results.value, HEX);
        switch(results.value){

          case 0xFF18E7: // in fata  - 2
          Forward();
          break;

          case 0xFF4AB5: // in spate - 8
          Reverse();
          break;

          case 0xFF10EF: //   stanga - 4
          Left();
          break;

          case 0xFF5AA5: //  dreapta - 6
          Right();
          break;

          case 0xFF38C7: //   stop  - 5
          Stop();
          break;

        }
        irrecv.resume();
  }
}

void Forward()
{
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  Serial.print("Motor 1 Forward");
  Serial.println();

  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Motor 2 Forward");
  Serial.println();
}

void Reverse()
{
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  Serial.print("Motor 1 Reverse");
  Serial.println();

  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Motor 2 Reverse");
  Serial.println();
}

void Left()
{
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  Serial.print("Motor 1 Reverse");
  Serial.println();

  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Motor 2 Forward");
  Serial.println();
}

void Right()
{
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  Serial.print("Motor 1 Forward");
  Serial.println();

  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Motor 2 Reverse");
  Serial.println();
}

void Stop()
{
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    Serial.print("Motor 1 Stop");
    Serial.println();

    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
    Serial.println("Motor 2 Stop");
    Serial.println();

}

How are you powering the setup?

lol ... did you mean week project, as in seven day project, instead of weak project as in wimpy project?

the power supply may be getting shorted for the time needed to run this command Serial.print();   .... make sure that IN1 and IN2 actually control one motor


text:
Serial monitor reading input strings, but cannot stop a while statement
I have just learned something called 'communication protocols' in Arduino, while I was testing this code, it appears to me that every time I input a string "YELLOW_ON" while statement works perfectly fine, however after that the serial monitor input cannot receive strings anymore. after inputting the string "YELLOW_ON", I cannot input another string which is "YELLOW_OFF" may I know why that is the case?
#include"Display.h"
const int YELLOW_LED = 7;

void setup()
{
  pinMode(YELLOW_LED, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  {
    INPUT_SERIAL();
  }
}

void INPUT_SERIAL()
{
  String INPUT_INFO = Serial.readStringUntil('\n');
  Serial.println(INPUT_INFO);

  while (INPUT_INFO == "YELLOW_ON")
  {
    Display.show("ON");
    digitalWrite(YELLOW_LED, HIGH);
    delay(250);
    digitalWrite(YELLOW_LED, LOW);
    delay(250);
  }
  if (INPUT_INFO == "YELLOW_OFF")
  {
    Display.show("OFF");
    digitalWrite(YELLOW_LED, LOW);
  }
}

Do you have your line endings set to "Both CR&NL" in the serial monitor?

@mejenko, what do you mean by set to both CR and NL, do you mind clarifying it?

In the Serial Monitor in the IDE there is a dropdown box that sets the "line endings". What is that dropdown box set to?

Aha! yes now I got it, it was set to a new line. However, when I changed it to both CR AND NL, the serial monitor receives input strings but does nothing ;/

Ok, New Line is what you want, actually. "CR and NL" will cause problems.

@Majenko , unfortunately if I put a new line it only works for one string and it stops receiving strings ;/

how could INPUT_INFO change in the while loop?

@Juraj Well spotted. Yes. while (INPUT_INFO == "YELLOW_ON") should really be if (INPUT_INFO == "YELLOW_ON").

@Juraj, i don't know what you mean by that, but I want the while loop to be there and I somehow want to stop it, is that possible? I want a permanent blinking of LED and then stop it by inputting a string into serial monitor

@Majenko , then there were no reason for OFF. I don't know how to answer questions with wrong logic. this sketch has so many problems. some are formal like using all uppercase for a variable name, function name etc. OP should take a coding course

From your comments:

I want the while loop to be there and I somehow want to stop it, is
  that possible?

=> yes - press the reset button.When I started programming some decades ago one of the basics was NEVER use while loops.Why? Because you might run into deadlocks like your code does. Options:

Check inside the while for a state change/input to break the while loop (worst choice)
Get rid of blocking code (while/delay() ) and work with if clauses (medium)
Get rid of blocking code (while/delay() ) and implement a state machine with switch case (better)

How to get rid of delays - IDE-file-examples-2 Digital - blinkwithoutdelay


text:
Problem sending strings to another ESP
I am having some problems with retrieving data from another esp. I have two esp8266, one is the access point which has a nextion lcd hooked up to it. The access point reads button presses from the lcd then sends messages to the other esp(the station point) in order to turn on the respcetive digital pins. The station point has two dht22 sensors hooked up to it. I am now trying to sens the temperature data from one of the sensor to the access point to print the data to the screen but I am having some problems(either sending or retrieving the sensor data, not sure how to test it).
Here is the code for the access point:
//this is the acces point
#include <doxygen.h>
#include <NexButton.h>
#include <NexCheckbox.h>
#include <NexConfig.h>
#include <NexCrop.h>
#include <NexDualStateButton.h>
#include <NexGauge.h>
#include <NexGpio.h>
#include <NexHardware.h>
#include <NexHotspot.h>
#include <NexNumber.h>
#include <NexObject.h>
#include <NexPage.h>
#include <NexPicture.h>
#include <NexProgressBar.h>
#include <NexRadio.h>
#include <NexRtc.h>
#include <NexScrolltext.h>
#include <NexSlider.h>
#include <NexText.h>
#include <NexTimer.h>
#include <Nextion.h>
#include <NexTouch.h>
#include <NexUpload.h>
#include <NexVariable.h>
#include <NexWaveform.h>

#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <Nextion.h>

//wifi stuff
WiFiServer server(80);
IPAddress IP(192, 168, 4, 15);
IPAddress mask = (255, 255, 255, 0);

//booleans for check
bool Red1=false;
bool Green1=false;
bool Blue1=false;
bool Red2=false;
bool Green2=false;
bool Blue2=false;
bool Relay1=false;
bool Relay2=false;
bool AmbientTemp=false;
//ints for temp data
//String tempOutside=" ";
String tempInside=" ";
String humOutside=" ";
String humInside=" ";
//buttons
// page id,id,""name"
NexButton b0 = NexButton(1,2,"b0");//red1
NexButton b1 = NexButton(1,3,"b1");//green1
NexButton b2 = NexButton(1,4,"b2");//blue1
NexButton b7 = NexButton(3,2,"b7");//relay1
NexButton b8 = NexButton(3,3,"b8");//relay2
NexButton b9 = NexButton(2, 14, "b9");
NexText t8 = NexText(2,10,"t8");//tremperature inside
NexText t9 = NexText(2,11,"t9");//temperature outside
NexText t10 = NexText(2,12,"t10");//humidity inside
NexText t11 = NexText(2,13,"t11");//humidity outside

NexTouch *nex_listen_list[] = {
  &b0,
  &b1,
  &b2,
  &b7,
  &b8,
  &b9,
  NULL
};
//led strip 1
void b0PushCallback(void *ptr) {
  Red1=true;

  }
void b1PushCallback(void *ptr) {
  Green1=true;
  Serial.println("Green1");
  }
void b2PushCallback(void *ptr) {
  Blue1=true;
  }
//relays
void b7PushCallback(void *ptr) {
  Relay1=true;
  }
void b8PushCallback(void *ptr) {
  Relay2=true;
  }
void b9PushCallback(void *ptr) {
  AmbientTemp=true;
  }

void setup() {
  Serial.begin(9600);
  nexInit();
  b0.attachPush(b0PushCallback,&b0);
  b1.attachPush(b1PushCallback,&b1);
  b2.attachPush(b2PushCallback,&b2);
  b7.attachPush(b7PushCallback,&b7);
  b8.attachPush(b8PushCallback,&b8);
  b9.attachPush(b9PushCallback,&b9);
  //wifi part
  WiFi.mode(WIFI_AP);
  WiFi.softAP("Wemos_AP", "Wemos_comm");
  WiFi.softAPConfig(IP, IP, mask);
  server.begin();
  Serial.println();
  Serial.println("accesspoint_bare_01.ino");
  Serial.println("Server started.");
  Serial.print("IP: "); Serial.println(WiFi.softAPIP());
  Serial.print("MAC:"); Serial.println(WiFi.softAPmacAddress());
}

void loop() {
  nexLoop(nex_listen_list);
  //wifi stuff again
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  //String request = client.readStringUntil('\r');
  Serial.println("********************************");
  //Serial.println("From the station: " + request);
  client.flush();
  //strip 1
  if (Red1==true){
    client.print("redOne\r");
    Serial.println("Red1");
    Red1=false;
    }
  if (Green1==true){
    client.println("greenOne\r");
    Green1=false;
    }
  if (Blue1==true){
    client.println("blueOne\r");
    Blue1=false;
    }
  //relays
  if (Relay1==true){
    client.println("relayOne\r");
    Relay1=false;
    }
  if (Relay2==true){
    client.println("relayTwo\r");
    Serial.println("Relay2");
    Relay2=false;
    }
  if (AmbientTemp==true){
    client.println("AmbientTemp\r");
    Serial.println("ambient temp");
    AmbientTemp=false;
    }
  String tempOutside=client.readStringUntil('\r');
  Serial.println("tempOutside: ");
  Serial.println(tempOutside);
  //t8.setText(tempOutside);
  //tempInside=client.readStringUntil('\b');
  //t9.setText(tempOutside);
  //humInside=client.readStringUntil('\e');
  //t10.setText(humInside);
  //humOutside=client.readStringUntil('\f');
  //t11.setText (humOutside);//halp
  //Serial.println(humOutside);
  //Serial.println("humoutside: ");
  //Serial.print("t11.txt=");
  //Serial.print(humOutside.toInt());
  //Serial.write(0xff);
  //Serial.write(0xff);
  //Serial.write(0xff);
  Serial.println("Byte sent to the station: ");
  //Serial.println(client.println("reeeeeeeeeeeeeeeeeeeee\r"));
  //Serial.println(client.println("IamAlive\r"));
  }

And here is the code for the access point:
#include <DHT.h>
#include <DHT_U.h>
#include <ESP8266WiFi.h>

#define DHTPIN 3 //outside
#define DHTPIN2 0 //inside
#define DHTTYPE DHT22//type of sensor that I am using
DHT dht(DHTPIN, DHTTYPE); //outside
DHT dht2(DHTPIN2, DHTTYPE); //inside

//pins
const int Red = 5;
const int Green = 4;
const int Blue = 14;
const int Relay1= 12;
const int Relay2= 13;
//booleans for on/off(state)
bool RedS=false;
bool GreenS=false;
bool BlueS=false;
bool Relay1S=false;
bool Relay2S=false;
bool AmbientTempS=false;

char ssid[] = "Wemos_AP";           // SSID of your AP
char pass[] = "Wemos_comm";         // password of your AP
IPAddress server(192,168,4,15);     // IP address of the AP
WiFiClient client;
void setup() {
  Serial.begin(9600);
  dht.begin();
  dht2.begin();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);           // connects to the WiFi AP
  Serial.println();
  Serial.println("Connection to the AP");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.println("Connected");
  Serial.println("station_bare_01.ino");
  Serial.print("LocalIP:"); Serial.println(WiFi.localIP());
  Serial.println("MAC:" + WiFi.macAddress());
  Serial.print("Gateway:"); Serial.println(WiFi.gatewayIP());
  Serial.print("AP MAC:"); Serial.println(WiFi.BSSIDstr());
  //pins
  pinMode(Red, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Blue, OUTPUT);
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  digitalWrite(Red, LOW);
  digitalWrite(Green, LOW);
  digitalWrite(Blue, LOW);
  digitalWrite(Relay1, LOW);
  digitalWrite(Relay2, LOW);
}
void loop() {
  client.connect(server, 80);
  Serial.println("********************************");
  Serial.print("Byte sent to the AP: ");
  Serial.println(client.print("Anyo\r"));
  String answer = client.readStringUntil('\r');
  Serial.println("From the AP: "+answer);
  int h = dht.readHumidity(); //humidity for Outside
  int t = dht.readTemperature(); //temperaure for Outside
  int h2 = dht2.readHumidity(); //humidity for Outside
  int t2 = dht2.readTemperature(); //temperaure for Outside
  Serial.println("temp outside: ");
  Serial.println(t);
  Serial.println("Thing: ");
  //Serial.println("temp inside:");
  //Serial.println(t2);
  //client.print(String(t2)+'\b');
  //Serial.println("hum outside:");
  //Serial.println(h);
  //client.print(String(h)+'\e');
  //Serial.println("hum inside:");
  //Serial.println(h2);
  //Serial.println(client.print(String(h2)+"\f"));
  client.flush();
  //stuff
  client.println(String(t)+'\r');
  //stuff again
  if(answer=="redOne"){
    if (RedS==false){
      digitalWrite(Red, HIGH);
      RedS=true;
      Serial.println("Red1 ON");
      }
    else{
      digitalWrite(Red, LOW);
      RedS=false;
      Serial.println("Red1 OFF");
      }
    }
  if(answer=="greenOne") {
    if (GreenS==false){
      Serial.println("Green1 ON");
      GreenS=true;
      digitalWrite(Green, HIGH);
      }
    else{
      Serial.println("Green1 OFF");
      GreenS=false;
      digitalWrite(Green, LOW);
      }

    }
  if(answer=="blueOne") {
    if (BlueS==false){
      Serial.println("Blue1 ON");
      BlueS=true;
      digitalWrite(Blue, HIGH);
      }
    else{
      Serial.println("Blue1 OFF");
      BlueS=false;
      digitalWrite(Blue, LOW);
      }

    }
  if(answer=="relayOne") {
    if (Relay1S==false){
      Serial.println("Relay1 ON");
      Relay1S=true;
      digitalWrite(Relay1, HIGH);
      }
    else{
      Serial.println("Relay1 OFF");
      Relay1S=false;
      digitalWrite(Relay1, LOW);
      }

    }
  if(answer=="relayTwo") {
    if (Relay2S==false){
      Serial.println("Relay2 ON");
      Relay2S=true;
      digitalWrite(Relay2, HIGH);
      }
    else{
      Serial.println("Relay2 OFF");
      Relay2S=false;
      digitalWrite(Relay2, LOW);
      }
  if(answer=="AmbientTemp") {
    if (AmbientTempS==false){
      Serial.println("AmbientTemp ON");
      AmbientTempS=true;
      }
    else{
      Serial.println("AmbientTemp OFF");
      AmbientTempS=false;
      digitalWrite(Red, LOW);
      digitalWrite(Green, LOW);
      digitalWrite(Blue, LOW);
      }
   while(AmbientTempS==true){
    Serial.println("Ambient temp is on!");
    }

    }
  client.stop();
  delay(2000);
  }
}

Thank you and sorry for any mistakes, English is not my first language.

start at the beginning ... reduce your code to sending a single byte or character... when that works reliably, then expand to multiple bytes/characters ... keep adding code in small increments

Will definitely try, had a similar problem and it worked in the end, I still posted the question to see if I made some obvious mistake I didn't catch.

Figured it out, not too sure what was causing it to not send messages but below is the code that is working.

#include <ESP8266WiFi.h>
#include <DHT.h>
#include <DHT_U.h>

#define DHTPIN 3 //outside
#define DHTPIN2 0 //inside
#define DHTTYPE DHT22//type of sensor that I am using
DHT dht(DHTPIN, DHTTYPE); //outside
DHT dht2(DHTPIN2, DHTTYPE); //inside

//pins
const int Red = 5;
const int Green = 4;
const int Blue = 14;
const int Relay1= 12;
const int Relay2= 13;
//booleans for on/off(state)
bool RedS=false;
bool GreenS=false;
bool BlueS=false;
bool Relay1S=false;
bool Relay2S=false;
bool AmbientTempS=false;

char ssid[] = "Wemos_AP";           // SSID of your AP
char pass[] = "Wemos_comm";         // password of your AP
IPAddress server(192,168,4,15);     // IP address of the AP
WiFiClient client;
void setup() {
  Serial.begin(9600);
  dht.begin();
  dht2.begin();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);           // connects to the WiFi AP
  Serial.println();
  Serial.println("Connection to the AP");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.println("Connected");
  Serial.println("station_bare_01.ino");
  Serial.print("LocalIP:"); Serial.println(WiFi.localIP());
  Serial.println("MAC:" + WiFi.macAddress());
  Serial.print("Gateway:"); Serial.println(WiFi.gatewayIP());
  Serial.print("AP MAC:"); Serial.println(WiFi.BSSIDstr());
  //pins
  pinMode(Red, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Blue, OUTPUT);
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  digitalWrite(Red, LOW);
  digitalWrite(Green, LOW);
  digitalWrite(Blue, LOW);
  digitalWrite(Relay1, LOW);
  digitalWrite(Relay2, LOW);
}
void loop() {
  int h = dht.readHumidity(); //humidity for Outside
  int t = dht.readTemperature(); //temperaure for Outside
  int h2 = dht2.readHumidity(); //humidity for Outside
  int t2 = dht2.readTemperature(); //temperaure for Outside
  client.connect(server, 80);
  Serial.println("********************************");
  Serial.print("Byte sent to the AP: ");
  Serial.println(client.print("Muie PSD\r")); //sending data to esp8266
  String answer = client.readStringUntil('\r');
  Serial.println("From the AP: " + answer);
  if(answer=="redOne"){
    if (RedS==false){
      digitalWrite(Red, HIGH);
      RedS=true;
      Serial.println("Red1 ON");
      }
    else{
      digitalWrite(Red, LOW);
      RedS=false;
      Serial.println("Red1 OFF");
      }
    }
  if(answer=="greenOne") {
    if (GreenS==false){
      Serial.println("Green1 ON");
      GreenS=true;
      digitalWrite(Green, HIGH);
      }
    else{
      Serial.println("Green1 OFF");
      GreenS=false;
      digitalWrite(Green, LOW);
      }

    }
  if(answer=="blueOne") {
    if (BlueS==false){
      Serial.println("Blue1 ON");
      BlueS=true;
      digitalWrite(Blue, HIGH);
      }
    else{
      Serial.println("Blue1 OFF");
      BlueS=false;
      digitalWrite(Blue, LOW);
      }

    }
  if(answer=="relayOne") {
    if (Relay1S==false){
      Serial.println("Relay1 ON");
      Relay1S=true;
      digitalWrite(Relay1, HIGH);
      }
    else{
      Serial.println("Relay1 OFF");
      Relay1S=false;
      digitalWrite(Relay1, LOW);
      }

    }
  if(answer=="relayTwo") {
    if (Relay2S==false){
      Serial.println("Relay2 ON");
      Relay2S=true;
      digitalWrite(Relay2, HIGH);
      }
    else{
      Serial.println("Relay2 OFF");
      Relay2S=false;
      digitalWrite(Relay2, LOW);
      }
  if(answer=="AmbientTemp") {
    if (AmbientTempS==false){
      Serial.println("AmbientTemp ON");
      AmbientTempS=true;
      }
    else{
      Serial.println("AmbientTemp OFF");
      AmbientTempS=false;
      digitalWrite(Red, LOW);
      digitalWrite(Green, LOW);
      digitalWrite(Blue, LOW);
      }
   while(AmbientTempS==true){
    Serial.println("Ambient temp is on!");
    }

    }
  client.flush();
  client.stop();
  delay(2000);
  }
}


text:
Is there a better way to combine if statement with an ISR?
In my sketch when an interrupt gets triggered, a state variable is toggled from high to low and vice versa. Depending upon the variable state I have an if statement in the main loop that will call alarm_On function if state is high and the else part of the conditional statement will call alarm_Off function if the interrupt is triggered a second time. Thus I want this if condition to run only when the interrupt is triggered. In all other circumstances I want to run other code but if it concerns the same components e.g. the leds, the other code doesn't execute. If it's not a common component then it works fine. How can I overcome this "common component" issue?
 // Analog Input devices
# define humiditySensor A5

// Alarm input
# define alarmButton 2 // Pushbutton

// Output Devices
# define redLed 10
# define yellowLed 11
# define greenLed 12
# define waterPump 9 // LED on relay
# define spk 5

// Variables
volatile byte alarm = LOW;

void setup() {
  pinMode (alarmButton, INPUT);
  pinMode (redLed, OUTPUT);
  pinMode (yellowLed, OUTPUT);
  pinMode (greenLed, OUTPUT);
  pinMode (waterPump, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(alarmButton), ISR_Alarm, RISING);
  Serial.begin(9600);
}

void loop() {
  if (alarm == 1) {
    alarm_On();
  } else if (alarm == 0) {
    alarm_Off();
  }
  int humVal = analogRead(humiditySensor);
  Serial.println(humVal);
  if (humVal >= 500) {
    digitalWrite(redLed, HIGH);
  } else {
    digitalWrite(redLed, LOW);
  }
} // void loop

void ISR_Alarm () {
  alarm = !alarm;  // toggle alarm function if pushed more than once
}

void alarm_On() {
  tone (spk, 100);
  digitalWrite(waterPump, HIGH);
  static byte ledState = LOW;
  static unsigned long oldTime = 0;
  if (millis() - oldTime >= 250) { // loop to blink leds in emergency
    oldTime = millis();
    if (ledState == LOW) {
      digitalWrite(redLed, HIGH);
      digitalWrite(yellowLed, HIGH);
      digitalWrite(greenLed, HIGH);
      ledState = HIGH;
    } else {
      digitalWrite(redLed, LOW);
      digitalWrite(yellowLed, LOW);
      digitalWrite(greenLed, LOW);
      ledState = LOW;
    }
  }
} // end of alarm on function

void alarm_Off () {
  noTone (spk);
  digitalWrite(redLed, LOW);
  digitalWrite(yellowLed, LOW);
  digitalWrite(greenLed, LOW);
  digitalWrite(waterPump, LOW);
} // end of alarm off function

void high_Humidity() {
  digitalWrite(waterPump, HIGH);
}

void low_Humidity() {
  digitalWrite(waterPump, LOW);
}

the first if - else statement is incorrectly formulated

your code does not block, as far as i can tell .... you should be able to add more functions to loop() without a problem

the alarm_On() code does not need the if (ledState) code block .............. use ledState = ((ledState == LOW) ? HIGH : LOW);  followed by digitalWrite(redLed   , ledState);, etc.

It does block the code if I want to do anything with the components/sensors that are mentioned in the arlam_on & alarm_Off functions. The only case where it doesn't interfere is when the code doesn't involve those components

@jsotola you also mention that the first if-else statement is incorrectly formulated. Can you please tell how can I properly formulate it?

else statements shouldn't have a condition with them.

@Zaffresky, google c++ if-else

Does this even compile? } else (alarm == 0) {

@ThomasWeller, no, the code does not compile ... the compiler returns a expected ';' before '{' token error .... the OP has been negligent in presenting a non-working code

Sorry my bad but I have taken out the errors and repasted the code.

Your code is not blocked, but ON or OFF are called each loop so your change are to the "common" components are overwritten quite fast.
Do not track the state within the IRQ. You could do something like:
volatile byte alarm = 1;
byte alarm_state = 1;

void ISR_Alarm () {
    alarm = 1;
}

void loop() {
    if (alarm){
        alarm = 0;

        if (alarm_state) {
            alarm_state = 0;
            alarm_Off();
        } else {
            alarm_state = 1;
            alarm_On();
        }
    }

    // other code
}

I was using the "blocking" in a different context but indeed the code is not blocking. It was easier to understand with your code example. Thanks


text:
Checking size in flash memory Esp32
I recently purchased an Esp32 and am doing some tests using Arduino IDE.
In one of the tests, I am recording a lot of .txt files with some text inside them in the flash memory, however, I would like to know how I can check the remaining space in the flash memory. I'm checking the flash memory space with Serial.println(ESP.getFlashChipSize());, however, the returned value is always the same.
Is this the right command to check? Why is it always with the same value?

Is this the right command to check? Why is it always with the same value?

The only way that size can change is if you desolder the can from the top of the ESP32 module, then desolder the flash chip, and replace it with one that has a different capacity.
The free space is not a function of the flash chip. It is a function of the filesystem you are using to store your data - be that SPIFFS or FAT.
You should check the manual for the filesystem you are using to find what functions there are pertaining to space usage.

Looking the source code I find the methods!
https://github.com/espressif/arduino-esp32/blob/master/libraries/SPIFFS/src/SPIFFS.cpp

The file system on the ESP32 is stored in a portion of the flash memory, and managed by the SPIFFS (SPI Flash File System) library. You can use the SPIFFS.info() function to get information about the file system, including the total size and the used size.
Assuming you have SPIFFS:
#include <ESP.h>
#include <SPIFFS.h>

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

  // Initialize the SPIFFS file system
  if (!SPIFFS.begin(true)) {
    Serial.println("Initialization failed!");
    return;
  }

  // size of the compiled program
  uint32_t program_size = ESP.getSketchSize();

  // size of the file system
  FSInfo fs_info;
  SPIFFS.info(fs_info);
  uint32_t file_system_size = fs_info.totalBytes;

  // used size of the file system
  uint32_t file_system_used = fs_info.usedBytes;

  // free size in the flash memory
  uint32_t free_size = ESP.getFlashChipSize() - program_size - file_system_size + file_system_used;

  Serial.print("Program size: ");
  Serial.print(program_size);
  Serial.println(" bytes");

  Serial.print("File system size: ");
  Serial.print(file_system_size);
  Serial.println(" bytes");

  Serial.print("File system used: ");
  Serial.print(file_system_used);
  Serial.println(" bytes");

  Serial.print("Free space: ");
  Serial.print(free_size);
  Serial.println(" bytes");
}

void loop() {
  // Do Nothing Here
}

Serial.println(ESP.getFlashChipSize());
don't return the physical flash size, it just returns the flash size that you have selected in the Arduino IDE Flash size.
Just try to set Flash size "2MB (16Mb)"
And the result is '2097152'

And if you want a bigger file system size, you can create your own partition table. Look at partitions.csv


text:
How to round up millis() when divided into minutes?
unsigned long milliseconds=millis();
// if at time of reading the above milliseconds = 599999 ie 1 millisecond short of 600000 ie 10 minutes
unsigned long minutes = (milliseconds/1000)/60;
// this will return 9 instead of 10.

How do you round the result to 10 minutes? I don't mean adding 1 to final result. It has to be within the calculation.

To round to the nearest X in fixed point arithmetic: add 1/2 X (in the base units, msec, in this case) and divide by X (again, in the base units) so:
milliseconds = (milliseconds + (30*1000L))/(60*1000L);
The addition of 1/2 X causes a carry of one whole X if the fractional X in the original quantity was 1/2 X or greater. (Likewise, if the fractional X was less than 1/2 X, no carry will result).
Integer division naturally truncates any fractional amounts, so you'll be left with the rounded integer result.

Here is a simple trick how to switch from integer math to floating point math and use round function.
  unsigned long milliseconds = 599999;

  unsigned long minutes_long = (milliseconds/1000)/60;
  // minutes_long = 9

  double minutes_double = (milliseconds/1000.0)/60.0;
  // minutes_double = 9.99998...

  double minutes_rounded = round(minutes_double);
  // minutes_rounded = 10

There also exists a trick that allows calculation of round using integer math. It's perfect if you don't have enough memory for a cast.
  unsigned long milliseconds;

  milliseconds = 600000 - 30*1000 - 1;
  //milliseconds = 569999

  unsigned long minutes_9 = (milliseconds+30000)/60000;
  // minutes_9 = 9

  milliseconds = 600000 - 30*1000;
  //milliseconds = 570000

  unsigned long minutes_10 = (milliseconds+30000)/60000;
  // minutes_10 = 10

try double minutes_double = (milliseconds/1000.0)/60.0;


text:
How can I start freshly? Libraries mess Wemos D1 Mini
I am using a wemosd1 MINI which has a ESP8266 module. I am using it for an IoT project, however a lot has been going wrong.  With libraries and version types. I want to start over but noticed that simply reinstalling arduino didnt do tha trick. How can i restart?

Windows, Linux or Mac?

Delete your IDE's data folder and libraries folder.

I don't understand, what your problem is. If you have a big mess of libraries, you can just delete the libraries from the libraries folder

Windows! Deleting the libraries causes conflicts in my program i feel like i deleted some curical ones as well.

Of course if you delete the libraries you won't be able to compile your program. It's after deleting that you need to the install the right versions of the right libraries.


text:
Connecting two sensors to one analog pin
I am completely new to programming with Arduino so please bear with me if this seems stupid.
I am using an Arduino Uno R3.
I have two sensors, a Soil Moisture sensor and an LDR Light Sensor. Both of them have one pin marked as A0 on them. So now, do I connect them both to A0 using a breadboard (Like how I am connecting multiple sensors' VCC to the 5V pin currently) OR do I use a different analog pin say A0 for one and A1 for the other? Will it make a difference?

AO is not "Ay Zero", it's "Ay Oh", and stands for "Analog Output". It means it just sends a varying voltage. It really doesn't care where it's sent to, it just sends it.
It's up to you where you connect that output to. But suffice it to say it wants to be connected to an input that can read an analog signal. And the Arduino has 6 of them.
Which one you connect it to is entirely up to you - you just have to read from that analog input by using the right pin number in analogRead().

(https://i.stack.imgur.com/Rm3On.jpg)
you can simply connect one in the A0 and the other in the A1 since all those pins can be used for the same function


text:
SIM900A network connection
I can't connect to the network.
Hardware used: Arduino UNO and SIM900A GSM module
Tutorial used: https://www.instructables.com/id/GSM-SIM900A-With-Arduino/
Sim card used: Orange (I set it on 2G frequency and disabled pin code)
I am from Romania.
Based on the tutorial above, once the connection is established successfully, the status/network LED on the SIM900A will blink continuously every 3 seconds. This does not happen to me, so it is a problem from the start. It keeps on searching for a network to connect.
Would you mind helping me, please?
Thank you so much!


text:
Why doesn't this timer code work?
Why doesn't the code below work? Timer will count 370ms then function called to ON LED. Again 370ms then function called to OFF LED. Basically a toggle function.
int IN0 = 12;
int IN1 = 11;
int OUT1 = 10;
int OUT2 = 9;
int OUT3 = 7;
int OUT4 = 6;
int LED = 13;
unsigned int count = 370;
unsigned int tcount = 0;
bool tflag = 0, mflag = 0, sflag = 0, lflag = 0, rflag = 0;
int a, b;

void setup() {
  pinMode(IN0, INPUT);
  pinMode(IN1, INPUT);
  pinMode(LED, OUTPUT);
  pinMode(OUT1, OUTPUT);
  pinMode(OUT2, OUTPUT);
  pinMode(OUT3, OUTPUT);
  pinMode(OUT4, OUTPUT);
  Timer1.initialize(a); // 370 miliseconds on time
  //Timer1.attachInterrupt(flash);
}

void flash_on() {
  //digitalWrite(LED, !digitalRead(LED));
  digitalWrite(LED, HIGH);
}

void flash_off() {
  //digitalWrite(LED, !digitalRead(LED));
  digitalWrite(LED, LOW);
}

void loop() {
  Timer1.attachInterrupt(flash_on);
  a = count;
  Timer1.attachInterrupt(flash_off);
  a = count;
}

At what point do you give the timer the new value you have put in a? Never.

You should give a a value before calling Timer1.initialize(a).
For example, like this:
void setup() {
  ....
  a = count;
  Timer1.initialize(a); // 370 miliseconds on time
  ....
}

Your loop() code will also not work like you expect it to.
As it is, you will be switching between two different ISRs very fast, without having any control over which of the two will be called once the Timer1 interrupt occurs.
It will be better to stick to one ISR that toggles the LED. That’s kind of the point of a Timer interrupt.

Here, in loop() i've called flash_on() the reason is i've to check the other parameter by polling. Just by toggling in my opinion i cannot do that. If there is any way to do with toggling, request you to please guide me with same.


text:
What are the units of output of soil moisture sensor?
I want to use a soil moisture sensor using arduino uno R3. I am using the analog output. The values are in the range of 100 to 1300 as in the readings mention in this question.
May I know what exactly these numbers mean? I read in a website that:

Most soil moisture sensors are designed to estimate soil volumetric water content based on the dielectric constant (soil bulk permittivity) of the soil.

So what are the units? Basically I want to base an estimate for the normal amount of soil moisture for typical loamy soil and I don't understand how to base this threshold based on the readings given by the sensor. It would be greater help if someone actually knows what an appropriate soil moisture threshold is for loamy soil.
I searched on the internet but the closest i could come to answers was this table and this particular entry:

Table 1.1. Typical field capacity and wilting point values (m^3
   m^(–3)) for different soil textures
Soil texture| Field capacity| Wilting point| Available water
Loam    |0.27| 0.12| 0.15|

I am so sorry if I seem confused but I am very new to the whole of sensors and electronics
This is the sensor that I am making use of

They measure units of moistosity. That is from dry to wet. The numbers themselves have no intrinsic meaning. At least not without more details about the "soil moisture sensor" that you're using.

@Majenko I have added the senor details that I have used in case it gives something more to work with :)

That device has no units. It doesn't measure anything absolute. It only gives you a voltage that is in proportion to the resistance of the soil compared to some other resistance that isn't specified. So it's just a number from dry to wet. Or maybe wet to dry. Even that isn't clear.

Also that kind of soil moisture sensor is the worst kind of moisture sensing you can possibly do. Fine short term for a pot plant I suppose, but it will corrode in no time unless you take special measures, and the results are, as you see, pretty meaningless. A proper soil moisture sensor costs a lot more and looks like this: https://www.davisinstruments.com/product/soil-moisture-sensor-vantage-pro-and-vantage-pro2/

Oh. Makes sense. But this was for the sake of experimentation. So.

Such cheap sensors are fine for learning and playing around with.

@Majenko: actually the Watermark sensors are soil water potential sensors, not soil water content sensors. Seems even people selling them don't always understand the difference.

Those sensors have no units. If you can find a schematic you could possibly relate the value to the resistance of the soil, but you'd need to know the resistance that the soil is paired with to form the resistive divider.
All you can say from the numbers is "This is wet" or "This is dry". Normally you would use trial and error to determine what the values roughly relate to, and say that "Anything under X should trigger watering. Anything over Y should stop watering."

So what exactly are the outputs obtained in the question I had linked? Were they resistances?

They are the ADC values that equate to the voltage that is read from the sensor which is related to the resistance of the soil and the resistance of the (unknown) resistor in the sensor circuit.

You could calibrate the sensors by measuring the output value in soil of known moisture but it probably wouldn't be worth it because those sensors corrode. There are some very inexpensive capacitance sensors available which would be better


text:
Error compile board LOLIN(WEMOS) D1 R2 & mini
I have a wemos d1 mini and a mpu 6060 sensor. I am trying to send the data from the sensor to Firebase. However i have come across a hurdle which i cant seem to solve. This is my error, can you help me out with this issue?
Error compiling for board LOLIN(WEMOS) D1 R2 & mini.
In file included from C:\Users\Zakaria\Documents\Arduino\libraries\firebase-arduino-master\src/Firebase.h:30:0,

                 from C:\Users\Zakaria\Desktop\WORKING_ACCELERAMETOR_BACKUP\WORKING_ACCELERAMETOR_BACKUP.ino:4:

C:\Users\Zakaria\Documents\Arduino\libraries\firebase-arduino-master\src/FirebaseObject.h:109:11: error: StaticJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6

     std::shared_ptr<StaticJsonBuffer<FIREBASE_JSONBUFFER_SIZE>> buffer_;

           ^

In file included from C:\Users\Zakaria\Desktop\WORKING_ACCELERAMETOR_BACKUP\WORKING_ACCELERAMETOR_BACKUP.ino:4:0:

C:\Users\Zakaria\Documents\Arduino\libraries\firebase-arduino-master\src/Firebase.h:86:11: error: StaticJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6

   std::shared_ptr<StaticJsonBuffer<FIREBASE_JSONBUFFER_SIZE>> buffer_;

           ^

Using library FirebaseJson at version 2.3.3 in folder: C:\Users\Zakaria\Documents\Arduino\libraries\FirebaseJson
Using library firebase-arduino-master at version 0.1 in folder: C:\Users\Zakaria\Documents\Arduino\libraries\firebase-arduino-master
Using library ArduinoJson at version 6.15.0 in folder: C:\Users\Zakaria\Documents\Arduino\libraries\ArduinoJson
Using library ESP8266HTTPClient at version 1.2 in folder: C:\Users\Zakaria\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\ESP8266HTTPClient
Using library ESP8266WiFi at version 1.0 in folder: C:\Users\Zakaria\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\ESP8266WiFi
Using library Wire at version 1.0 in folder: C:\Users\Zakaria\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\Wire
exit status 1
Error compiling for board LOLIN(WEMOS) D1 R2 & mini.

it says: "error: StaticJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6". so install ArduinoJson 5.x or do the upgrade steps


text:
One ISR should be called, but both ISR has been called on Arduino UNO
I experimenting with the interrupt ISR using Arduino Uno. In my circuit, I am taking two mechanical switches that are connected with Uno's interrupt pins, pins 2 and 3, and also taking a built-in LED to confirm the ISR call.
My logic is when I press switch1 (which is connected to pin 3) or I press switch2 (which is connected to pin 2) LEDs should be turned on/off by the interrupt service routine.
My problem is that when I pressed switch1 and both ISR are called multiple times.
Here's my code:
const int mechanicalSwitchUpPin = 2, mechanicalSwitchDownPin = 3;

volatile byte stateSwitchUp = HIGH, stateSwitchDown = HIGH;

inline void upCallback()
{

  Serial.println("u");

  stateSwitchUp = digitalRead(mechanicalSwitchUpPin);

}

inline void downCallback()
{

  Serial.println("d");

  stateSwitchDown = digitalRead(mechanicalSwitchDownPin);

}

void setup()
{

  Serial.begin(115200);

  pinMode(13, OUTPUT);

  pinMode(mechanicalSwitchUpPin, INPUT);

  pinMode(mechanicalSwitchDownPin, INPUT);

  digitalWrite(mechanicalSwitchUpPin, HIGH); //Enable Pull-Up resistor to this pin

  digitalWrite(mechanicalSwitchDownPin, HIGH);//Enable Pull-Up resistor to this pin

  attachInterrupt(digitalPinToInterrupt(mechanicalSwitchUpPin), upCallback, RISING);

  attachInterrupt(digitalPinToInterrupt(mechanicalSwitchDownPin), downCallback, RISING);

}

void loop()
{

  !stateSwitchUp ? digitalWrite(13, HIGH) : digitalWrite(13, LOW);

  !stateSwitchDown ? digitalWrite(13, HIGH) : digitalWrite(13, LOW);

  delay(1);

}

Here is the output during one short press/release of the button connected to pin 2:
17:10:06.231 -> d

17:10:06.231 -> u

17:10:06.231 -> u

17:10:06.231 -> u

17:10:06.231 -> d

17:10:06.231 -> u

17:10:06.231 -> u

17:10:06.231 -> d

17:10:06.231 -> u

17:10:06.231 -> u

17:10:06.231 -> u

17:10:06.231 -> u

17:10:06.231 -> d

17:10:06.231 -> u

17:10:06.264 -> u

simulate this circuit – Schematic created using CircuitLab

you can use pinMode(mechanicalSwitchUpPin, INPUT_PULLUP);

Your switches are bouncing.  You need to debounce them.  You can do that in software or you can put a small capacitor across the button.  Google the term "debounce" for more information.

you can also use digitalWrite(13, ((!stateSwitchUp) ? HIGH : LOW))

You shouldn't have serial printing in your ISR.

First of all the bouncing phenomenon are really disturbing, there is A Guide to Debouncing by Jack G. Ganssle https://my.eng.utah.edu/~cs5780/debouncing.pdf. Second issue that contributes to the abnormal behaviour is the fact that this is the same interruptable. Doesn't matter SW1 is pressed or SW2 is pressed, both ISR going to be called. Am I right?


text:
how do i know what battery(how much ampere and voltage) my circuit needs to work perfectly?
i really love to make a lot of things  but i always have this problem that i don't know how can i determine what battery(with how much voltage and amp)my circuit must have to work perfectly! please help me:( for example i have two circuits.circuit 1  includes:arduino uno ,2 servo motors and a DFplayer module and an led but i don't know is a 7.4 voltage Lipo battery with 1500mAh suitable for it or not???
and circuit 2 includes:arduino uno,L298 driver & 2 dc motors & 2 ultrasonics sensor but i don't know what battery does it need?
i really love to learn it (determine the battery  my self)

You can guess/calculate/measure the current being used. With that you can calculate how long the project can run on the battery you want to use. You then have the choose if that's a reasonable runtime. Thought there are a lot of tricks to reduce the current being used. For example putting the Arduino in sleep mode. Using an Arduino Pro Mini instead of and UNO, so you don't have the USB chip using up power. etc.

thank youuu, but is there any faster and easier way?it's too time consuming:(

Even 7.4v looks okay for powering the Arduino, it is not a straight answer whether 1500mAh is enough, it also depends on how long you want the battery to last.

@amir this calculator might help. You don't have to be very precise. You just want to get a rough runtime calculation. Like, does is run for hours, days, or months. I often do the first rough extimate this in my head. Then I might do some measurements, or look at the current consumption specified in the datasheet of the different components. Shouldn't take too long.

@hcheung thank you

@Gerben thank youuu.you have no idea how much you helped:)

TL;DR: You really need to know what components you have and you need to find datasheets. In the datasheet, you find what voltage the component requires.
Don't care too much about amperes in the beginning. If you get the voltage right, each component will just draw as much current as it needs.
An Arduino Uno operates from 7 to 12 Volts, so 7.4 V is ok.
"Servo motor" is simply not enough information. There are servo motors for 4.8 V, some for 6 V and others for 12 V. There are even AC servo motors for 240 V~.
DFPlayer is for 3.2 V to 5 V, so it shouldn't be powered directly off the 7.4 V battery. Maybe it can be powered from a 5 V pin of the Arduino. Since they power it from the 5 V pin, it seems to be possible.
Also "LED" is not a term that is good enough. Is it Infrared, Red, Yellow, Green, Violet, UV or white? Depending on the color, it needs something between 1.6 and 3.0 V. Therefore, you need a resistor. What's the use of the LED? Do you need to turn it on and off by Arduino, or can it just be always on from the Lipo battery?
The L298N has a supply voltage from 2.5 V to 46 V, so 7.4 V is fine.
Next, "DC motor" is not specific enough. I have seen 3 V, 5 V, 6 V, 12 V, 24 V.
Also, for ultrasonic, there are SR04 and SRF05. These two operate at 5 V. But if you have a different one, that may not be the case.

it seems that you are a professional teacher and i think you can help me for this question too:i can't understand how much this lipo battery(7.4v) is charged.is there a way i can find out what percentage is charged?or can i make something for it with arduino or anything else that shows what percentage of the it's charge?

thank you so much sir for your help , my servo is MG995(4.8V-7.2V). my led is full color and i turn it on and off by arduino.im not sure but i think my dc motor's voltage is 3volt.my ultrasonics are srf 05.i wanna make a circuit that it works like this:when i turn on the switch servos and DFplayer(circuit1) start working but circuit 2 is off and when i turn the switch off, the circuit 1 will also turn off then dc motors,L298 and ultrasonics(circuit2) start working .is that possible mix two circuit with one arduino? do you think my lipo battry (7.4v)is enough for all of these?


text:
Freezing ESP8266 after 4-8h
Build my own 'Artnet to WS2812b Neopixel' boxes for lighting in a club. Working fine. I have 20 stripes with 50 pxls each. One ESP8266(NodeMCU) is feeding 6 stripes, so it gets 2 DMX universes via Artnet. Depending on the FPS(~20-40FPS) i'm sending, thats about 200-300kbp/s constant bitrate for each of the ESPs.
Every 4-8h one of my boxes freezes randomly. No pinging possible anymore. The other boxes continue working as usual. Only chance of resetting is to disconnect the power.
First, i thought the ESP gets to hot (installed at the clubs ceeling and the power supply is also in such a box) or the humidity is to high, but it must be a software problem (tested it in the oven, dont laugh ;)).
So why isn't the watchdog resetting? I am not able to provoke any of those freezes at home (only waiting)
The code is pretty straight forward:

test the leds
connect to wifi (if no wifi, go to 1)

Loop:

check UDP packets for Artnetdata
update the WS2812 with the fastled-lib

any ideas?
#define FASTLED_ESP8266_NODEMCU_PIN_ORDER
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#include <FastLED.h>

// ARTNET CODES
#define ARTNET_DATA 0x50
#define ARTNET_POLL 0x20
#define ARTNET_POLL_REPLY 0x21
#define ARTNET_PORT 6454
#define ARTNET_HEADER 17

WiFiUDP udp;

#define NUM_LEDS 50

CRGB leds[NUM_LEDS];
CRGB leds2[NUM_LEDS];
CRGB leds3[NUM_LEDS];
CRGB leds4[NUM_LEDS];
CRGB leds5[NUM_LEDS];
CRGB leds6[NUM_LEDS];

unsigned long previousMillis = 0;
int offset=0;

uint8_t uniData[514];
uint8_t maxuni=0;
uint16_t uniSize;
uint8_t hData[ARTNET_HEADER + 1];

const char* ssid     = "*";
const char* password = "*";

IPAddress local_ip(192, 168, 0, 111);
IPAddress gateway_ip(192, 168, 0, 1);
IPAddress subnet_ip(255, 255, 255, 0);

void setup() {
  WiFi.begin(ssid, password);
  WiFi.config(local_ip, gateway_ip, subnet_ip);

  while (WiFi.status() != WL_CONNECTED) {
   delay(500);

delay(2000); // sanity delay
FastLED.addLeds<WS2812, 1, GRB>(leds, NUM_LEDS);
FastLED.addLeds<WS2812, 2, GRB>(leds2, NUM_LEDS);
FastLED.addLeds<WS2812, 3, GRB>(leds3, NUM_LEDS);
FastLED.addLeds<WS2812, 4, GRB>(leds4, NUM_LEDS);
FastLED.addLeds<WS2812, 5, GRB>(leds5, NUM_LEDS);
FastLED.addLeds<WS2812, 6, GRB>(leds6, NUM_LEDS);
initTest();

  }

  udp.begin(ARTNET_PORT); // Open ArtNet port
}

void loop() {

  if (udp.parsePacket()) {
    udp.read(hData, ARTNET_HEADER+1);
    if ( hData[0] == 'A' && hData[1] == 'r') { //checking first two letters, if its Artnet data
      if ( hData[8] == 0x00 && hData[9] == ARTNET_DATA) {
      uniSize = (hData[16] << 8) + (hData[17]);
      udp.read(uniData, uniSize);

      if(hData[14]>maxuni){maxuni=hData[14];}

     switch(hData[14]+1-maxuni){

      case 0: //for each DMX universe updating the pixels
         for (int j=50; j--;){
            leds[j].setRGB(uniData[j*3+offset],uniData[j*3+1+offset],uniData[j*3+2+offset]);
          leds2[j].setRGB(uniData[j*3+150+offset],uniData[j*3+151+offset],uniData[j*3+152+offset]);
          leds3[j].setRGB(uniData[j*3+300+offset],uniData[j*3+301+offset],uniData[j*3+302+offset]);
         }
         break;

      case 1:
         for (int j=50; j--;){
           leds4[j].setRGB(uniData[j*3+offset],uniData[j*3+1+offset],uniData[j*3+2+offset]);
          leds5[j].setRGB(uniData[j*3+150+offset],uniData[j*3+151+offset],uniData[j*3+152+offset]);
          leds6[j].setRGB(uniData[j*3+300+offset],uniData[j*3+301+offset],uniData[j*3+302+offset]);
         }
         break;
     }
}
}
}

FastLED.show();
}

void initTest()
{
//only at Startup checking the LEDs, so nothing special here....}

disconnect the LED strip ... does it still freeze?

it could be power fluctuations, maybe a fat cap from gnd to vcc would help. or a memory leak, keep an eye on the heap size and see if it ticks down over time. Worst case, work on getting them to boot faster, then reboot every few hours.


text:
What is the name of a peripheral which reads servo output data physically?
I know the title is phrased terribly, but I'm not sure how to phrase it since I'm not sure of the name.
I have a servo, that I cannot connect to, except for the output spine/shaft (physically).  I need to get the output of that servo into an arduino, or raspberry pi.  So I need some kind of peripheral that can attach to the shaft of the servo, and tell me what position it's in.  I can't figure out how to find what part I need, because I can't google for the name of it correctly.  I've tried servo input shaft, and many other things that don't make sense.

More Info.
I have a servo on a machine, and I can not interface with this servo in any way but physically.  I can't read the output from it electronically, and the signals are proprietary.  I can't take anything apart, all I can do is put something physically on it.
So, the issue is, I need to (based on nothing but the position of the servo shaft) figure out what position that 3rd party servo is at.
With that information, I'm then going to man in the middle, and attach another servo to my device, and change the value to what I want.
So if the factory servo is at 50%, and I know that by using something like a rotary encoder, if that ends up being the answer, I then could add x% to my actual servo.

google rotary encoder

please provide a clear description of what you are trying to achieve ... why would you need position feedback from a servo? ... the servo actuator can already be commanded to move to specific angles

@jsotola I'll edit the question now to explain.

@jsotola You should write the rotary encoder as the answer, because this is exactly what I needed to know.  Thank you so much!

What you need is an absolute rotary encoder.
It will provide feedback about the absolute rotational position of the servo shaft.
An encoder that uses gray code is preferred because only one binary bit changes between adjacent positions.


text:
OTA-program SPIFFS on the ESP8266
Something I'd like information on is whether it is possible to upload a SPIFFS filesystem image to the ESP8266. In theory it might work: It can be uploaded over USB, and according to the logs the flash location changes, but that's about it. PlatformIO also seems to offer an Upload SPIFFS option in a platform that's set to an OTA port, but that could just be it not checking the upload type.
So, what I want to know is how I can configure (or otherwise make) a SPIFFS image OTA-uploadable. I have two main OTA methods: Option One is the default Arduino OTA library, and Option Two is a re-skin of the OTA method-whose-name-is-forgettable where I can upload a file on a webpage hosted by the ESP8266 and it will read the file and update its firmware.
I'm assuming that there's a configuration parameter for this somewhere, but I don't know where to start looking, and the documentation on these libraries has a few very basic examples that don't cover complex or advanced use cases.
(The web server--though essentially unrelated to this issue, it's a great example--is the most egregious of these; the code is complex and now templated too, so I can't make sense of it, and the "examples" consist largely of compressed javascript that doesn't show the user anything. Then you get to the interesting stuff like actually getting the real size of an uploading file, or want to know how uploading things actually works (or why it fails), or you want to serve a file piecemeal by assembling bits of text (in the same way that debug statements usually make use of multiple Serial.print() statements), and there's just nothing)

ESP8266HTTPUpdateServer supports SPIFFS

How is that integrated? Does it detect the image (or does the user use a different upload page/form/button), how does it perform the physical update, etc?

https://github.com/esp8266/Arduino/blob/d600cc7fa6c3fc5c31ed903ec12fd2e2da2c3678/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h#L14

all ways of OTA updates are applied with Update object from core

Basicly OTA supports the upload of *.bin files. Wether this contains compiled code or a filesystem (SPIFFS/LittleFS) is irrelevant. BUT The space for the OTA (partition) has to be min the size of the *.bin plus an overhead for processing. So with 4MB at all, you would need 2.5MB OTA for 1.5MB App/SPIFFS. To tweak partition sizes (or custom partitions) you have to go into the boards.txt file.OTA - Details and Info here
File system - Details and Info here

Thank you for the links. One of them did hint at the ability, but it's still not clear how it's actually set up, accessed, or used.


text:
Ultrasonic Sensor as Unlock Sensor
Is it possible to use ultrasonic sensors maybe HC SR04 type as unlock sensors? I'm figuring out if it can replace matrix keypad?
For example 6 HC SR04 are used to be an input sensor waiting for a pattern to unlock a certain thing? Usually, in matrix keypad we will push [ 6,0,1,7] as the password is it possible to replace that with ultrasonic sensors as the receiver of input, and if it i possible, what type of code to be used?

I guess you can make it so that when anyone stands in front of it then it unlocks but that doesn’t make it very secure.

Short answer: yes.
General answer: you can use any input device for use as unlock mechanism. You can use a keypad, several single buttons, you can even use a single ultrasonic sensor (and depending on the distance differences from that sensor create a pattern), you can use a microphone, a temperature sensor (that will be tricky to unlock something though).
I would start with a typical example of an ultrasonic sensor sketch and program a pattern recognition algorithm in it. How that sketch would look like exactly, depends on your requirements (how you want to store the pattern, should it be hardcoded or changeable).
First try one sensor, than try multiple (I never tried, but I guess it's possible). If not by a default library, you have to write your own (that will be tricky possibly). Than think about the pattern recognition (values of the ultrasonic sensor in the correct order), than about changing/storing the 'code'.


text:
Unpredictable behavior on parsing key-value delimited input from serial
I am having trouble with a "simple" command parser; I'm guessing I'm doing something wrong with memory allocation - appreciate any pointers :)
For context: I'm running on an Arduino Uno (if it matters). The commands I expect are of the form <key1=value1;key2=value2;key3=value3>. For simplicity here (as well as for my own failed attempts at debugging), I've removed everything extraneous, so that this code just prints back to the serial monitor whatever the current value associated with the key "text" is every time a command enclosed in < > is encountered.
This seems to work correctly until after the first time the key is found; then it behaves somewhat unpredictably - haven't yet been able to discern the pattern.  But, for instance, if I send:
<a=5>
-> EMPTY
<b=7;text=here;d=9>
-> here
<d=abc>
-> here
<d=ghi;e=afds>
-> afds

That last displayed value is wrong, since no new key of text was sent over serial. The complete code is here:

// command indicators
char START_MARKER = '<';
char END_MARKER = '>';

const int MAX_KEY_VALUE_PAIRS = 3;  // maximum number of key-value pairs in message
const int MAX_ELEMENT_CHARS = 25;  // the maximum number of characters (+1 for terminator) in a key or a value

// message format: <key1=value1;key2=value2;key3=value3>
const int MAX_MESSAGE_CHARS = (MAX_KEY_VALUE_PAIRS * (MAX_ELEMENT_CHARS + 1)) * 2 + (MAX_KEY_VALUE_PAIRS - 1) + 2;  // maximum message size

char received_chars[MAX_MESSAGE_CHARS];  // <- EDIT#1
char received_chars[30] ={'\0'};
bool new_data = false;

char *text;  // the value identified by the "text" keyword, i.e.: in <text=abc;time=814a>, text would be abc.

void ParseData(char *str) {
  // This picks off the ;-delimited key-value pairs and assigns them to a multi-dim array
  char * pch;
  int pairs_count = 0;
  char config[MAX_KEY_VALUE_PAIRS][2][MAX_ELEMENT_CHARS];

  pch = strtok(str, "=");

  while (pch != NULL)
  {
    strcpy(config[pairs_count][0], pch);
    pch = strtok(NULL, ";");
    if (pch == NULL) break;

    strcpy(config[pairs_count][1], pch);
    pairs_count++;
    pch = strtok(NULL, "=");
    if (pch == NULL) break;
  }

  for(int i=0;i<pairs_count;i++) {
    if (strcmp(config[i][0], "text")==0) text = config[i][1];
  }
  Serial.println(text);
}

void ReadSerial(){
  // After calling ReceiveText to empty the buffer, if a complete command has been found,
  // parse that command.
  new_data = ReceiveText();
  if (new_data == true) {
    char temp_chars[MAX_MESSAGE_CHARS];  // temporary array for use when parsing
    strcpy(temp_chars, received_chars);
    received_chars[0] = '\0';  // <- EDIT#2
    ParseData(temp_chars);
  }
}

boolean ReceiveText() {
  // This dumps the characters on the buffer so far received_chars, searching for an END_MARKER
  // along the way; if it finds one, it goes back to find a START_MARKER; if that is also found,
  // the string within is the ;-delimited set of key value pairs
  static boolean recv_in_progress = false;
  static byte ndx = 0;
  char rc;

  boolean new_data = false;
  while (Serial.available() > 0 && new_data == false) {
    rc = Serial.read();

    if (recv_in_progress == true) {
      if (rc != END_MARKER) {
        received_chars[ndx] = rc;
        ndx++;
        if (ndx >= MAX_MESSAGE_CHARS) {
          ndx = MAX_MESSAGE_CHARS - 1;
        }
      } else {
        received_chars[ndx] = '\0'; // terminate the string
        recv_in_progress = false;
        ndx = 0;
        new_data = true;
      }
    } else if (rc == START_MARKER) {
        recv_in_progress = true;
    }
  }
  return new_data;
}

void setup() {
  Serial.begin(9600);
  text = (char*)malloc(25);
  strcpy(text, "EMPTY");
  received_chars[0] = '\0';
}

void loop() {
  ReadSerial();
}

Thanks!

Are your "keys" pre-defined values? Or is this intended to allow absolutely anything to be entered as a "key"?

At present, they're defined so as to allow anything to be entered as a key.

Is that really what you want? Personally I usually define a struct to take the data and do string matching on the key to work out which entry in the struct to assign the value to. You also parse the value according to what the type is, so numbers are stored as integers, etc.

The way you use malloc and changing the pointer of dynamic created variable will cause memory leak. As for the problem, you are picking up the memory content left by the previous buffer.

Welcome to the I forgot to empty my buffer char club (I lost some days finding a simlar problem)
 strcpy(temp_chars, received_chars)  // strcpy empties temp_chars and adds the received_chars

but you have no (for me) visible routine to empty received_chars
Do this either by setting
received_chars[0] ='\0'; // set the pointer to first index

or
 received_chars ="0";

or
strcpy(received_chars,"0");

after you used the buffer content. By using
static byte ndx = 0;

you just set the pointer and then start to write, as a safequard you should first reset the end terminator and then start to write. This is probably the reason you see characters even if no key is pressed due to a still "full" charbuffer.To prevent heap corruption define your received_chars as a fixed arraybefore setup:
char received_chars[128] ={'\0'}; // 127 chars + terminator

if you use malloc you have to use free, but doing that with a lot of dynamic data causes heap fracturing -> crash in the end
EDIT
The program does now the following

ignores all char not enclosed by <>
check for text and displays everything after = and before;
ignores everything after ; if its not text= again
if its text= again ignores the first and only displays the second param

You do not need strtok here as it deletes chars I use a modified substring routne for char arrays.
Here is the code working as described above:
// command indicators
const char START_MARKER = '<';
const char END_MARKER = '>';

const uint8_t MAX_KEY_VALUE_PAIRS = 3;  // maximum number of key-value pairs in message
const uint8_t MAX_ELEMENT_CHARS = 25;  // the maximum number of characters (+1 for terminator) in a key or a value

// message format: <key1=value1;key2=value2;key3=value3>
const uint8_t MAX_MESSAGE_CHARS = (MAX_KEY_VALUE_PAIRS * (MAX_ELEMENT_CHARS + 1)) * 2 + (MAX_KEY_VALUE_PAIRS - 1) + 2;  // maximum message size

//char received_chars[MAX_MESSAGE_CHARS] = {'\0'};// <- EDIT#1
char received_chars[256] = {'\0'};
bool new_data = false;
char text[25] =  {'\0'};      // the value identified by the "text" keyword, i.e.: in <text=abc;time=814a>, text would be abc.

void ParseData(char *str) {
  // This picks off the ;-delimited key-value pairs and assigns them to a multi-dim array
  char * pch;
  int pairs_count = 0;
  char config[MAX_KEY_VALUE_PAIRS][2][MAX_ELEMENT_CHARS];

  pch = strtok(str, "=");

  while (pch != NULL)  {
    strcpy(config[pairs_count][0], pch);
    pch = strtok(NULL, ";");
    if (pch == NULL) break;

    strcpy(config[pairs_count][1], pch);
    pairs_count++;
    pch = strtok(NULL, "=");
    if (pch == NULL) break;
  }

  for (uint8_t i = 0; i < pairs_count; i++) {
    if (strcmp(config[i][0], "text") == 0) strcpy (text,config[i][1]);
  }
  Serial.println(text);
}

void ReadSerial() {
  // After calling ReceiveText to empty the buffer, if a complete command has been found,
  // parse that command.
  new_data = ReceiveText();
  if (new_data == true) {
    char temp_chars[MAX_MESSAGE_CHARS];  // temporary array for use when parsing
    strcpy(temp_chars, received_chars);
    received_chars[0] = '\0';  // <- EDIT#2
    ParseData(temp_chars);
  }
}

bool ReceiveText() {
  // This dumps the characters on the buffer so far received_chars, searching for an END_MARKER
  // along the way; if it finds one, it goes back to find a START_MARKER; if that is also found,
  // the string within is the ;-delimited set of key value pairs
  static boolean recv_in_progress = false;
  static byte ndx = 0;
  char rc;

  bool new_data = false;
  while (Serial.available() > 0 && new_data == false) {
    rc = Serial.read();

    if (recv_in_progress == true) {
      if (rc != END_MARKER) {
        received_chars[ndx] = rc;
        ndx++;
        if (ndx >= MAX_MESSAGE_CHARS) {
          ndx = MAX_MESSAGE_CHARS - 1;
        }
      } else {
        received_chars[ndx] = '\0'; // terminate the string
        recv_in_progress = false;
        ndx = 0;
        new_data = true;
      }
    } else if (rc == START_MARKER) {
      recv_in_progress = true;
    }
  }
  return new_data;
}

void setup() {
  Serial.begin(115200);
   strcpy (text, "EMPTY");
 //  text = (char*)malloc(25);
//  received_chars[0] = '\0';
}

void loop() {
  ReadSerial();
}

If you could describe what you really want in the end I'm sure we can help with some basic routines.

Thanks for the idea - I've made those changes, both to initialize in setup, and immediately after the strcopy, with the received_chars[0] = '\0'; suggestion. Alas, I still get the same bad behavior. But perhaps I misunderstood your suggestion.

Please edit your question with the updated code

Done - yes, that probably helps you see exactly what I did (wrong) :P

Thank you - following your code highlighted my errant ways. Specifically, once I found the keyword "text", I was using text = config[i][1];, whereas I should have been using strcopy(text, config[i][1];. Appreciate the help!

Please mark as solved/accepted - Thanks

The problem was that, in the variables I wanted to keep (i.e.: text in the code below), I was assigning the value of a pointer to the parsed string which is reused the next time a command is found, rather than copying the string.
Fixed code below - see comment Fig#1. There's also a second fix, although that wasn't causing the problem behavior.
// command indicators
char START_MARKER = '<';
char END_MARKER = '>';

const int MAX_KEY_VALUE_PAIRS = 3;  // maximum number of key-value pairs in message
const int MAX_ELEMENT_CHARS = 25;  // the maximum number of characters (+1 for terminator) in a key or a value

// message format: <key1=value1;key2=value2;key3=value3>
const int MAX_MESSAGE_CHARS = (MAX_KEY_VALUE_PAIRS * (MAX_ELEMENT_CHARS + 1)) * 2 + (MAX_KEY_VALUE_PAIRS - 1) + 2;  // maximum message size

char received_chars[MAX_MESSAGE_CHARS];
bool new_data = false;

char *text;  // the value identified by the "text" keyword, i.e.: in <text=abc;time=814a>, text would be abc.

void ParseData(char *str) {
  // This picks off the ;-delimited key-value pairs and assigns them to a multi-dim array
  char * pch;
  int pairs_count = 0;
  char config[MAX_KEY_VALUE_PAIRS][2][MAX_ELEMENT_CHARS];

  pch = strtok(str, "=");

  while (pch != NULL)
  {
    strcpy(config[pairs_count][0], pch);
    pch = strtok(NULL, ";");
    if (pch == NULL) break;

    strcpy(config[pairs_count][1], pch);
    pairs_count++;
    pch = strtok(NULL, "=");
    if (pch == NULL) break;
  }

  for(int i=0;i<pairs_count;i++) {
    if (strcmp(config[i][0], "text")==0) strcpy(text, config[i][1]);  // Fix#1
  }
  Serial.println(text);
}

void ReadSerial(){
  // After calling ReceiveText to empty the buffer, if a complete command has been found,
  // parse that command.
  new_data = ReceiveText();
  if (new_data == true) {
    char temp_chars[MAX_MESSAGE_CHARS];  // temporary array for use when parsing
    strcpy(temp_chars, received_chars);
    received_chars[0] = '\0';  // Fix #2 - wasn't causing this problem, but still was wrong
    ParseData(temp_chars);
  }
}

boolean ReceiveText() {
  // This dumps the characters on the buffer so far received_chars, searching for an END_MARKER
  // along the way; if it finds one, it goes back to find a START_MARKER; if that is also found,
  // the string within is the ;-delimited set of key value pairs
  static boolean recv_in_progress = false;
  static byte ndx = 0;
  char rc;

  boolean new_data = false;
  while (Serial.available() > 0 && new_data == false) {
    rc = Serial.read();

    if (recv_in_progress == true) {
      if (rc != END_MARKER) {
        received_chars[ndx] = rc;
        ndx++;
        if (ndx >= MAX_MESSAGE_CHARS) {
          ndx = MAX_MESSAGE_CHARS - 1;
        }
      } else {
        received_chars[ndx] = '\0'; // terminate the string
        recv_in_progress = false;
        ndx = 0;
        new_data = true;
      }
    } else if (rc == START_MARKER) {
        recv_in_progress = true;
    }
  }
  return new_data;
}

void setup() {
  Serial.begin(9600);
  text = (char*)malloc(25);
  strcpy(text, "EMPTY");
  received_chars[0] = '\0';
}

void loop() {
  ReadSerial();
}

Thanks to Codebreaker007 for the help.


text:
How to add a yield before else if?
So I am running my project on a NodeMCU, but I don't know how to let it add a yield in front of an else if. It will give me an error like this:

Arduino:1.8.12 (Windows 10), 開發板:"NodeMCU 1.0 (ESP-12E Module), 80 MHz, Flash, Legacy (new can return nullptr), All SSL ciphers (most compatible), 4MB (FS:2MB OTA:~1019KB), 2, v2 Lower Memory, Disabled, None, Sketch + WiFi Settings, 115200"
G:\資優班\科展\程式碼\Front_End\Main_Code_V5\Main_Server\Main_Server.ino: In function 'void loop()':
Main_Server:84:5: error: 'else' without a previous 'if'
exit status 1
  'else' without a previous 'if'
This report would have more information with
  "Show verbose output during compilation"
  option enabled in File -> Preferences.

Here's the code:
#include <SPI.h>
#include <ESP8266WiFi.h>

#define MAX_SRV_CLIENTS 2
#define led LED_BUILTIN

WiFiServer server(80);
WiFiClient serverClients[MAX_SRV_CLIENTS];
IPAddress ip(10, 241, 241, 27);
IPAddress mask(255, 255, 255, 0);
IPAddress gateway(10, 241, 241, 254);
char ssid[] = "AP";
char pass[] = "Science_Fair";

void setup() {
  Serial.begin(9600);
  WiFi.config(ip, gateway, mask);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    yield();
  }
  server.begin();
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
}

void loop() {
  uint8_t i;
  Serial.setTimeout(10);
  for (i = 0; i < MAX_SRV_CLIENTS; i++) {
    Serial.println("Pre 1");
    if (server.hasClient()) {
      Serial.println("Pre 2");
      if (!serverClients[i] || !serverClients[i].connected()) {
        Serial.println("Pre 3");
        if (serverClients[i]) {
          Serial.println("Pre 4");
          serverClients[i].stop();
          Serial.println("Pre 5");
        }
        Serial.println("Pre 6");
        serverClients[i] = server.available();
        Serial.println("Pre 7");
        serverClients[i].setTimeout(10);
        Serial.println("Pre 8");
        Serial.print("New client: ");
        Serial.println("Pre 9");
        Serial.println(i);
        Serial.println("Pre 10");
        break;
      }
    }
    yield();
  }
  for (i = 0; i < MAX_SRV_CLIENTS; i++) {
    String fromClient = serverClients[i].readStringUntil('e');
    Serial.println("P1");
    yield();
    if (fromClient == "LR") {
      Serial.println("LR");
      String reply = Serial.readStringUntil('e');
      Serial.println("P2");
      yield();
      if (reply == "Warn_B") {
        yield();
        Serial.println("Confirm");
        Serial.println("P3");
        for (i = 0; i < MAX_SRV_CLIENTS; i++) {
          serverClients[i].print("Warn_B");
          Serial.println("P4");
          yield();
        }
      }
    }
    yield(); // this is the yield I need to add
    else if (fromClient == "RR") {
      Serial.println("RR");
      Serial.println("P5");
      String reply = Serial.readStringUntil('e');
      Serial.println("P6");
      yield();
      if (reply == "Warn_A") {
        Serial.println("P7");
        Serial.println("Confirm");
      }
      for (i = 0; i < MAX_SRV_CLIENTS; i++) {
        serverClients[i].print("Warn_A");
        Serial.println("P8");
        yield();
      }
    }
    yield();
  }
}

I need the yield() there but I don't know how to let it still do the else if. Please help me guys, thanks!

Why do you  think you need a yield there?

@Majenko Uh cuz I am using my NodeMCU and I have a watchdog timer, I think there is the problem cuz it is always giving me a bunch of errors like feefeffe

Yes, but why there? Why between two pieces of code that are "either / or"? If the first ran then the second won't. If the second ran then the first won't have. There's no "between" in that scenario.

the yield() before the if is the yield() before the else

First of all do yourself a favour and listen to your IDE
This report would have more information with
 "Show verbose output during compilation"
option enabled in File -> Preferences.

and in an if else there is no in between so either let it run as a state machine especially inyour case A != B != C != other:
void subfunction(){
  if(A){
  // code to run
  return;
  }
 yield();
 if(B){
  // code to run
  return;
  }
 yield();
 if(C){
  // code to run
  return;
  }
 else{}  // to catch if not A or B or C
 yield();
}

or implement switch case (Pseudo code)
 switch(fromClient){
    case "LR":
      //code to run
      yield();
      break;
    case "RR":
      //code to run
      yield();
      break;
    default:
      //code to run
      yield();
      break;
  }

Id else chains are prone to errors as in your case its A != B != C != other

Thank you! But again I am at home, I'll test it tmr in my lab, thank you again!

why not yield() after the switch?

I just copied his"use case" but you are right he could even do it before the cases and in the case (depends on his WD timer