text:
How do I run 4 LEDs sequentially based off of a push button input?
I am trying to create a program that runs 4 LEDs sequentially while also being able to do other things with different inputs and outputs. Because of this, I am using the millis function and not the delay. I have the code working but not exactly how I want it. It runs through the LEDs and turns them off then runs through again like it is supposed too but there are two problems:

It will pass through the first if statement, then the first again then to the second, then it will go through the first, the second, then the third, etc. I want it to cascade through the if statements, keeping the LED from the previous steps on without repeating. It is causing the LEDs to flash super quick.
The code still runs even if the input is read as LOW as it is dependent on millis. I somehow need it to start from the beginning every time the button is pushed and reset when the button is not pressed.

below the code is a picture of the serial monitor showing the program running through every if statement and not staying in one and moving to the next. If needed, I can add a video showing what the LEDs do.
below is the code
//Code to build 4 sequentially run LEDs that reset everytime there is not input
int RTS_IN  = A0; //input button

//Output LEDs, assigning them to pins
int LED_5 = 5;
int LED_6 = 6;
int LED_7 = 7;
int LED_8 = 8;

//1 second for each time interval
unsigned long Time1 = 1000;
unsigned long Time2 = 2000;
unsigned long Time3 = 3000;
unsigned long Time4 = 4000;
unsigned long Time5 = 5000;

//variables for holding millis values
unsigned long currentMillis;
unsigned long newMillis = 0;

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

  pinMode(RTS_IN, INPUT);
  pinMode(LED_5, OUTPUT);
  pinMode(LED_6, OUTPUT);
  pinMode(LED_7, OUTPUT);
  pinMode(LED_8, OUTPUT);

}

void loop()
{
  currentMillis = millis();

  //using sequential method if the input button pressed and held
  if(digitalRead(RTS_IN) == HIGH)
  {
    sequential();
  }
  //keeping LEDs OFF if button has been released
  else
  digitalWrite(LED_5, LOW);
  digitalWrite(LED_6, LOW);
  digitalWrite(LED_7, LOW);
  digitalWrite(LED_8, LOW);
}

//method to run LEDs sequentially
void sequential()
{

  //if statement checking to see if a second has passed to allow the first led to turn on
  if(currentMillis - newMillis >= Time1)
  {
    Serial.println("5 is on");

    digitalWrite(LED_5, HIGH);
    delay(1);

    //if statement checking to see if 2 seconds has passed to allow the second led to turn on
    if(currentMillis - newMillis >= Time2)
    {
      Serial.println("6 is on");

      digitalWrite(LED_6, HIGH);
      delay(1);

      //if statement checking to see if 3 seconds has passed to allow the third led to turn on
      if(currentMillis - newMillis >= Time3)
      {
        Serial.println("7 is on");

        digitalWrite(LED_7, HIGH);
        delay(1);

        //if statement checking to see if 4 seconds has passed to allow the fourth led to turn on
        if(currentMillis - newMillis >= Time4)
        {
          Serial.println("8 is on");

          digitalWrite(LED_8, HIGH);
          delay(1);

          //if statement to turn off LEDs and wait a second before turning the first back on
          if(currentMillis - newMillis >= Time5)
          {
            Serial.println("All off");

            digitalWrite(LED_5, LOW);
            digitalWrite(LED_6, LOW);
            digitalWrite(LED_7, LOW);
            digitalWrite(LED_8, LOW);

            //this is in order to add a period of this process to each of the
            //interval times to keep up with millis without this, they would all stay on
            Time1 = Time1 + 5000;
            Time2 = Time2 + 5000;
            Time3 = Time3 + 5000;
            Time4 = Time4 + 5000;
            Time5 = Time5 + 5000;
            delay(1);

          }
        }
      }
    }
  }
}

updated code below with if else statements and the other programming combined

const int RTS_IN  = A0;
const int LTS_IN = A1;

//break signal
const int BS_IN  = A2;
const int BS_OUT = 11;

//reverse signal
const int RS_IN  = A3;
const int RS_OUT = 10;

const int NR_OF_LEDS = 4;
const int RIGHTLEDS[NR_OF_LEDS] = { 6, 7, 8, 9 };
const int LEFTLEDS[NR_OF_LEDS] = { 5, 4, 3, 2 };
const int interval = 100;

int nrOfRightLedsOn = 0;
int nrOfLeftLedsOn = 0;

unsigned long t = 0;

void StateRight();
void StateRightProcess();

void StateLeft();
void StateLeftProcess();

boolean oldSwitchStateRS = LOW;
boolean newSwitchStateRS = LOW;
boolean oldSwitchStateBS = LOW;
boolean newSwitchStateBS = LOW;

void setup()
{
  Serial.begin(9600);
  pinMode(RTS_IN, INPUT);
  pinMode(LTS_IN, INPUT);

  for (int led = 0; led < NR_OF_LEDS; led++)
  {
    pinMode(RIGHTLEDS[led], OUTPUT);
  }

  for (int led = 0; led < NR_OF_LEDS; led++)
  {
    pinMode(LEFTLEDS[led], OUTPUT);
  }

}

void loop()
{
  StateRight();
  StateLeft();

  newSwitchStateBS = digitalRead(BS_IN);
   if(newSwitchStateBS != oldSwitchStateBS)
  {
    if(newSwitchStateBS == HIGH)
    {
      digitalWrite(BS_OUT, HIGH);
    }
    else
    digitalWrite(BS_OUT, LOW);
    oldSwitchStateBS = newSwitchStateBS;
  }

 newSwitchStateRS = digitalRead(RS_IN);
  if(newSwitchStateRS != oldSwitchStateRS)
  {
    if(newSwitchStateRS == HIGH)
    {
      digitalWrite(RS_OUT, HIGH);
    }
    else
    digitalWrite(RS_OUT, LOW);
    oldSwitchStateRS = newSwitchStateRS;
  }

}

void StateRight()

{
  if(digitalRead(RTS_IN) == LOW)
  {
    SwitchRightLedsOff();
    nrOfRightLedsOn = 0;
    t = millis() + interval;
  }
  else if (nrOfRightLedsOn < NR_OF_LEDS)
  {
    StateRightProcess();
  }
  else
  {
    if(millis() >= t + interval)
    {
      t = millis();
      SwitchRightLedsOff();
      nrOfRightLedsOn = 0;
    }
  }
}

void StateRightProcess()
{
  if(millis() >= t + interval)
  {
    t = millis();
    digitalWrite(RIGHTLEDS[nrOfRightLedsOn], HIGH);
    nrOfRightLedsOn++;
  }
}

void SwitchRightLedsOff()
{
  for (int led = 0; led < NR_OF_LEDS; led++)
  {
    digitalWrite(RIGHTLEDS[led], LOW);
  }
}

void StateLeft()
{
  if(digitalRead(LTS_IN) == LOW)
  {
    SwitchLeftLedsOff();
    nrOfLeftLedsOn = 0;
    t = millis() + interval;
  }
  else if (nrOfLeftLedsOn < NR_OF_LEDS)
  {
    StateLeftProcess();
  }
  else
  {
    if (millis() >= t + interval)
    {
      t = millis();
      SwitchLeftLedsOff;
      nrOfLeftLedsOn = 0;
    }
  }
}

void StateLeftProcess()
{
  if (millis() >= t + interval)
  {
    t = millis();
    digitalWrite(LEFTLEDS[nrOfLeftLedsOn], HIGH);
    nrOfLeftLedsOn++;
  }
}

void SwitchLeftLedsOff()
{
  for (int led = 0; led < NR_OF_LEDS; led++)
  {
    digitalWrite(LEFTLEDS[led], LOW);
  }
}

Thanks for the wonderful question. here is the Arduino project link which you can use for further discussion. I am sure, you will find it very easy to share your project in this way https://wokwi.com/arduino/projects/321913849735283283

To be honest, I don't understand exactly the problems, but I try to give some guideline and hope you can use the idea to fix your problems.
What you need is a so called 'state machine'.
I think (according to your problem) that you have 6 states:
0 Idle (no sequence)
1 One LED on
2 Two LEDs on
3 Three LEDs on
4 Four LEDs on
5 No LEDs on

For this you can best use an enum type and global variable with similar values:
enum EState
{
    Idle,
    OneLedOn,
    TwoLedsOn,
    ThreeLedsOn,
    FourLedsOn,
    NoLedsOn
}

EState _state;

You need a function to check the new state, depending on the current state. In words something like:
current     When                          Action           New
state                                                      state
--------    ----------------------------  ---------------- -----
Idle        digitalRead(RTS_IN) == HIGH   Start counter    OneLedOn
                                          Switch on LED 0
OneLedOn    digitalRead(RTS_IN) == LOW    Switch LEDs off  Idle
            5 seconds have passed         Switch on LED 1
                                          Start counter    TwoLedsOn
TwoLedsOn   digitalRead(RTS_IN) == LOW    Switch LEDs off  Idle
            5 seconds have passed         Switch on LED 2
                                          Start counter    ThreeLedsOn
ThreeLedsOn digitalRead(RTS_IN) == LOW    Switch LEDs off  Idle
            5 seconds have passed         Switch on LED 3
                                          Start counter    ThreeLedsOn
FourLedsOn  digitalRead(RTS_IN) == LOW    Switch LEDs off  Idle
            5 seconds have passed         Switch LEDs off
                                          Start counter    NoLedsOn
NoLedsOn    digitalRead(RTS_IN) == LOW    Switch LEDs off  Idle
            5 seconds have passed         Switch on LED 0
                                          Start counter    OneLedn

(if you would draw one circle for each state and arrows between them, a so called UML State Diagram, you will see a much clearer way to depict the states and flows).
I don't have a compiler so I do it out of my head.
void Process()
{
    switch (_state)
    {
    case EState::Idle:
        if ((digitalRead(RTS_IN) == HIGH)
        {
            _time = millis();
            digitalWrite(LED_5, HIGH);
            _state = EState::OneLedOn;
        }
        break;
    case EState::OneLedOn:
        if ((digitalRead(RTS_IN) == LOW)
        {
            SwitchLedsOff();
            _state = Idle;
        }
        else if (millis() > time + 5000)
        {
            _time = millis();
            digitalWrite(LED_6, HIGH);
            _state = EState::TwoLedsOn;
        }
        break;
    case EState::TwoLedsOn:
       ...
}

The function SwitchLEDsoff sets all LEDs to low, and you only need one unsigned long _time global variable which you update when a new state starts and check in most states.
Note that high likely you can optimize this (like making each state its own function and removing almost duplicated code), but the main goal is to let you understand how to use a state machine and to use it in this sketch and future sketches.
Update
The following sketch is the same as yours but:

Optimized for reducing code duplication (ProcessState)
Introduced constants
Introduced array for LEDs to iterate over
Removed the state, instead used _nrOfLedsOn
Removed idle state, handled separately now
Prefixed global variables with an underscore (personal preference)
Better names for variables/functions
Used prototypes to put functions in logical order (high level to low level)

Code:
const int RTS_IN  = A0;
const int NR_OF_LEDS = 4;
const int LEDS[NR_OF_LEDS] = { 5, 6, 7, 8 };
const int DURATION = 300;

int _nrOfLedsOn = 0;
unsigned long _time = 0;

void ProcessState();
void ProcessLedsState();
void SwitchLedsOff();

void setup()
{
    Serial.begin(9600);
    pinMode(RTS_IN, INPUT);
    for (int led = 0; led < NR_OF_LEDS; led++)
    {
        pinMode(LEDS[led], OUTPUT);
    }
}

void loop()
{
    ProcessState();
}

void ProcessState()
{
    if (digitalRead(RTS_IN) == LOW)
    {
        SwitchLedsOff();
        _nrOfLedsOn = 0;
        _time = millis() + DURATION + 1;
    }
    else if (_nrOfLedsOn < NR_OF_LEDS)
    {
        ProcessLedsState();
    }
    else
    {
        if (millis() > _time + DURATION)
        {
            _time = millis();
            SwitchLedsOff();
            _nrOfLedsOn = 0;
        }
    }
}

void ProcessLedsState()
{
    if (millis() > _time + DURATION)
    {
        _time = millis();
        digitalWrite(LEDS[_nrOfLedsOn], HIGH);
        _nrOfLedsOn++;
    }
}

void SwitchLedsOff()
{
    for (int led = 0; led < NR_OF_LEDS; led++)
    {
        digitalWrite(LEDS[led], LOW);
    }
}

I think you nailed it! This is a lot clearer way of coding it I believe. I will try to implement this into my code and get back to you. I appreciate the quick response.

You're welcome.

I have implemented the new code with your help and It works great except for one thing, it doesnt enter state 5 and turn the LEDs LOW with RTS_IN HIGH. I have updated my original post

Change SwitchLedsOff; to SwitchLedsOff(); in case 5.

Check the update, I optimized the sketch.

Awesome, I will check that code out and try to implement the parts that I can understand. You have been a great help thank you.

what is the point of have those case statements if the code just falls through. I also do not understand why you add 1 to t in the first if statement in void ProcessState(). Can you explain please?

You are right about the switch statement, I converted it/combined it with the previous if statement. I also fixed a 'bug' where I had two methods named equal. And the reason why to add +1: If you see the function ProcessLedsState, you see if (millis() > _time + DURATION) ... when it's equal it wouldn't trigger immediately, so I added 1. Maybe instead using >= would be better, as you probably want to change LEDs every 300 ms, not when it's (necessarily) more than 300 ms.

so do i only need 2 case statements then?

Let us continue this discussion in chat.


text:
ESP32 Access Point and HTTP Web Server, how to send multiple parameters?
I made this minimal example in order to figure out how to get requests (or whatever they are called) to display in the serial monitor. However, none of the query parameters (in the URL) can be seen in the serial monitor at 115200 baud.
The files are below and here: https://github.com/adamelli/MinimalExamples/tree/main/22-1-25_query_parameters_submitButton
File structure
sketch (folder)

sketch.ino
data (folder)

index.html
selection.html

sketch.ino
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <painlessMesh.h>

const char* ssid = "Wireless Controller";
const char* password = "12345678";

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

void sendMessage() {
  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));
}

AsyncWebServer server(80);

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}
IPAddress IP(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

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

  // Initialize SPIFFS
  if (!SPIFFS.begin(true))
  {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  WiFi.softAP(ssid, password);
  delay(500);
  WiFi.softAPConfig(IP, gateway, subnet);
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

// Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/index.html", String(), false );
  });

  // Index.HTML NAVIGATION BUTTIONS ************************************************

  server.on("/index.html", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/index.html", String(), false);
  });

  server.on("/selection.html", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/selection.html", String(), false );
  });

  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
  {

    int paramsNr = request->params();
    Serial.println(paramsNr);

    for (int i = 0; i < paramsNr; i++)
    {
      AsyncWebParameter* p = request->getParam(i);
      Serial.print("Param name: ");
      Serial.println(p->name());

      Serial.print("Param value: ");
      Serial.println(p->value());

      Serial.println("------");
    }

    request->send(200, "text/plain", "message received");
  });

  server.begin();
}

void loop() {}

index.html
<!DOCTYPE html>

Main Menu

<button class="button">Selection</button>

<button class="button">Oblivion</button>

selection.html
<!DOCTYPE html>

<form action="/" method="get">

    Shape Size:

    <select name="size" id="size" style="font-size: 22px;">
      <option value="1"> 1   </option>
      <option value="2"> 1/2 </option>
        </select>

Speed:

    <select name="speed" id="speed" style="font-size: 24px">
      <option value="1">          Slowest </option>
      <option value="2" selected> Regular </option>
    </select>

<button class="submit" name="circle" value="3">Circle</button>

<button class="submit" name="square" value="4">Square</button>

</form>

The data files must be uploaded via "Tools" → "ESP32 Sketch Data Upload".
How is the data (size and speed) viewable in the serial monitor? What needs to change?

Thank you for making a minimal example! So many people won't bother to do it, and it's a huge help in debugging.

You have two handlers for "/":
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/index.html", String(), false );
  });

and
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
  {

    int paramsNr = request->params();
    Serial.println(paramsNr);

    for (int i = 0; i < paramsNr; i++)
    {
...

Only one will be called when you load the top level page. You'll need to combine them to both serve index.html and process the parameters being passed to it.

Thanks, but I still do not understand how to change the request body/message. I just want it to return to the main menu index without changing the content of that main index page. In the ino sketch request->send(200, "text/plain", "message received") changes the whole main index page. Yet when I take that request part out, the program does not compile.

@Adam you asked why the parameters are not printed. Well, because the handler in which you print them is never called due to the double definition.

Yes, but the first definition makes the main menu viewable. You mention combining the two. I tried combining them though trial and error edits, but nothing has worked. One of the two pages always either becomes "Not Found" or clears out to be left with "message received." I suppose I can ask another question, but it's going to be pretty much the same.

I think what @romkey say "combine" means that you need to something about the two duplicate routes. Not literally combine them. One easy way to fix the problem is to rename your route that handling the params to server.on("/submit", HTTP_GET, callback_func), and change your selection.html form submission to <form action="/submit" method="get">.

Changing selection.html form submission to <form action="/submit" method="get"> makes the selection.html page "Not Found" (and the params handle was changed)

@hcheung is right. You need to rethink how you are putting together your web page and where you're handling the parameters. You can't have two handlers for the same path ("/"). You can however change what you return depending on the presence or values of parameters. If you change the path to "/submit" then you'll need a handler for "/submit".

@romkey I changed the params handle to that (as I mentioned) and it results in "Not Found" on the selection.html page.

Did you also change the route that handling the params to server.on("/submit", HTTP_GET, [](AsyncWebServerRequest * request)?

@hcheung Yes, I did. Still, it does not work for me. Did you get it to work?

source: Stack Exchange

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

sort: votes


text:
Convert from raw data to float from DDSU666-H

Hi professers, i am trying to read the data from DDSU666-H ( Smart metter) CHINT using modbus RTU, i only get the raw data but i don't know how to convert it to float , in the code below is about Voltage , real data is 233,4V but in the serial is like this, can some one help me to convert this one to float 233,4V, thank you so much!

 Here is my code, i get it from modbusmaster library.
/*

  RS485_HalfDuplex.pde - example using ModbusMaster library to communicate
  with EPSolar LS2024B controller using a half-duplex RS485 transceiver.

  This example is tested against an EPSolar LS2024B solar charge controller.
  See here for protocol specs:
  http://www.solar-elektro.cz/data/dokumenty/1733_modbus_protocol.pdf

  Library:: ModbusMaster
  Author:: Marius Kintel <marius at kintel dot net>

  Copyright:: 2009-2016 Doc Walker

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

#include <ModbusMaster.h>

/*!
  We're using a MAX485-compatible RS485 Transceiver.
  Rx/Tx is hooked up to the hardware serial port at 'Serial'.
  The Data Enable and Receiver Enable pins are hooked up as follows:
*/
#define MAX485_DE      50
#define MAX485_RE_NEG  52

// instantiate ModbusMaster object
ModbusMaster node;

void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, 1);
  digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

void setup()
{
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);

  // Modbus communication runs at 115200 baud
  Serial1.begin(9600);
  Serial.begin(9600);

  // Modbus slave ID 1
  node.begin(12, Serial1);
  // Callbacks allow us to configure the RS485 transceiver correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}
void loop()
{
  uint8_t i, result;
  uint16_t data[2];
  union
  {
    uint32_t j;
    float f;
  } u;
  // Read 16 registers starting at 0x3100)
  Serial.println("-----------------------");
  result = node.readHoldingRegisters(0x2000, 2);
  if (result == node.ku8MBSuccess)
  {
    for (i = 0; i < 2; i++)
    {
      data[i] = node.getResponseBuffer(i);
    }
    Serial.println(data[0]);
    Serial.println(data[1]);
    u.j = ((unsigned long)data[1] << 16 | data[0]);
    Serial.println(u.f);
  }

not a question about Arduino ... it is a general programming question at best

please remove the picture of text and add the actusl text ... text in a picture cannot be copied for analysis

you mean " hi professer" text ?

no, the printout of the readings ... it should be text, not a picture

Could you share your wiring between rs485 module and ddsu please ?

Seems the data sheet does not specify the endianness. Or maybe it does,
but you are not showing it. From the numbers you get, it appears that
the floats come in big-endian order, whereas your code assumes
little-endian.
Change the assignment of u.j as follows:
u.j = ((unsigned long)data[0] << 16 | data[1]);

oh,, i actually read voltage register successfully, but with the frequentcy ( 0x200E), it doesn't work , haha

Hello expert, why i can't read the frequency and power active register while i can read voltage and current ?

@HẢIHỒ: No idea. Check the documentation of your device.

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


text:
Why do I read my own transferred data during my RS485 serial comms?
I am writing a RS485 serial communication firmware for the ESP32 (the minimal code is at the end of the question you can paste it as an Arduino INO or in platformIO main.cpp file).
It is quite simple: it asks for commands on a regular basis, say command ID 0x92, in the form of 0xA5 0x40 0x92 0x08 etc.on 13 bytes and the master is expected to send the response back in the form 0xA5 0x01 0x92 0x08 etc.as a 13-byte packet as well. So far so good.
As you certainly noticed A5 is a constant header, 0x40 is used to ask the master (whilst 0x01 marks an incoming message) and 0x92 is the message ID we are interested in.
The logs are as follows, and as you can see, my reading portion of code received my own sent message followed by the response.
I am trying to understand why: a design flow in my code? flush() does not actually flush? or whatever I should do to fix it?
18:38:14.936 -> Starting RS485 serial comm @ 9600 SWSERIAL_8N1
18:38:14.936 -> #1: Asking for command 00
18:38:14.936 -> Writing command:
18:38:14.936 -> =====> a5 40 00 08 00 00 00 00 00 00 00 00 ed …
18:38:16.946 -> Asking for command 90
18:38:16.946 -> Writing command:
18:38:16.946 -> =====> a5 40 90 08 00 00 00 00 00 00 00 00 7d …
18:38:18.963 -> Asking for command 91
18:38:18.963 -> Writing command:
18:38:18.963 -> =====> a5 40 91 08 00 00 00 00 00 00 00 00 7e …
18:38:20.986 -> Asking for command 92
18:38:20.986 -> Writing command:
18:38:20.986 -> =====> a5 40 92 08 00 00 00 00 00 00 00 00 7f …
18:38:22.977 -> Received some bytes as follows:
18:38:23.011 -> <===== a5 40 92 08 00 00 00 00 00 00 00 00 7f a5 01 92 08 00 01 ff 01 fa 01 03 d6 15
18:38:23.011 -> Let ask once more!

And the code I wrote is as follows:
/// RS 485 test lab for ESP32
/// Minimal firmware for testing the SBM IoT RS485
/// Created by Sdl on Friday January 7th 2021 10:43am @ Will's N Hoagland Blvd in Kissimme, FL, USA

#include "SoftwareSerial.h"

#define RXD GPIO_NUM_19
#define TXD GPIO_NUM_18

#define PACKET_HEADER_LENGTH 4
#define PACKET_LENGTH 13

// == Software serial bound to TX RX 18/19
SoftwareSerial s(RXD, TXD, false);

/**
 * Computes the check sum
 * @param {[uint8]} data The data buffer
 * @param {Number} length The number of bytes
 * @returns The ine-byte checksum
 */
uint8_t checksum(uint8_t *buffer) {
  const int length = PACKET_LENGTH - 1;

  uint8_t checksum = 0;
  for (int i=0; i<length; i++) {
    checksum += buffer[i];
  }
  return checksum&0xff;
}

// == Build the remote master
#define MASTER 0x40

int messageCount = 0;

/// Sneds a message whose ID is the given [id]
void sendMessage(uint8_t id) {
  Serial.printf("Asking for command %02x", id); Serial.println();

  uint8_t command[PACKET_LENGTH] = {
    //Head  Master, Id: Soc   Length    Data 1, 2,    3     4     5     6     7     8     cs
    0xA5, MASTER, id,     8,        0x00,   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };

  send(command);
}

void send(uint8_t *buffer) {
  const int length = PACKET_LENGTH;

  // == Compute command checksum
  buffer[PACKET_LENGTH-1] = checksum(buffer);

  //digitalWrite(TXD, HIGH); //enable sending

  // == Write command
  Serial.println("Writing command: ");
  Serial.print("=====> ");

  for(int i=0; i<length; i++) {
    Serial.printf("%02x ", buffer[i]);
  }
  Serial.println("…");

  //size_t count =
  s.write(buffer, length);

  // == Disable transmitter
  s.flush();
  s.drain();

  //digitalWrite(TXD, LOW); //back to receiving
  //log("sent %d bytes", count);

  delay(2000);
}

uint8_t commands[] = {
  0x00,
  0x90,
  0x91,
  0x92,
  0x93,
  0x94,
  0x95,
  0x96,
  0x97,
  0x98,
  0xD8,
};
int commandsCounter = 0;

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

  // == Start comms
  Serial.println("Starting RS485 serial comm @ 9600 SWSERIAL_8N1");
  s.begin(9600, SWSERIAL_8N1, RXD, TXD, false, 256);

  Serial.printf("#%d: ", ++messageCount);

  for (int i=0; i<4; i++) {
    sendMessage(commands[i]);
    commandsCounter++;
  }
}

void loop() {

    // == Now wait for reading

    if (s.available()) {
      Serial.println("Received some bytes as follows:");
      Serial.print("<===== ");

      int i=0;
      int messageId = 0;
      while(s.available()) {
        uint8_t b = s.read();
        Serial.printf("%02x ",b);
      }

      Serial.println();

      // == Ask again
      Serial.println("Let ask once more!");
    }
    else {
      Serial.println("No bytes to read: ask for the SoC");
    }

    // == Wait for 5 secs
    delay(5000);

    // == Ask BMS for message
    Serial.printf("#%d: ", ++messageCount);
    sendMessage(commands[commandsCounter++]);

    // == Loops thru the commands vector
    if (commandsCounter>=sizeof(commands)) commandsCounter = 0;

}

Not sure this is the case here, but I have seen a number of RS232 level shifters that cause this behavior. Try disconnecting everything from the TX/RX pins and test that you don't get echo in that case.

@PMF Oh really? That counts for one direction to search! Thanks!

How did you wire the “transmit enable” and the “receiver enable” pins of your transceiver?

If you keep your receiver enabled while sending, of course you will receive your sent message. The RS485 serial communication is a bus, there are no separated lines for the different directions.

Is it 2- or 4-wire RS485 (half/full-duplex)? Which transceiver do you use?


text:
Uploading image to Google Drive with Arduino/ESP8266
I have a toucscreen tft connected to an ESP8266 the aim for which is to take a screeenshot (.bmp format) and upload to Google Drive. I have been following this tutorial.
Where I am stuck in how to proceed is the actual upload part. I have used the code in the tutorial up to line 264, and it is thereafter I don't know how to solve for. This reference project uses a function in a special library for the camera to parse it into packets and use client.write() to upload the packets. Relevant code here:
int i;
int packet_num = cameraPacketNum();
char packet[PIC_PKT_LEN] = {0};

for(i = 0; i < packet_num; i++)
{
    long packet_len = cameraGetPacket(i, packet);
    client.write((const uint8_t *)&packet[4], packet_len - 6);
    total += packet_len - 6;
}

cameraGetPacket(i, packet);
client.print(end_boundary);

I looked at the code for the function but can't figure out what it's doing and how to replicate it. This is it here:
long cameraGetPacket(unsigned int i, char* buf) {
    char cmd[] = { 0xaa, 0x0e | camera_address, 0x00, 0x00, 0x00, 0x00 };

    Serial.setTimeout(100);

    if(i < camera_packet_num) {
        cmd[4] = i & 0xff;
        cmd[5] = (i >> 8) & 0xff;

        cameraClearRxBuf();
        cameraSendCmd(cmd, 6);

        int pkt_len;

        if(i < (camera_packet_num - 1))
            pkt_len = PIC_PKT_LEN ;
        else
            pkt_len = camera_last_packet_len;

        uint16_t cnt = Serial.readBytes((char *)buf, pkt_len);

        return cnt;
    } else {
        cmd[4] = 0xf0;
        cmd[5] = 0xf0;
        cameraSendCmd(cmd, 6);
    }

    return "";
}

The Google Drive API reference states: "Add the chunk's data to the request body. Create chunks in multiples of 256 KB (256 x 1024 bytes) in size, except for the final chunk that completes the upload. Keep the chunk size as large as possible so that the upload is efficient."
How can I take an image saved to the SD on the tft and cut it into the appropriate sized chunks and use client.write() to upload it to Google Drive? This example (which received no responses) seems to have divided the image file into 1,000's to upload but I don't know if that is correct or efficient.
int Index;
for (Index = 0; Index < imageFile.length(); Index = Index+1000) {
  client.print(imageFile.substring(Index, Index+1000));
}

Another thing I am unsure about is whether I need to have the image file itself converted into Base64 or URLencoded. I have seen examples for the ESP32 CAM which do that, but I wonder if that is just the way that camera encodes images which then need to converted. The first example cited above doesn't have conversion code as it isn't an ESP32 CAM, but maybe it's happening in the background. The Google API doesn't make mention of it.
Any help would be greatly appreciated. Or any examples you can point me to that do this would be helpful too.

my StreamLib has ChunkedPrint. the library is in Library Manager. see the example

Thanks for pointing me to that. how might I might I adapt that for an image file? I've seen a few examples of chunking and uploading text, but an image file is something altogether different.

It's really not. It's a file.

what would be more helpful is offering how i can implement base64 with an image file since the examples only show a text string.


text:
How to determine when a sensor's output signal changes significantly?
Starting with an analog signal from any sensor, how do I automatically determine if there is a real signal change or a reset? Below is the sample code that better explains my goal:
value = sensorRead();

if (millis() > t + 1000) {
  value_old = value;
  t         = millis();
}
float d = value - value_old;
if (d < -3) {
  print("signal change")
  myfunction(); //ex. bink led
}

So if value(current) = 0.5 and value_old = 100 there has been a real change in signal, even if, because of noise, the value is not exactly 0.
It's very raw code, and I'd like to use a more professional approach that can detect both increments and decrements. Ideally, a suitable library, or alternatively a more efficient algorithm, would be ideal.

https://www.best-microcontroller-projects.com/arduino-absolute-value.html

you could average the reading over a period of time

if (millis() > t + 1000) { will run into problems about 49 days after arduino reset ... read this https://www.norwegiancreations.com/2018/10/arduino-tutorial-avoiding-the-overflow-issue-when-using-millis-and-micros/

The problem is not the millis(). The values are already filtered by a moving average, I want to distinguish the increments.

What do you know about the process's insignificant noise?  Do you care about drift?  E.g. would +0.1 per cycle be noteworthy?

There is no simple and universal way of deciding what is to be
considered a “significant” change. My recommendation would be to create
an algorithm by playing with the data on your computer:

Upload a sketch to your Arduino that simply reads the sensor and
transmits the readings to your computer via Serial.

Capture a long run of such readings in a file.

Graph the readings and look carefully at the graphs: what would you
consider a significant change? What criteria could you use to decide
that a change is significant? Devise an algorithm to take this
decision.

Implement and test the algorithm on your computer, using the recorded
data.

Port the code to the Arduino.

Below are two examples that maybe could give you some ideas. First comes
the simplest I can think of: it says the change is significant if the
current value is far enough from a previously recorded value. That
recorded value is only updated after a significant change has been
detected.
bool changed_significantly(int value) {
    const int change_threshold = 4;  // tune to taste
    static int old_value;
    bool changed = abs(value - old_value) >= change_threshold;
    if (changed)
        old_value = value;
    return changed;
}

It would be used like this:
void loop() {
    int value = sensorRead();
    if (changed_significantly(value))
        Serial.println("Signal changed.");
}

Note that, with this algorithm, a very slow drift would periodically
trigger the detection of significant changes. If this is not what you
want, you may prefer to only detect changes that happen fast enough.
This can be detected by the use of a high-pass filter. The function
below implements a simple low-pass filter (exponentially weighted moving
average) and compares the current input to the previous output. The
difference is equivalent to a high-pass filter. If that difference is
large enough, a significant change is detected, then the filter is reset
in order to prevent it from being repeatedly triggered by a drift:
bool changed_significantly(int value) {
    const float change_threshold = 4;   // tune to taste
    const float filter_constant = 0.1;  // this one also
    static float filtered_value;
    float delta = value - filtered_value;
    bool changed = abs(delta) >= change_threshold;
    if (changed)
        filtered_value = value;
    else
        filtered_value += filter_constant * delta;  // low-pass filter
    return changed;
}

Edit: some details about the filter.
This high-pass filter alone could be simplified as this:
float filter(float x)
{
    static float y;
    float delta = x - y;
    y += filter_constant * delta;
    return delta;
}

Note that, if this function returned y, we would have a conventional
first-order low pass filter (exponentially weighted moving average).
Since it returns instead the difference between the input and the
previous low-pass-filtered value, it behaves as a high-pass filter. Its
transfer function is
H = (z − 1) / (z + k − 1)
where k is the filter constant. This constant is related to the cut-off
frequency as
fc ≈ k fs / (2π)
where fs is the sampling frequency. Note that, for
frequencies significantly smaller than the cut-off, the filter behaves
like a scaled derivative:
H x ≈ 1/(k fs) dx/dt

We don't deserve you Edgar!

Why would small drift over time trigger the first code? Is it because it accumulates over a long period of time? Basically, is it a math thing, or a programming issue?

@ZhelyazkoGrudov: It's the algorithm. The recorded value is only updated after a significant change has been detected. If there is a slow drift,  it will accumulate change until that detection is triggered.

Thank you so much, I tried your last function, and it works as desired, simple and effective!!!! I don't really understand the filter_constant function, how can I estimate the ideal value based on usage?

@boromyr: See expanded answer.


text:
Wind speed measuring using Hall sensor

Hi!
I require your help regarding a problem I’m encountering.
I am trying to measure wind speed using Hall sensor, Neodymium magnet & below mentioned code. But I only get “0” value for both RPM & KPH values. Can you help me to solve this?
volatile byte revolutions;

unsigned int rpmilli;
float speed;

unsigned long timeold=0 ;

void setup()
{
    Serial.begin(9600);
    attachInterrupt(digitalPinToInterrupt(2), rpm_fun, RISING);

    revolutions = 0;
    rpmilli = 0;
    timeold = 0;
}

void loop()
{
    if (revolutions >= 1) {
         //Update RPM every 20 counts, increase this for better RPM resolution,
         //decrease for faster update

         // calculate the revolutions per milli(second)
         rpmilli = revolutions/(millis()-timeold);

         timeold = millis();
         revolutions = 0;
         // WHEELCIRC = 2 * PI * radius (in meters)
         // speed = rpmilli * WHEELCIRC * “milliseconds per hour” / “meters per kilometer”

         // simplify the equation to reduce the number of floating point operations
         // speed = rpmilli * WHEELCIRC * 3600000 / 1000
         // speed = rpmilli * WHEELCIRC * 3600

         speed = rpmilli 1.288053600;

         Serial.print(“RPM:”);
         Serial.print(rpmilli * 60000 ,DEC);
         Serial.print(" Speed:");
         Serial.print(speed,DEC);
         Serial.println(" kph");
    }
}

void rpm_fun()
{
    revolutions++;
}

rpmilli = revolutions/(millis()-timeold);

All variables in this line are of type int, so this is an integer division. When the time delta in ms is larger than the number of revolutions it counted, this always returns 0. You need to change this to:
rpmilli = ((float)revolutions)/(millis()-timeold);

and change rpmilli to float.

Thank you so much for the help


text:
DC Motor not running with the L298N (Green) card
I have a DC motor connected to a L298N (Green) controller. The controller is receiving  electricity but the motors aren't. This is how we wired everything

Our code:
#include <SoftwareSerial.h>

int IN1 = 13;
int IN2 = 12;

int IN3 = 8;
int IN4 = 9;

void setup(){
  Serial.begin(9600);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

}

void loop(){
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  delay(2000);
}

The DC motor is not responding at all
Edit: Why is the motor not receiving electricity? How can we connect the card to the Arduino UNO correctly and get the motors running?

How exactly are you powering the Arduino? Over USB? Or over the 5V pin of the L298N? Has your L298N board a 5V voltage regulator? If you are trying to power the Arduino from the 5V pin of the L298N, you should use the 5V pin of the Arduino instead of the Vin pin (since that is connected to the linear voltage regulator)

And are you really using a single 3.7V battery to power it all?

@chrisl The arduino is powered by USB and L298N is connected to a 9V battery via VCC.

Then please remove the connection to Arduino Vin. It is not needed (since you power over USB), neither does it work (on Vin you need about 7V to get it working reliably). 2. Are you using one of these standard 9V block batteries? If yes, then this is a problem. They are not build for providing enough current (like for motors). They are made for low current applications (like smoke alarms).

Please also provide a link to the exact L298N board, that you have.

This is the board we use: https://www.robotistan.com/l298-cift-motor-surucu-karti-dual-motor-driver-yesil-pcb. Also yes, we are using those standart 9V block batteries

@chrisl Also what type of battery is good for DC motors?

start at your motor specs.  if the battery matches the specs, attach to battery in forward, then reverse.  once that works, connect to driver.  instead of using arduino output pins, manually connect and disconnect to/from arduino ground and 5V.  if that works, then you need to figure out what's up with your arduino output ports using a multimeter.

First: The connection between the 5V pin of the L298N and Arduino Vin is not correct here. The L298N 5V pin is an output. You could use it to power the Arduino. But then you would have to connect it to the 5V pin of the Arduino. Vin is connected to the linear voltage regulator. You need about 7V here to get the Arduino running reliably, because the regulator needs some headroom for regulating it down to 5V and the battery deplets over time a bit. Since you are powering the Arduino over USB you can remove this connection.
Second: The standard 9V block batteries, that you use, are not meant for providing the power for something like a motor. They are made for low power applications (like smoke detectors). So you will need a different battery type. Which exactly is dependent on further factors. You could start with putting AA batteries in series (enough to get to the voltage, that you need for your motors). Or you can buy a LiIon or LiPo battery (including the corresponding charging board). I'm not enough of a battery expert myself to go more detailed with the recommendations on direct batteries.
If you want it easy you might want to use a standard USB power bank. These give you 5V and (depending on the product) about 1 or 2A of current. Using a standard power bank has the advantage, that you get well regulated voltage, relatively high current and it already has the correct charging electronics.
With a USB-C power bank a corresponding PD board (Power Delivery) you can even get up to 12V from the power bank. Haven't tried this myself yet. Have a look at this video from GreatScott on Youtube. Looking at a standard online marketplace (we all know which one) and searching for "USB-C PD board" gave some promising results.


text:
ESP32 Access Point using ESPAsyncWebServer, how to send multiple parameters between submenu and main (index) menu while still retaining page layout?
I am trying to figure out how to get requests (or whatever they are called) to display in the serial monitor, yet not change the HTML page bodies.
The user selects their choices in the submenu (selection). Once clicking the submit button there, they return to the original main index menu and simultaneously the query parameters are sent to the ESP32 of the user's selections.
Based off another very similar question I asked, it works so that the query parameters (in the URL) can be seen in the serial monitor. Although, then the main menu is cleared out and left with "message sent".
Alternatively, the main menu can remain the same, but the query parameters are not sent. So one works but not the other, and vise versa.
The files are below and here: https://github.com/adamelli/MinimalExamples/tree/main/22-1-25_query_parameters_submitButton
File structure
sketch (folder)

sketch.ino
data (folder)

index.html
selection.html

sketch.ino
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <painlessMesh.h>

const char* ssid = "Wireless Controller";
const char* password = "12345678";

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

void sendMessage() {
  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));
}

AsyncWebServer server(80);

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}
IPAddress IP(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

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

  // Initialize SPIFFS
  if (!SPIFFS.begin(true))
  {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  WiFi.softAP(ssid, password);
  delay(500);
  WiFi.softAPConfig(IP, gateway, subnet);
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  server.on("/selection.html", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/selection.html", String(), false );
  });

// Main menu index page works
//  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
//    request->send(SPIFFS, "/index.html", String(), false );
//  });

// Query parameters works
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
  {

    int paramsNr = request->params();
    Serial.println(paramsNr);

    for (int i = 0; i < paramsNr; i++)
    {
      AsyncWebParameter* p = request->getParam(i);
      Serial.print("Param name: ");
      Serial.println(p->name());

      Serial.print("Param value: ");
      Serial.println(p->value());

      Serial.println("------");
    }

    request->send(200, "text/plain", "message received");
  });

  server.begin();
}

void loop() {}

index.html
<!DOCTYPE html>

Main Menu

<button class="button">Selection</button>

<button class="button">Oblivion</button>

selection.html
<!DOCTYPE html>

<form action="/" method="get">

    Shape Size:

    <select name="size" id="size" style="font-size: 22px;">
      <option value="1"> 1   </option>
      <option value="2"> 1/2 </option>
        </select>

Speed:

    <select name="speed" id="speed" style="font-size: 24px">
      <option value="1">          Slowest </option>
      <option value="2" selected> Regular </option>
    </select>

<button class="submit" name="circle" value="3">Circle</button>

<button class="submit" name="square" value="4">Square</button>

</form>

The data files must be uploaded via "Tools" → "ESP32 Sketch Data Upload".
How can the definitions, server.on("/" be combined so the data (size/speed/shape) is viewable in the serial monitor AND where the main and submenu remain the same (with their buttons)?
I have tried...

putting request->send(SPIFFS, "/selection.html", String(), false); and    request->send(200, "text/plain", "message received"); together inside  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)

sending different stuff for request->send(200, "text/plain", "message received"); even though I still do not understand how to get it to submit data, and return to the main menu, without clearing it out with a new message (various trial and error combinations either did not allow it to compile or just made one of the pages "Not found")

messing with HTML stuff (nothing changed)

So - if I understand you correctly - you want to just normally serve your index.html, until parameters are provided with the request. Then you want to output them to serial and serve the "message received" text. Is that correct?

Nope. The user selects their choices in the submenu (selection). Once clicking the submit button there, they return to the original main index menu and simultaneously (in the background) the query parameters are sent to the ESP32 of their selections. (When I replace "message received" with "" it just shows a blank main index menu.)

This is nothing to do with Arduino. This is all about Javascript and XMLHttpRequest calls.

Please don't repost, does this answer your question?

According to your original post https://arduino.stackexchange.com/questions/88538/esp32-access-point-and-http-web-server-how-to-send-multiple-parameters, you had a duplicate route handler for /, what you need to do is to change your param handling route to something else , say,  server.on("/submit" and also change your form submission action on selection.html to <form action="/submit" method="get">. It will shows it on Serial Monitor as what you are asking.

This is not an answer per se.
Posted as an answer because of attached images.
It is unclear what you are actually asking.
I ran a python minimal web server in the same folder as index.html.
Here is the trace from the server.
C:\Users\qwerty\Desktop2\MinimalExamples-main\22-1-25_query_parameters_submitButton\data>py3 -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
::1 - - [27/Jan/2022 15:43:23] "GET / HTTP/1.1" 200 -
::1 - - [27/Jan/2022 15:43:24] code 404, message File not found
::1 - - [27/Jan/2022 15:43:24] "GET /favicon.ico HTTP/1.1" 404 -
::1 - - [27/Jan/2022 15:43:25] "GET /selection.html HTTP/1.1" 200 -
::1 - - [27/Jan/2022 15:43:32] "GET /?size=2&speed=1&circle=3 HTTP/1.1" 200 -
::1 - - [27/Jan/2022 15:43:34] code 404, message File not found
::1 - - [27/Jan/2022 15:43:34] "GET /notMinimal.html HTTP/1.1" 404 -
::1 - - [27/Jan/2022 15:43:39] "GET /?size=1&speed=2&circle=3 HTTP/1.1" 200 -
::1 - - [27/Jan/2022 15:45:07] "GET /?size=1&speed=2&square=4 HTTP/1.1" 200 -
::1 - - [27/Jan/2022 15:52:46] code 404, message File not found
::1 - - [27/Jan/2022 15:52:46] "GET /notMinimal.html HTTP/1.1" 404 -
::1 - - [27/Jan/2022 15:53:02] "GET /?size=2&speed=1&square=4 HTTP/1.1" 200 -

This is what index.html is called with.
The data is available to index.html. You only have to parse it from the URL.


text:
How I can use more than 64 analog in arduino
Hi dears
I want help I’m in begging in programming. I want use more than 64 analog pin for ldr photoresistor in single reading. Because I can’t   use digital pin 0-1.
Any methods I can use ,,,,
And How??

what are you trying to do? .... Because I can’t use digital pin 0-1. ... why do you say that? ... how would that give you 64 analog inputs?

Which Arduino? I don't know of any that have 64 analog inputs to start with. I agree with jstotola. What are you trying to achieve? This sounds like an X-Y problem.

You basically have 2 ways to do this:

You can use multiplexer chips, which are capable of carrying analog signals. Then you can connect the multiplexers to an analog input and the inputs of the multiplexers to the LDRs. Each multiplexer gets controlled over multiple digital pins (depending on the exact chips; it may be good to find one with a serial interface like I2C) and connects the analog input with one of the LDRs. Which one depends on the control inputs.

You can use external ADCs (Analog Digital Converters, like the one in the Arduino). These are normally controlled over a serial interface (like I2C) and give you multiple analog inputs at once. For example this board from adafruit, which gives you 16 analog inputs and is controlled over only 2 lines (I2C, A4 and A5 on an Arduino Uno/Nano). This is probably a simpler way, though for a higher cost. If you want to to cheaper than the linked board, you may wanna use blank ADC chips instead of a breakout board.

Thanks dear you can help me more which the best and easier one,, and if you have an example for that.

Besr and easiest ist probably using the ADC board from adafruit. Are you willing to invest that much?

I've just built a board that allows an Arduino to access 192 analog inputs - one at a time of course. More is possible. It uses 4067 16 x 1 analog mux chips. A single 8 bit port controls it.
Need a schematic?

Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

My page about multiplexers gives some details about this approach.


text:
ATMega328p internal comparator problem - ISR(ANALOG_COMP_vect) not firing
After being introduced to this code on github, and exploring electronoobs tutorial I was compelled to try and recreate it with the Arduino Nano, and using the A0-A3 analog comparator inputs. Currently, I am just trying to get the rising edge of the receiver transducer to be recognized in the interrupt. Thus, I think my problem resides in ISR(ANALOG_COMP_vect)
Using an oscilloscope confirms that the ultrasonic transducer is firing every 100 ms, and I can detect the ping with the receiver as a small voltage above GND, which should trigger the ISR interrupt with DIO6 connected to GND... but that is not happening...
Here is my code:
#include  <avr/interrupt.h>

#include  <stdint.h>
#include  <stdlib.h>
#include  <stdio.h>
#include  <stdbool.h>

#include <Arduino.h>
#include  "fastio.h"

#define F_CPU 16000000UL

// pins for TX driver
#define PING0   PB1
#define PING1   PB2

#define LED     DIO13

#ifndef MASK
  #define MASK(m) (1UL << m)
#endif

#define DEBUG 0
#define INTERVAL 100
#define diff(a,b) (((a) >= (b))?((a)-(b)):((b)-(a)))

inline bool ge(uint32_t a, uint32_t b) {
  return ((a - b) & 0x80000000UL) == 0;
}

inline bool lt(uint32_t a, uint32_t b) {
  return ((a - b) & 0x80000000UL) != 0;
}

volatile uint32_t milliseconds = 0;

uint16_t starttime = 0;
volatile uint16_t envelopetime = 0;
volatile uint16_t phasetime = 0;

#define PULSECOUNT_X2 16
volatile uint8_t edges = 0;

void pins_init(void) {
  WRITE(PING0, 0);
  SET_OUTPUT(PING0);

  WRITE(PING1, 0);
  SET_OUTPUT(PING1);

  WRITE(LED, 0);
  SET_OUTPUT(LED);

}

void timer_init(void) {
  // init timers
  GTCCR = MASK(TSM) | MASK(PSRSYNC); // pause clocks

  PRR &= ~MASK(PRTIM1) & ~MASK(PRTIM0) & ~MASK(PRADC); // enable timers 0 and 1 and ADC

  // use timer1 for output waveform generation and analog comparator timing
  TCCR1A = 0;                       // normal mode, no match behaviour
  TCCR1B = MASK(CS10);              // maximum speed (no prescale)

  // use timer0 for our millisecond clock
  TCCR0A = MASK(WGM01);             // CTC mode
  TCCR0B = MASK(CS00) | MASK(CS01); // prescaler=64, ie clock is 250kHz
  OCR0A  = 250;                     // interrupt at 1kHz, ie every 1ms
  TIMSK0 = MASK(OCIE0A);            // interrupt on compare

  // set up analog comparator
  ADCSRA = (0 << ADEN);
  ADCSRB = (1 << ACME);
  ADMUX = 0;
  ACSR |= 0x03;

  GTCCR = 0; // re-enable clocks
}

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

void loop() {
  timer_init();
  sei();
  Serial.println("Start");

  uint32_t pingtime = INTERVAL;

  for (;;) {
    if (ge(milliseconds, pingtime) && (edges == 0)) {
      // note when we should ping next
      pingtime += INTERVAL;

      // start in a millisecond from now to avoid race conditions
      starttime = TCNT1 + (F_CPU / 1000);
      OCR1A = OCR1B = starttime;

      // reset edge counter
      edges = PULSECOUNT_X2;

      // set A and clear B on match
      TCCR1A = MASK(COM1A0) | MASK(COM1A1) | MASK(COM1B1);

      // disable interrupt on comparator
      TIMSK1 &= ~MASK(ICIE1);

      // clear flag in case it triggered during startup
      TIFR1 = MASK(OCF1A);

      // enable interrupt
      TIMSK1 |= MASK(OCIE1A);
    }
    if (phasetime != 0) {
      uint16_t eoff = envelopetime - starttime; // time when Rx signal became loud enough to consider, ie start of envelope
      uint16_t poff = phasetime - starttime;    // time of first zero crossing after envelope, use for calculating phase offset

      //printf_P(PSTR("envelope +%u (%uus) phase +%u (%uus)\n"), eoff, eoff >> 4, poff, poff >> 4);

     Serial.println(eoff);
     //Serial.println(poff);

      // zero so we only print once, process data before this
      phasetime = 0;
    }
  }
}

ISR(TIMER1_COMPA_vect) {
  if (edges == PULSECOUNT_X2) {
    TCCR1B |= MASK(ICES1);   // listen for rising edge
    TIFR1 = MASK(ICF1);      // clear flags in case it triggered during startup
    TIMSK1 |= MASK(ICIE1);   // interrupt on comparator

    TCCR1A = MASK(COM1A0) | MASK(COM1B0); // toggle on match
    //Serial.println("PULSE");
    WRITE(LED, 1);
  }
  else if (edges == 1) {
    TCCR1A = MASK(COM1A1) | MASK(COM1B1); // clear both on match
  }
  else if (edges == 0) {
    //putc('>');

    TIMSK1 &= ~MASK(OCIE1A);   // disable interrupt

    return;
  }
  edges--;
  OCR1A = OCR1B += F_CPU / 80000; // set next timeout
}

ISR (ANALOG_COMP_vect)
  {
  phasetime = ICR1;
  if((ACSR & B00100000)){
    envelopetime = ICR1;      // store timestamp
    WRITE(LED, 0);
    TIMSK1 &= ~MASK(ICIE1);   // disable interrupt on comparator
  }
}

ISR(TIMER0_COMPA_vect) {
  milliseconds++;
}

What's the purpose of ge() and lt()? Why not >= and <? 2. There is a lot going on in this code. Could you reduce this to a minimal example that shows the problem you are facing and nothing more? 3. You don't explain enough how it is supposed to operate. Must we read the full tutorial in order to understand it? 4. Expressions such as ACSR & B00100000 are very hard to decipher. ACSR & MASK(ACO) would be more readable. 5. You may want to use the avr-libc macros such as _BV() (equivalent to your MASK()) and bit_is_set().

ISR(ANALOG_COMP_vect) will never fire if you don't enable the interrupt (bit ACIE in ACSR).

Everything Edgar Bonet said. If I were working on this I'd probably remove MASK for the same reason I wouldn't use _BV. Unless you're making extraordinary use of these, they exist mostly so other people reading the code can have a "WTF?.... oh is that all?" moment. It's difficult to tell if the same thing is happening with ge() and lt().

You have not enabled the comparator interrupt.
Just need to change the line where you set ACSR.
//Comparator interrupt on rising output edge.
ACSR |= (1 << ACIS0) | (1 << ACIS1);

//Enable comparator interrupt
ACSR |= (1 << ACIE)

Can also be achieved with.
ACSR = 0x0B

If you want to change what triggers an interrupt.
Bits 0 and 1 control how an interrupt is fired (Toggle, falling or rising).
//Toggle (Default, only required if another interrupt mode is already selected)
ACSR &= ~(0b11)

//Falling
ACSR &= ~(1 << ACIS0); //Only required if ACIS0 is set
ACSR |= (1 << ACIS1);

//Rising
ACSR |= (1 << ACIS0) | (1 << ACIS1);
//Or
ACSR | = 0x03;

You will also need to enable global interrupts. (Which you have done)
Which can be done by calling...
interrupts(); //Arduino only
sei();        //AVR and Arduino

I see you are calling "sei" in the loop, it only needs to be called once (unless you have disabled them with "cli()," and I believe its not even required at all with Arduino as I think interrupts are already enabled.
The datasheet is your friend. Tutorials are a great way to learn, but if you really want to increase your skill set you should try to break free from tutorials as much as possible by reading the datasheet, and experimenting on your own.
The comparator starts on page 202, and would be a great place to start as its an easy peripheral to get going.


text:
Problem adding library in the Arduino IDE
Currently, I'm trying to build image processing on ESP32 using OpenCV GitHub - joachimBurket/esp32-opencv: Shrinked OpenCV for ESP32. Then I want to put this library into Arduino IDE.
But, I'm having problem "Specified folder/zip file does not contain a valid library".  Is there a file that must be deleted to be included in the Arduino IDE libraries? And, I previously also tried manual input. But, not everything was detected by the Arduino IDE.
Please give me a way out as I am new in this field.

it is not an Arduino library

As Juraj wrote, this is not an Arduino library. It is meant to be compiled directly with the esp-idf toolchain, outside of the Arduino framework. To use it you would first have to port it to the Arduino framework, which is probably rather tedious.

Thank you for your answer. what if i change or adapt to the arduino libraries and manually input to arduino ide libraries, is it possible?


text:
Problem regarding on HC-SR04 sonar with an additional stepper and SG90 servo motor
I'm making a project based on HC-SR04 ultrasonic sensor with a stepper motor and an SG90 servo motor. I have done some conditions for my stepper motor that is given below. Now I want to include my servo in it. When the distance goes below 10cm the servo rotates at 90 degrees (N.B. the stepper remain the same as it is) and when the distance is above 10cm then the servo comes back to 0 degree.
Please help me out to complete this.
Thanks.
#include <Stepper.h>

// Define number of steps per rotation
const int stepsPerRevolution = 2048;

int rotationCW = 0;
int rotationCCW = 0;
int location = 1;

// Create stepper object called 'myStepper' note the pin order:
Stepper myStepper = Stepper(stepsPerRevolution, 8, 10, 9, 11);

const int trigPin = 2;
const int echoPin = 3;

// defines variables
long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement

void setup()
{
  myStepper.setSpeed(15); //Set the speed to 5 rpm

  Serial.begin(9600); // // Serial Communication is starting with 9600 of baudrate speed

  pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
  pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
}

void loop()
{
  // Clears the trigPin condition
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  // Sets the trigPin HIGH (ACTIVE) for 10 microseconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);

  // Calculating the distance
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)

  // Displays the distance on the Serial Monitor
  //Serial.print("Distance: ");
  //Serial.print(distance);
  //Serial.println(" cm");

  if (distance >= 20 && location == 1)
  {
    rotationCW = (.4 * stepsPerRevolution);
    myStepper.step(rotationCW);
    location = (2);
    delay(500);

    Serial.println ("Gate closed");
  }
  else if (distance <= 20 && location == 2)
  {
    rotationCCW = .4 * -stepsPerRevolution;
    myStepper.step(rotationCCW);
    location = 1;
    delay(500);

    Serial.println ("Gate opened");
  }
}

What is your exact problem in doing this? I don't see any servo code.

There is no problem with this code. I just want to added an extra servo with it, and it will rotate 90 degrees when the distance measurement is under 10cm, and goes back to its initial stage (i.e. 0 degree) when the distance will be up to 10 cm.

But why are you not just doing this? Adding an if statement for 10cm and adding servo code (like in the examples that come with the Servo library). You can find many tutorials and examples online about how to use a servo with Arduino. Have you looked and tried them? What exactly didn't you understand? What exactly makes you problems here? We need to know that to provide a good answer. We won't just write the code for you.

Yes, I tried. I actually want to do a project that meets the following conditions. Those conditions are:

When the distance is less than 20cm the stepper motor rotates clockwise (specific step) - gate open
When the distance goes above 20cm, the stepper rotates counterclockwise (specified step) - gate closed

When the distance goes below 10cm, a servo will rotate 90 degrees + as well as the stepper will fulfill its previous conditions.
When the distance goes above 10cm, the servo fire will come to the previous position + the stepper will still keep the gate open because 20cm has been fixed before.

I don't understand how to create the loop, and which conditional loop is useful to fulfill those conditions.

What do you mean by "loop"? Sounds just like ifstaments with distance < 10 (and the corresponding else statement), where you execute the Servo.write() in. Maybe it helps you to write that down. Imagine you are the program. What steps do you need to do in exactly which order to reach your goal. Each instruction needs to be one single action, like "set motor to 90°" or "if distance smaller than 10cm" or "rotate stepper Y steps". Check your own logic. When thats correct you can nearly directly translate each line into Arduino code


text:
Writing Arduino code for MPXV6115V pressure sensor
I'm attempting to use an MPXV6115V pressure sensor to monitor the constant vacuum of a suction device. I haven't been able to find a library to use with this sensor. I'm very new to Arduino but I am a software developer so would like to write some code to get this sensor working. The datasheet for this sensor can be found here. I've had some success using the code found here but this is for a different MPX pressure sensor and the output doesn't look right, I believe my constant values might need adjusting but not sure.
I've heard I may be able to use the transfer function for the basis of the code? I'm really not sure where to start with that. Could someone please explain how I can write the code to get this sensor working with the Arduino? Thank you.

why would you need a library? ... the sensor outputs voltage that is proportionsl to the pressure ... measure the voltage

The linked code basically just does analogRead()s, calculates a real world value from the results and sends it over Serial. Thats also what you want to do, you just need to change the calculation.
So take the transfer function of your sensor and reorder it so that you get a formula for P:
P = (Vout/Vs - 0.92)/0.007652

with Vs being the supply voltage (5V in this case) and Vout being the output voltage. The ADC of the Arduino is 10 bits, so it gives you a value in the range of 0 to 1023 for 0V to 5V. So you get the voltage by calculating
voltage = analogRead(pin) / 1023.0 * 5.0;

Now put that into the formula above, write it as proper C++ code (for the variables use float as type, while pin is an integer and is the pin you connected the sensor to, like A0) and then replace the calculation in the linked code with yours - or wrote your own complete code. There isn't much to do besides analogRead(), the calculation and corresponding Serial.println() calls.


text:
Problem with IR remote and Pushbutton for digispark
As digispark is more compact and suitable for my electrical application. Following the same procedure in brtiberio answer. I tried to convert the script from Arduino UNO to digispark, but not succeed
#define irPin 2
const int buttonPin1 = 0;
const int buttonPin2 = 4;
const int relay1 = 1;
const int relay2 = 3;
int Relay1State = 0;
int Relay2State = 0;
int master1State = 0;
int master2State = 0;
int button1State;
int button2State;
int lastButton1State;
long lastDebounceTime1 = 0;
int lastButton2State;
long lastDebounceTime2 = 0;
long debounceDelay = 50;
void setup() {
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  digitalWrite(relay1, Relay1State);
  digitalWrite(relay2, Relay2State);
}

void loop() {

  int key = getIrKey();

  if(key == 7388){
    Relay1State = !Relay1State;
    if(Relay1State == true)
      digitalWrite(relay1, HIGH);
    else
      digitalWrite(relay1, LOW);
  }

  if(key == 1778){
    Relay2State = !Relay2State;
    if(Relay2State == true)
     digitalWrite(relay2, HIGH);
   else
     digitalWrite(relay2, LOW);
  }
}

int getIrKey(){
  int len = pulseIn(irPin,LOW);
  int key, temp;
  key = 0;
  //Serial.print("len=");
  //Serial.println(len);
  if(len > 6000) {
    for(int i=1;i<=32;i++){
      temp = pulseIn(irPin,HIGH);
      if(temp > 1000)
        key = key + (1<<(i-17));
    }
  }
  if(key < 0 )
    key = -key;

  //if(key)
    //Serial.println(key);

    delay(250);
  return key;
  //**********************//
  int reading = digitalRead(buttonPin1);
  if (reading != lastButton1State) {
    lastDebounceTime1 = millis();
  }
  if ((millis() - lastDebounceTime1) > debounceDelay) {

    if (reading != button1State) {
      button1State = reading;

      if (button1State == HIGH) {
        master1State = !master1State;
        Relay1State = master1State;
      }
    }
  }

  digitalWrite(relay1, Relay1State);
  lastButton1State = reading;

  //*******************************//
  int reading2 = digitalRead(buttonPin2);
  if (reading2 != lastButton2State) {
    lastDebounceTime2 = millis();
  }
  if ((millis() - lastDebounceTime2) > debounceDelay) {

    if (reading2 != button2State) {
      button2State = reading2;

      if (button2State == HIGH) {
        master2State = !master2State;
        Relay2State = master2State;
      }
    }
  }

  digitalWrite(relay2, Relay2State);
  lastButton2State = reading2;
}

Any advise, please?

not succeed is not a description of a problem

Not sure why you means of "to convert the script from Arduino UNO to digispark"? IRremote library does support DigiSpark (and ATtiny85) without the need of any conversion.

Which Arduino Core are you using? If you are running ATTinyCore, you can use the IRremote library without any problem.

The remote part is working well. the problem is with the push button function only. it dosen't works.

@Mah would you please share your final codes? I am in badly need of that

Your button code is in the function int getIrKey(). But it never gets executed, because before it you execute return key;. With that you leave the function and returning the value of key. Everthing that comes after the return statement will not be executed.
Putting the button code in that function doesn't make sense in the first place (since the buttons are not used to "get the pressed IR key"). Instead try to put it in the loop() function, after the other relay code.

Thanks to chrisl. It is working fine now.

If you think my answer was correct, you can mark it as correct, so that others can see and learn from that.

Sorry, I forget that.


text:
How to update root certificate(s) on Arduino MKR GSM 1400 (SARA-U201 basically) in order to be able to connect to GCP MQTT?
I wish to upload measurement data to Google Cloud Platform IoT Core with Arduino MKR GSM 1400. I have followed:
https://docs.arduino.cc/tutorials/mkr-gsm-1400/securely-connecting-a-mkr-gsm-1400-to-google-cloud-iot-core
and
https://create.arduino.cc/projecthub/Arduino_Genuino/securely-connecting-a-mkr-gsm-1400-to-google-cloud-iot-core-b8b628
but I did not succeed on connecting to Google's MQTT broker.
I have seen that I am not the only one with this problem, but I hope that someone has figured out the solution to this problem.
Reading this:
https://groups.google.com/a/arduino.cc/g/developers/c/EK7lmDK-jTA?pli=1
I came to the realization that I might need to update the root certificate in the "radio module", aka SARA-U201. I've tried to figure out how to do this, and stumbled upon the arduino-fwuploader, I have tried to run it like this:
/arduino-fwuploader firmware get-version -b arduino:samd:mkrgsm1400 -a /dev/ttyACM0
in order to succeed with this:
./arduino-fwuploader certificates flash -b arduino:samd:mkrgsm1400 -a /dev/ttyACM0 -u mqtt.googleapis.com:443
but the fwupdater does not even find the board despite "arduino:samd:mkrgsm1400" being correct. And yes, I am trying to do all this under Linux.
I was also trying to make the example: "SSLCertificateManagement_Example" working, but for this I would have needed the certificates to be converted to DET format and arrange it to be an array of unsigned chars.
https://www.sslshopper.com/ssl-converter.html
At this point I don't know what else I should/could try. I know for a fact that the hardware itself is working, I have tried as many examples regarding GSM as I could (sending SMS, GPRS ping, initiating a voice call, detecting GSM networks, etc.), and all worked. Following the tutorial, I have properly locked the ECC508 crypto chip, and generated a private/public key into slot 0. I have a GCP account, configured it properly, I have even tried to disable the HTTP protocol in the GCP project registry, but no use, I still think that it is about updating the root certificate in the SARA module.
Did anyone figure this out yet?
Thank you for the related tips and ideas!

Your question is "how to upgrade root cert", but your description is more like  "how to establish a SSL connection". Nobody will follow all the links you provided trying to guess how's your code looks like and what are you trying to do, it would be easier for you to post your code, and more importantly what shows on the Serial Monitor? So that it provides better understanding on whether it failed on establishing a SSL connection (which root CA will be used) or failed on authentication (which your public/private key) exchange mattered.

Hi Hcheung, thank you for the feedback, I may have been less specific at places where I should have been more specific. I wanted to demonstrate what I have done to try to solve the problem. The complete code can be found under my first link in the original question. Near the end of the "comments" section of the second link people begin to write about the same problem, what I am facing: The code gets stuck at an endless loop (writing ascii "."-s) trying to connect to mqtt.googleapis.com. That's the point where I begun my investigation.


text:
I cant get a stepper motor to work with arduino UNO
I'm using an arduino UNO with a L2989N motor controller with a nema 17 hanpose 17h3401 stepper motor. I'm using two 9 volt batteries in series to power it. I'm sure I connected them properly but it just doesn't work. I tried using the example stepper motor sketch stepper_oneRevolution but it didn't work. I just cant pinpoint what's wrong.
PS. I'm very new to this

standard 9V block batteries? They are not made for providing that much current. You need other batteries

It is highly likely your power source supplies insufficient current to power both the stepping motor and the Arduino reliably.
This is very similar to one of my past stackexchange question / answer.
Where I say ...

Consider using a power source which can supply more current.  For
instance, D size cell batteries can supply much more current than
a small 9 volt battery.

... all that said, stepping motors are high current devices.  It may not be feasible to run stepping motors off batteries.

Can you post a schematic as you have wired it showing all connections. You connect a lot of things but to what? Also post links to the hardware items. I did not find the L2989N motor controller.

@Gil, if you are asking questions of the O.P. then you might put your comment after the Question and not after the Answer. Then the O.P. might get a notification instead.

@김준호, do edit your original post instead of posting an answer.  Otherwise it is confusing as people can and do sometimes answer their own questions.  A L298 does not appear to have a 12v to 5v regulator.  But maybe there is one on the board you bought?  Do you have a link to that product?  What a battery can power depends on more than it's chemistry (LiPo) or voltage (14.8V).  Maybe try 2 different batteries.  One for the Arduino and another for the motor.  As a test if nothing else. Just so you know, some large steppers may need the likes of a motor cycle battery to keep running.


text:
Question about using millis for alarm conditions - Arduino
I am new to programming in general and to Arduino as well.
I am working on a small project to improve my ability to write complete and kind of useful programming sketches.
I am facing a problem. I am using a few things in my circuit like 7-segment display and relays and several indicating LEDs and a buzzer.
Let's sat that when a condition occurs I want one LED to  blink while everything still works fine and sends data to the display and controls relays, and I solved that with the millis function.
But the problem came when I tried to implement the same concept to the buzzer (which in my case I want to buzz for a pre-set amount of time, and then stop, without keeping buzzing all the time which might be too long), without using the delay function.
I tried many many code but nothing would work for me so far. Here is the simple code of my sketch. I hope you guys will help me find a solution
const byte buzzer = 13;  // buzzer_PIN
const byte switch1 = 3;  // PUSH-BUTTON PIN

/* please NOTE:
that the switch in my project will actually represent a condition to start the buzzer alarm, then maybe that condition will not exist, and after that the condition might come back and need the buzzer again
*/

unsigned const int delaytime = 500; // delay time needed between on and off states for the buzzer
unsigned long previousBuzz = 0;     // Variable for millis
unsigned long currentTime = millis();
boolean buzzPreState = true;        // Boolean made to avoid repetition for the buzzer when not needed

void setup() {
  pinMode(buzzer,OUTPUT);
  pinMode(switch1,INPUT_PULLUP);
}

void loop() {
  unsigned long currentTime = millis();
  int switchVal = digitalRead(switch1);

  if (switchVal == LOW && currentTime - previousBuzz > delaytime && buzzPreState == true) {
    previousBuzz = currentTime;
    buzzPreState = false;
    buzzerStart(5);
    buzzPreState = true;
  }
}

void buzzerStart(int repeat) {
  for (byte i=0; i<repeat; i++) {
    digitalWrite(buzzer, !digitalRead(buzzer)); // to switch buzzer ON and OFF alternatively
  }
}

active or passive buzzer? for passive buzzer you can use tone() function where you can specify the duration. it doesn't block execution. https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

@Juraj
Thank you for your replay my friend, actually it is an active buzzer..

Then why are you toggling the buzzer pin multiple times without any time inbetween in buzzerStart()? Doesn't make much sense to me. An active buzzer just has to be turned on and off (via digitalWrite()). So you could replace buzzerStart(5) with a single digitalWrite(buzzer, !digitalRead(buzzer);

You are missing a delay here:
for (byte i = 0; i < repeat; i++) {
    digitalWrite(buzzer, !digitalRead(buzzer));
}

Without the delay, the whole loop terminates so fast that you cannot
hear anything.
Now, if you want non-blocking code, you should instead use the approach
of the Blink Without Delay tutorial:

have the program remember the current state
when it's time to switch states (as determined by millis()), update
the current state.

The difficulty is that, whereas the program state in that tutorial is
trivial (either the LED is off or it's on), in your case it is more
complex. In addition to the time of the last toggle, you have to keep
track of:

whether the buzzer is off or on
whether it is supposed to be making sound
a counter for the buzzing cycles.

The approach I would use is to have a counter (let's call it
buzzer_remaining) telling how many cycles it still has to complete.
The counter would decrement when the pin goes LOW. When it reaches
zero, the buzzing is done. Note that this choice implies that, when the
condition for buzzing becomes true, we will start at the middle of a
buzzing cycle.
Here is a tentative implementation of this approach:
const uint32_t buzzer_half_period = 500;  // 500 ms in each state
const uint8_t buzzer_count = 5;  // buzz for 5 cycles
uint8_t buzzer_remaining;        // remaining buzzing cycles
uint8_t buzzer_state;            // LOW or HIGH
uint32_t buzzer_last_toggle;     // millis() at last toggle time

void buzzer_start() {

    // Ignore request to start if we are already buzzing.
    if (buzzer_remaining > 0)
        return;

    // Initialize the buzzer state.
    buzzer_remaining = buzzer_count;
    buzzer_state = HIGH;
    digitalWrite(buzzer, buzzer_state);
    buzzer_last_toggle = millis();
}

// Call this periodically from loop().
void buzzer_update() {

    // Do nothing if we are not supposed to be buzzing.
    if (buzzer_remaining == 0)
        return;

    // Do nothing if it is too early to switch state.
    uint32_t now = millis();
    if (now - buzzer_last_toggle < buzzer_half_period)
        return;

    // Update the buzzer state.
    if (buzzer_state == LOW) {
        buzzer_state = HIGH;
    } else {
        buzzer_state = LOW;
        buzzer_remaining--;
    }
    digitalWrite(buzzer, buzzer_state);
    buzzer_last_toggle = now;
}

I resisted the temptation to put all this inside a class. It would be
cleaner, but I think this “plain C” style of programming might be easier
on a newcomer.
Note that calling buzzer_start() when the program is already buzzing
has no effect: the request to start the buzzer is ignored. This is not
the only possible choice: one could instead want to reset the counter in
order for the buzzing to last longer. The choice I made is arbitrary,
and I only made it because, in your question, the program requirements
are not fully specified.


text:
Can't upload programs to Raspberry Pi Pico with Arduino
I am trying to use a RP2040 Pico with the Arduino IDE. This is a huge uphill battle. Initially I couldn't get the upload serial port to show up, then copied the "hello world" UF2 to the Pico folder (https://datasheets.raspberrypi.com/soft/hello_world.uf2), after which the port showed up in the Arduino ISE 2.0.0 on Windows 10 - but I can't upload any programs. All I get is this error message:
    Traceback (most recent call last):
      File "C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.9.15/tools/uf2conv.py", line 380, in <module>
        main()
      File "C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.9.15/tools/uf2conv.py", line 360, in main
        drives = get_drives()
      File "C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.9.15/tools/uf2conv.py", line 233, in get_drives
        "FileSystem,", "DriveType"])
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 395, in check_output
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 472, in run
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 775, in __init__
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 1178, in _execute_child
    FileNotFoundError: [WinError 2] The system cannot find the file specified
    Upload error: Failed uploading: uploading error: exit status 1

This is ultra-weird, because no such folders etc. exist on my drive D:, and I have no idea why it's looking for files on drive D:\ in the first place, because the Arduino IDE is installed on drive C:. And these folders also aren't present on C:.
Does anyone have any ideas on how to fix this? I've Googled everything I can find and have so far found nothing helpful. I'm about ready to give up and would REALLY appreciate any help you can give!

Those paths with the D: drive come from the stacktrace of the library that's used. Whoever built that library did have a D: drive. Nothing to worry about for you.

The serial port is only used for resetting the chip into the bootloader. Once there it presents as a USB MSD device (hard drive) to which the .uf2 file generated to the IDE gets copied to. It looks like it's not finding that drive. When you upload does the board reset to present a hard drive or not? If not then you can force it by connecting the board while holding in the button on the board. Once it's showing a drive hit upload and it should work.

Thanks for the replies. Neither Arduino 1.8.19 nor 2.0.0 can access the RPi Pico via COM. Neither successfully compiles code for it either (maybe it's just me, but if a compilation fails because the IDE can't find a nonexistent file, I do tend to worry about it). Interestingly, the 2.0.0 IDE also can't find the COM port for an ESP32, which appears in the Windows device manager & also in 1.8.19. I'm ditching the RPi Pico in the Arduino ecosystem because I simply don't have more time to waste. Likewise, the Arduino IDE 2.0.0. They are more riddled with bugs than a rotting log in the rainforest.

Installing a generic driver with  https://zadig.akeo.ie/ while the PICO was plugged in solved the issue for me.

It took me two days to fix that mistake!
Who would have thought that this is due to the missing file "C:\Windows\SysWOW64\framedynos.dll".
When I put the file back in place, everything went back to normal.
UPD:
Turn on "Show verbose output" in Preferences and browse several last lines.
There should be a line like this:
C:\Users\light\AppData\Local\Arduino15\packages\rp2040\tools\pqt-python3\1.0.1-base-3a57aed/python3 -I C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.10.0/tools/uf2conv.py --serial COM5 --family RP2040 --deploy C:\Temp\arduino_build_214726/...

Copy and run that line in Terminal (Win-R). There may be bug reports to help you solve your problem.

Welcome to Arduino:SE.  This doesn't actually provide an answer to the question that was asked.  To ask another question, just click Ask Question above. If you wish, include a link to this question to help provide context.


text:
How to swap byte order
Background
I'm reading a 24-bit ADC value into a uint32. Using SPI bus, here's the logic:
value = SPI.transfer(0);   // read first 8 bits (MSB first)
value <<= 8;               // shift bits left
value |= SPI.transfer(0);  // read next 8 bits
value <<= 8;               // shift bits left
value |= SPI.transfer(0);  // read final 8 bits

As such I'm left with this ADC reading:
00000000 11111111 11111111 11111111
         MSB                    LSB

(Ignore the leading zeros for now.)
Now I transfer this value over ethernet like so:
client.write((const byte*) &value, sizeof(value));

The problem is this:

The value is stored as MS bit first.
client.write() transmits it LS byte first.

I am using NodeRED as a TCP server. So at the other end, I receive the data like this:
11111111 11111111 11111111 00000000
     LSB          MSB

I understand this is the expected behavior, but I would like to switch the BYTE order around before sending, so that it is read in NodeRed native endianness.

Question
Perhaps I should do some bit shifting at the point of reading the ADC, to accommodate the fact that client.write() sends the least significant byte first, like this:
  byte1 = SPI.transfer(0);
  byte2 = SPI.transfer(0);
  byte3 = SPI.transfer(0);
  response = byte3;
  response <<= 8;
  response = byte2;
  response <<= 8;
  response = byte1;

Is this the most efficient way in terms of clock cycles?
Please note that my MCU is a Teensy 4.1, and I'm transferring 10,000 readings per second. I would like to keep the clock cycles for any necessary bitwise operations to a minimum, so that the timing of ADC readings are affected as little as possible.

You can use an array of byte to save the shifts at all. This solution should be the one with the least clock cycles, and with no additional memory usage.
static byte value[4] = { 0 };

    /* ... */

    /* value[0] is still 0. */
    value[1] = SPI.transfer(0);
    value[2] = SPI.transfer(0);
    value[3] = SPI.transfer(0);

    client.write(value, sizeof value);

Some notes:

Using an array avoids the re-interpretation of a 32 bit variable as a byte array. You read bytes from SPI, and write() expects a byte array. This circumvents your endianness issue completely.

In the call of write() you don't need to cast the address of value to const byte *, because the const is a qualifier for the called function. It is not allowed to change the bytes pointed to.

Making the array static saves you from zeroing the first byte repeatedly. BTW, it is sufficient to provide the first byte, as all other bytes are zeroed automatically. However, the last bytes will be updated on each transfer.

sizeof is an operator, not a function. However, it is quite common to use it with a type instead of an object, and then you need parentheses because of the syntax. But it is better to use the respective object, actually you mean that.

You have explained this really well, but just to confirm as I get to grips with this idea, you are saying instead of using an in32_t function and creating a response value, then reading / shifting each byte into the value, it's better to create an array of bytes? So let's say I am storing 100 values, I would have a 2D array (100 x 3 or whatever)? I am sure the answer is "yes" but I just wanted to fully understand.
Also what if I want to cast to float and send that value, with bytes swapped as well? Is it best to read into an array, then somehow cast 3 vals in the array to a float?

// reverse wire order:
client.write((const byte*) &value + 3, 1);
client.write((const byte*) &value + 2, 1);
client.write((const byte*) &value + 1, 1);
client.write((const byte*) &value,     1);

Just nitpicking but... I would add either spaces around + or parentheses around (const byte*) &value. Otherwise it looks like + binds more tightly than the cast, which is of course not the case.


text:
Using Random() and Greater Than
Total Arduino noob, I come from a Python "background", though I barely know that, either.
I'm writing a super simple script that will turn on a bulb when the random number generator generates a number greater than 100. Obviously, I have a syntax problem or something: What am I doing wrong? Secondly, How quickly does random query numbers? Is it possible to slow it down? I don't need my bulb turning on 50 times a second.
Thanks! And please be kind; I know this is Googleable, I just lack the prerequisite knowledge to Google this efficiently.
/*

*/
int relayPin = 7;
int randomNumber = random(1001);

void setup() {
  pinMode(relayPin, OUTPUT);

}

void loop() {

if(randomNumber > 100)
  digitalWrite(relayPin, LOW);

else{
   digitalWrite(relayPin, HIGH);}

}```

what is the problem?

btw, put the ``` on a separate line so that it is invisible

The problem is that the relay module does not switch. I assume that there is an error in my code.

yes, logic error ... ask yourself  when is the value of randomNumber updated?

The current code (if you move the random number generation into loop()) will switch not just 50 times, but thousands of times per second. Look at some example code to get an idea about how to solve that.

Start to learn, aka "build knowledge", by looking into some of the provided examples... ;-)

Start with the blink example and think how you can randomise it...

There are a few things to be discussed in here.
First, the random number generation: in fact, the arduino does not generate random numbers. It has a list of numbers on its memory that just "seems" to be random. That's why it's called a pseudo-random number.
So, you need to declare a starting point on this sequence, from which you will get the "random" numbers. This is made with "randomSeed()" in void setup. For example:
void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point,
                             //in this case, the analogRead value of an unconnected pin
}

Next, let's generate our number. The variable can be global (as you declared it outside any function), but you must declare it with "random()" only inside "void loop". Otherwise, its value will be assigned just one time (that's what your code is telling it, to do it once).
Here is what I would do:
int relayPin = 7;
long randomNumber; //just declares the variable; it must be type "long"

void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point
  pinMode(relayPin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  randomNumber = random(0, 301);
  //each time the code loops, it assings another value to randomNumber
  //in this case, the number will be between 0 and 300 (301 is the excluded limit)

  if(randomNumber > 100){
    digitalWrite(relayPin, HIGH);
  }
  else{
    digitalWrite(relayPin, LOW);
  }
  delay(500); //half a second delay

}

If you want to have more details about how random numbers are generated in the Arduino, visit the Arduino language Reference:
https://www.arduino.cc/reference/en/

Thank you for this! This explanation was very kind and helpful of you! I will implement this after work.


text:
1 global variable consuming 19% of memory
I am working on a simple project on talking to the serial monitor, and my only global variable ("int" type, named "incomingByte") is consuming a lot of memory. There is no problem on running the scketch, but I am not satisfied to have it that way.
When I load it, I receive: "Global variables use 390 bytes (19%) of dinamic memory...".
Why is it happening, and how could I fix this?
int incomingByte = 0; //for the incoming serial data
void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point
  Serial.begin(9600);
  //waits for serial initialization to send the messages:
  //(Serial) returns false for serial off, and true for serial on. This is inverted with !.
  while(!Serial){
    ;
  }
  //sending instructions:
  Serial.println("Initializing...");
  Serial.println(" ");
  delay(2000);
  Serial.println("Please select an option:");
  Serial.println("1 - greetings");
  Serial.println("2 - random number");
  Serial.println("3 - calculator");
  Serial.println(" ");
}

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial.available() > 0){
    incomingByte = Serial.read(); // Serial.read() returns the first byte of incoming data

    //recognizing the command received:
    if (incomingByte == '1'){
      numberOne();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '2'){
      numberTwo();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '3'){
      numberThree();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
  }
}

void numberOne() {
  Serial.println("Hello, Vitor! Good to see you!");
}

void numberTwo() {
  //sets the random number to be picked between [0, 101[
  long randomNum = random(0, 101);
  Serial.print("Your random number is: ");
  Serial.println(randomNum, DEC);
}

void numberThree(){
  Serial.println("Tool not available yet");
}

Why do you think, that all the dynamic memory allocation is for that variable? Other things (like Serial) also use some of the RAM

I think that because the message I receive is telling "Global variables". As you said, does the object "Serial" count as a global variable, when using RAM?

Yes, it is global. It's just defined in a different file (inside the used Arduino core), but there at global scope

The random seed also needs to be stored somewhere, or some other state for the RNG.

Just out of curiosity, if you have two global variables, do they use 38% of memory?

A few things that count towards the “global variables” that you may not
think of:

all your literal strings, unless encapsulated within the F()
macro; you have quite a few of them
The Serial object, including its transmit and receive buffers (157
bytes on an Uno)
The vtable for HardwareSerial (that's the class Serial belongs
to, 18 bytes)
The time-keeping variables (9 bytes).

And then, on top of that, there are the actual global variables of your
code, and the static locals which, for the purpose of memory allocation,
are the same as globals. An int, for example, takes 2 bytes on
AVR and 4 bytes on most other hardware platforms.

Edit: answering the questions in a comment

every single time I call Serial it will increase the memory
consumption of the code?

I don't quite understand what you mean by “every time”:

Every time you add a reference to Serial to a sketch, the linker
will add the Serial object to your compiled code, and the program's
RAM consumption will grow by the size of this object.
Within a single sketch, whether Serial is used once or many times
makes no difference: the object will be instantiated only once.

why does the IDE considers everything that uses RAM as a global
variable?

When it says “global variables” it actually means “statically allocated
data”. It says “global variables” because it is targeted at beginners,
and the authors assume beginners would not understand what static
allocation means. Globals are the simplest form of static allocation.

is there a difference in consumption between globals and locals?

Yes. Globals get allocated statically, i.e. at compile time. That's why
the IDE can report how much space they will consume. Locals (at least
non-static locals) get allocated and deallocated on the stack, at run
time. Short of running the program in an emulator, it is very hard to
predict how much stack space a program will consume, as this will
usually depend on run-time events.

I understood about the literal strings and the serial consumption, but I couldn't get some points. Firstly, every single time I call Serial it will increase the memory consumption of the code? Also, why does the IDE considers everything that uses RAM as a global variable? (is there a difference in consumption between globals and locals?)

@VitorZ.: se expanded answer.

Oh now I got it! Your explanation was very useful and complete, thank you. By using your tip in transferring the strings to PROGMEM with F(), I could reduce the SRAM consumption from 19% to only 9%, with just 1% more of Flash usage.