text:
Trigger event onRelease of button
I am using the EasyButton library to detect button presses on an arduino.
I want do execute a function when the user

Presses a button
Presses and holds a button
Releases a button

Detecting when a user presses or holds a button is straight forward
#include <Arduino.h>
#include <EasyButton.h>
# define BUTTON_PIN 2;
EasyButton button(BUTTON_PIN);

void onPressedCallback() {
  Serial.println("Button was pressed and released");
}

void onHoldCallback() {
  Serial.println("Button was pressed and held");
}

void setup() {
  button.begin();
  button.onPressed(onPressedCallback);
  button.onPressedFor(buttonHoldDuration, onHoldCallback);
}

The easyButton library has the following events

onPressed
onPressedFor
onSequence

It has the following states

isPressed
isReleased
wasPressed
wasReleased
pressedFor
releasedFor

How would you trigger an event when a button is 'released'?
Full Documentation
https://easybtn.earias.me/docs/on-single-press-api
What I've tried

Check the state from inside an event

void onHoldCallback() {
  while (button.isPressed() {
     Serial.println("you are still holding the button");
  }
  Serial.println("Button was released");
}

This unfortunately creates an infinite loop since the button state is never refreshed (button.begin();)
Additional Resources

https://github.com/evert-arias/EasyButton/tree/main/examples
Source code for the system interupt https://github.com/evert-arias/EasyButton/blob/4e818410252e9518564fc55f8d4a976fac70a9b2/src/EasyButton.cpp#L55-L82

I have 3 states I want to perform different actions on. 1: Press 2: Press & Hold 3: Release. The hold and release action is the problem I haven't been able to solve

The onPressed() event Triggers a callback function when the button has been pressed and released.
Here's a test sketch to show what I mean. I've also added a function you could use to detect the moment the button is first pressed.
#include <EasyButton.h>

// EasyButton(uint8_t pin,
//            uint32_t debounce_time = 35,
//            bool pullup_enable = true,
//            bool active_low = true)
EasyButton button(2);

void onReleased(){
  Serial.println("Button Releast");
}

void firstPressed(){
  Serial.println("First Pressed");
}

void setup(){

  // Test output to serial monitor.
  Serial.begin(9600);

  // Initialize the button.
  button.begin();

  // Add the callback function to be called
  // when the button is pressed then released.
  // NOTE: This function is only called AFTER
  // the button has been released.
  button.onPressed(onReleased);

}

void loop(){

  // Continuously read the status of the button.
  button.read();

  // Call a function the moment the button is pressed.
  if(button.wasPressed()){
    firstPressed();
  }

}

Just check the easyButton state in your loop code and run your functions as required. The library already has the events you need, no point rolling your own. It's best just to set a variable or flag in event code so it returns quickly, then deal with the results in the main loop. The easyButton library has done most of that work for you.

Origionally I started with the EasyButton library, but when I wasn't able to get it working I switched to the madleech/Button@^1.0.0 library and got the following working.
Note that this depends on polling which could definitly be improved.
While this deviates from the original question, I feel it is worth sharing for anyone else who wants a working but (less than ideal) solution.
#include <Arduino.h>

#include <Button.h>

Button button1(2);

unsigned long buttonCheckMillis;

void setup()
{
  buttonCheckMillis = millis();
  button1.begin();
}

void loop()
{
  if (button1.toggled()) {
    // User pressed the button
    if (button1.read() == Button::PRESSED) {
      Serial.println("Button Pressed");
    }
    // User released the button
    else {
      Serial.println("Button Released");
    }
  }
  // Poll every 100 milliseconds to see if user is still holding button
  if (millis() - buttonCheckMillis > 100) {
    buttonCheckMillis = millis();
    if (button1.read() == Button::PRESSED) {
      Serial.println("Button Held");
    }
  }

}


text:
How initialise and uninitialise serial based on the user's input?
In Summary. If the argument is true, I want to create a function that prints the necessary stuff into the serial. However, if its false serial is uninitialised and does not print anything, it only executes the code.
The code below does not work, but it's an example code to show what I mean.
bool status;
void setDebug(bool x){
 if (x){
  Serial.begin(115200);
  status = true;
 }
else {
 status = false;}
}
void setup(){
 setDebug(true);
}
void loop(){
Serial.println("Hello World");
}

I have found a few solutions that might be beneficial

If Statement - This overall code works; however, I am looking for a better and more efficient way to do this

void loop(){
 if (status){
  Serial.println("Hello World");
 }
}

Preprocessor directive - I have seen many libraries use #ifdef DEBUG, which works. However, I want to be able to  change it through a function, and the preprocessor directives won't allow me to do that

void loop(){
 #ifdef DEBUG
  Serial.println("Hello World");
 #endif
}

How else can I achieve this?

source: Stack Exchange

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

sort: votes


text:
Using Visual Studio Code to program an Arduino
I had recently got an Arduino Uno and did quite a few programs on it. Now, I had always used Visual Studio Code to do my C projects. So, is it possible to use Visual Studio Code to program an Arduino, but without the Arduino plugin available in Visual Studio Code?
This might sound a bit weird, but I wanted to learn how to build those type of plugins from scratch. Are there some resources from where I could learn to do that? I searched through Google, but I couldn't find any answers.

Install extension Arduino by Microsoft. its very simple to configure and use.  for larger projects i would recommend platformio, BTW did you try new Arduino IDE2? if not give it a try, its much better than before.

This might not be the answer you are looking for, but maybe it helps you and others. Besides, it's too long to write as a comment.

Use VS Code only as editor
Make sure that your .ino file is as small as possible, typically, just enough to call a second file (.cpp or .c file). The idea is that you do not need to change the .ino file often as you need to load the .ino file only in your Arduino IDE. All other files (including the .ino) you load in VS Code.
Than you edit your files in VS Code as asual, but you compile/upload the file with the default Arduino IDE. The Arduino IDE doesn't see files being saved as new, so that's why you need not to change the .ino file often, as you need to synchronize it manually.

MS Visual Studio
I'm using MS Visual Studio, comparable to VS Code and written stubs or even emulations for certain Arduino classes (like Arduino, but also for other libraries I use on the Arduino, which mimic or at least print something when called).
This way I can fully compile an Arduino project, and most important, run it so I can check the business logic and some parts of the hardware logic on a normal PC having a decent debugger etc. When working, I can use the first solution to upload it to an Arduino.
Writing these stubs is quite some work and the simulation can depend on the project (like for a LED strip project I actually visualized the LEDs on a PC).

In both above cases, I use the Arduino IDE only for compiling and uploading, not for editing. It would be also useful to skip using this Arduino IDE completely by using a command line to compile/upload using the CLI version of Arduino (see comment of theBusyBee below. In at least Microsoft Visual Studio but probably Visual Studio Code external commands can be added calling this Arduino IDE for compiling/uploading.

PMF's comment below: You can use VisualMicro on top of  Microsoft Visual Studio; this is a paid extension.

You might want to add that the Arduino infrastructure allows building by the command line. There are also some questions here...

@thebusybee That's indeed a good addition. Not sure which questions you refer to.

Well, my free time is heavily limited, so I don't think I can search for and choose one. Perhaps someone else can do this and add it to the answer.

It's just 3 options (or options on top of each other).

Oh, I think we have a misunderstanding, perhaps. I meant that some questions here on SE/Arduino refer to CLI usage and might have good answers, worth to link to them. I did not mean that some points in this question are left open.

Ok clear ... I assume that with option 3, people will realize they can also use the CLI directly without any of the IDE's mentioned and search for that themselves.

Because Visual Studio was mentioned: There's actually an extension called "VisualMicro" that adds all features of the Arduino IDE to Visual Studio (+ a live debugger). It's not free, but cheap enough also for private projects.

@PMF: Thanks, I added it to the answer (with your name of course)

If you really looking for an alternate for Arduino IDE. Than I will recommends you to go with platformio. It has great library management.
Just install the platformio extensions on the vs code and you are ready to go.

You can write C++ file with the editor of your choice, include avr/io.h to manage Arduino I/O, and then compile with avr-gcc and upload with avrdude. This is what I do because I don't like working with the .ino sketch directory structure that hides away normal C++ code that you would use with any other microcontroller. (See What is the relationship of an Arduino .ino file to main.cpp?, Why does an `.ino` file have to be in a folder of the same name?)
Guide: https://create.arduino.cc/projecthub/milanistef/introduction-to-bare-metal-programming-in-arduino-uno-f3e2b4

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


text:
Problem with displaying true RMS of the main voltage using Arduino Uno and MAX7219
I want to display the true RMS of the main voltage using an Arduino and a MAX7219. At first, I used of circuit #1 (the following circuit) and the True RMS library. The circuit could successfully return the true RMS and print it on the Serial Monitor of thr Arduino every 0.5 s. The accuracy was acceptable. This circuit was supplied from a PC.

At the next step, I decided to use a MAX7219 (LedControl library) to display the true RMS voltage on a 7-segment display. For this, I used of circuit #2. I don't know what happened. The displayed voltage had variations. In circuit #1, the maximum error was 1 volt (checked by a true-RMS multimeter - for example, the voltage was 210 V and the printed voltage was 209 or 211 V). But in circuit #2, the error was up to 10 V with a fast variation. For example, the voltage was about 210 V (using multimeter) for a minute, but the displayed voltage by the Arduino was 203, then 209, then 217, then 205, then 200, then 215, ....
I also used another true-RMS multimeter to check the first multimeter. The voltage was the same value as the first one showed. The problem was that the voltage remained approximately constant, but the Arduino showed a variable voltage. I checked the supplied voltage from the PC. It doesn't have effective changes.
I also used of circuit #3, but I still had the same problem. It seems that the used of MAX7219 is causing the problem. What is the solution?

My code (for bi-color common anode 7-segment - I have 3 digits):
#include <TrueRMS.h>
#include <digitalWriteFast.h> // It uses digitalWriteFast only for the purpose of debugging!
                              // https://code.google.com/archive/p/digitalwritefast/downloads

#define LPERIOD 1000    // 1000 loop period time in us. In this case 1.0ms
#define ADC_INPUT 0     // define the used ADC input channel
#define RMS_WINDOW 40   // rms window of 40 samples, means 2 periods @50Hz
// #define RMS_WINDOW 50   // rms window of 50 samples, means 3 periods @60Hz

#define PIN_DEBUG 4

unsigned long nextLoop;
int adcVal;
int cnt = 0;
float VoltRange = 5.00; // The full scale value is set to 5.00 Volts but can be changed when using an
                        // input scaling circuit in front of the ADC.
Rms readRms; // create an instance of Rms.

// Max7219 ===============================================================
#include "LedControl.h"
int ClockPin = 5;
int CsPin = 6;
int DinPin = 7;
LedControl lc = LedControl(DinPin, ClockPin, CsPin, 1);
// 1 as we are only using 1 MAX7219

void setup() {
  Serial.begin(115200);
  pinMode(PIN_DEBUG, OUTPUT);

  // configure for automatic base-line restoration and continuous scan mode:
  readRms.begin(VoltRange, RMS_WINDOW, ADC_10BIT, BLR_ON, CNT_SCAN);
  //readRms.begin(VoltRange, RMS_WINDOW, ADC_10BIT, BLR_OFF, CNT_SCAN);
  // configure for no baseline restauration and single scan mode:
  //readRms.begin(VoltRange, RMS_WINDOW, ADC_10BIT, BLR_OFF, SGL_SCAN);
    readRms.start(); //start measuring
    nextLoop = micros() + LPERIOD; // Set the loop timer variable for the next loop interval.

  // Max7219
  // the zero refers to the MAX7219 number, it is zero for 1 chip
    lc.shutdown(0, false); // turn off power saving, enables display
    lc.setIntensity(0, 15); // 15 sets brightness (0~15 possible values)
    lc.clearDisplay(0); // clear screen
  }

// Max7219
byte board[1][8] = {
  {
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000
  }
};

//  Max7219             Device
void ClearDisplay(int b, int digit) {
  for (int i=0; i<8; i++) { // It clears all segments of Digit "digit" of Device "n"
    bitClear(board[b][i], 7-digit);
  }
}

void Display() {
  for (int i=0; i<9; i++){
     lc.setRow(0, i, board[0][i]);
  }
}

//         Device  Digit      Num       Dot
void SetNum(int b, int digit, int num, int dot) {
switch(num) {
  case -2: // displays  "-"
    bitClear(board[b][0], 7-digit); // seg-A
    bitClear(board[b][1], 7-digit); // seg-B
    bitClear(board[b][2], 7-digit); // seg-C
    bitClear(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitClear(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
  case -1: // it clears the display
    bitClear(board[b][0], 7-digit); // seg-A
    bitClear(board[b][1], 7-digit); // seg-B
    bitClear(board[b][2], 7-digit); // seg-C
    bitClear(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitClear(board[b][5], 7-digit); // seg-F
    bitClear(board[b][6], 7-digit); // seg-G
    break;
  case 0:
    bitSet(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitSet(board[b][3], 7-digit); // seg-D
    bitSet(board[b][4], 7-digit); // seg-E
    bitSet(board[b][5], 7-digit); // seg-F
    bitClear(board[b][6], 7-digit); // seg-G
    break;
  case 1:
    bitClear(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitClear(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitClear(board[b][5], 7-digit); // seg-F
    bitClear(board[b][6], 7-digit); // seg-G
    break;
  case 2:
    bitSet(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitClear(board[b][2], 7-digit); // seg-C
    bitSet(board[b][3], 7-digit); // seg-D
    bitSet(board[b][4], 7-digit); // seg-E
    bitClear(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
  case 3:
    bitSet(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitSet(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitClear(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
  case 4:
    bitClear(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitClear(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitSet(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
  case 5:
    bitSet(board[b][0], 7-digit); // seg-A
    bitClear(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitSet(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitSet(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
  case 6:
    bitSet(board[b][0], 7-digit); // seg-A
    bitClear(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitSet(board[b][3], 7-digit); // seg-D
    bitSet(board[b][4], 7-digit); // seg-E
    bitSet(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
  case 7:
    bitSet(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitClear(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitClear(board[b][5], 7-digit); // seg-F
    bitClear(board[b][6], 7-digit); // seg-G
    break;
  case 8:
    bitSet(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitSet(board[b][3], 7-digit); // seg-D
    bitSet(board[b][4], 7-digit); // seg-E
    bitSet(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
  case 9:
    bitSet(board[b][0], 7-digit); // seg-A
    bitSet(board[b][1], 7-digit); // seg-B
    bitSet(board[b][2], 7-digit); // seg-C
    bitSet(board[b][3], 7-digit); // seg-D
    bitClear(board[b][4], 7-digit); // seg-E
    bitSet(board[b][5], 7-digit); // seg-F
    bitSet(board[b][6], 7-digit); // seg-G
    break;
    default:
    break;
  }
  if (dot == 1) {
    bitSet(board[b][7], 7-digit); // seg-dp
  }
}

//                          0-1-2-3
//                  Device  Digit      Num       Dot      Color
void SetNumWithColor(int b, int digit, int num,  int dot, char color) {
  switch(color) {
    case 'r': // digits 0,1,2,3 are Red
      SetNum(b, digit, num, dot);
      SetNum(b, 4, -1, dot); // clears all Green segments
      SetNum(b, 5, -1, dot); // clears all Green segments
      SetNum(b, 6, -1, dot); // clears all Green segments
      SetNum(b, 7, -1, dot); // clears all Green segments
      break;
    case 'g': // digits 4,5,6,7 are Green
      SetNum(b, digit+4, num, dot);
      SetNum(b, 0, -1, dot); // clears all Red segments
      SetNum(b, 1, -1, dot); // clears all Red segments
      SetNum(b, 2, -1, dot); // clears all Red segments
      SetNum(b, 3, -1, dot); // clears all Red segments
      break;
    case 'o':
      SetNum(b, digit, num, dot); // Turns Red on
      SetNum(b, digit+4, num, dot); // Turns Green on
      break;
    default:
      break;
  }
  Display();
}

void loop() {
  adcVal = analogRead(ADC_INPUT); // read the ADC.
  // readRms.update(adcVal); // update
  digitalWriteFast(PIN_DEBUG, HIGH);
  readRms.update(adcVal); // for BLR_ON or for DC(+AC) signals with BLR_OFF
  // readRms.update(adcVal-512); // without automatic baseline restoration (BLR_OFF); substract a fixed DC offset in ADC-units here.
  digitalWriteFast(PIN_DEBUG, LOW);

  cnt++;
  if (cnt >= 1500) { // 500 = publish every 0.5s
    readRms.publish();
    float RMS=readRms.rmsVal;
    float AccRMS=RMS*128;
    int RMSout=AccRMS;
    Serial.print("Vrms=");
    Serial.print(RMSout);
    int a1=RMSout/100;
    int b1=RMSout%100;
    int a2=b1/10;
    int a3=b1%10;
    if (RMSout<200) { // Red
      SetNumWithColor(0, 0, a1,  0, 'r'); // displays a1 at digit 0
      SetNumWithColor(0, 1, a2,  0, 'r'); // displays a2 at digit 1
      SetNumWithColor(0, 2, a3,  0, 'r'); // displays a3 at digit 2
    }else if(RMSout<215){ // Orange
      SetNumWithColor(0, 0, a1,  0, 'o'); // displays a1 at digit 0
      SetNumWithColor(0, 1, a2,  0, 'o'); // displays a2 at digit 1
      SetNumWithColor(0, 2, a3,  0, 'o'); // displays a3 at digit 2
    }else{ // Green
      SetNumWithColor(0, 0, a1,  0, 'g'); // displays 1 at digit 0
      SetNumWithColor(0, 1, a2,  0, 'g'); // displays 2 at digit 1
      SetNumWithColor(0, 2, a3,  0, 'g'); // displays 3 at digit 2
    }
    Serial.print(", Vin=");
    Serial.println(RMS,4);
    // float dc=readRms.dcBias;
    // Serial.println(dc,4);
    cnt=0;
    // readRms.start();  // Restart the acquisition after publishing if the mode is single scan.

  }

  while (nextLoop > micros());  // wait until the end of the loop time interval
  nextLoop += LPERIOD;  // set next loop time to current time + LOOP_PERIOD

}

// end of Measure_rms.ino

Without seeing your code it's hard to guess completely, but this is my supposition:

The RMS measurement has to measure rapidly over a short period to capture the peak values of the AC waveform
You are updating the display while doing the measurement
The display updates slow down the sampling of the AC waveform giving you incorrect values.

You need to make sure that the sampling of the AC waveform happens fast enough by not doing anything else (much) during the sampling period and only displaying anything on the display when all the sampling for the current data point is done.

Thank you. Before displaying, the RMS over two periods is calculated. So, updating occurs after measurement and calculation. The code is here (https://github.com/MartinStokroos/TrueRMS). Actually, I plotted only A0 using "Serial Plotter" of Arduino. I could see that the amplitude is obviously changing fast in circuit #2!!!! while the multimeter didn't confirm this. But for circuit #1, it didn't occur at all. Why? Does Max7219 affect the input A0 or sin wave of main voltage?

That's just the library and examples. It's not your code.

I added my code. Thanks

@soheil the answer applies for setup() too


text:
How to connect Draw wire encoder to Arduino Uno?
Hello Stack Community,
I am new to Arduino, and I am trying to figure out how to connect a draw wire encoder to Arduino and collect data from it.
I have attached a link of the product that I currently have, which also has datasheet, incase anyone needs more information.
https://www.kuebler.com/en/products/measurement/linear-measuring-systems/product-finder/product-details/A30
I know that the encoder's output is through analog, but I am having trouble with connections as well.
To summarize, how can I connect the encoder to Arduino Uno?
Lastly, I am using the encoder to measure linear distance of linear actuators.

The simplest way is to use the version with potentiometer output:

simulate this circuit – Schematic created using CircuitLab
Connect the wiper to an analog input (A0 in the example), and use the analog reference voltage as "supply" voltage.

Hi Busybee, Thanks so much. It worked, well. I was able to convert analog values to digital values and then to volts. Since I am converting digital values to volt: I will have 0 digital value = 0 volts & 1023 digital value = 5 volts, I also know that 0 volts = 0 mm & 5 volts = 600 mm (based on draw wire encoder max & min range). Based on all of this how to convert volts to millimeters, any idea?

Why not simply multiply by 1000? -- Oh, BTW, you might like to mark the answer, comments with "thank you" are kind of frowned upon. ;-) This will help future visitors of this site, too, to decide which question/answer to read.


text:
Why modem driver is loaded and used from my linux machine in order to communicate with Arduino?
Once I plugin an arduino to my linux machine the following response is retrieved (via dmesg):
[ 7250.906241] perf: interrupt took too long (2504 > 2500), lowering kernel.perf_event_max_sample_rate to 79750
[ 9517.599165] usb 1-3: new full-speed USB device number 5 using xhci_hcd
[ 9517.749504] usb 1-3: New USB device found, idVendor=2341, idProduct=0043, bcdDevice= 0.01
[ 9517.749510] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[ 9517.749513] usb 1-3: Manufacturer: Arduino (www.arduino.cc)
[ 9517.749516] usb 1-3: SerialNumber: 7533131313335170A061
[ 9517.780753] cdc_acm 1-3:1.0: ttyACM0: USB ACM device
[ 9517.781046] usbcore: registered new interface driver cdc_acm
[ 9517.781047] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

The last line from dmesg caught my attention:
[ 9517.781047] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

Also as far as I remember in order to communicate with arduino my user needs to be into dialout group. Does that mean that a modem communication protocol is used in order to communicate from/to arduino in order to communicate via USB?

linux questions belong at https://unix.stackexchange.com/questions , not here

@jsotola I disagree. While the answer is in the linux domain, the question in and of itself asks whether there is "some modem protocol" happening between PC and Arduino.

The answer to that is one of history.
There was a time when the main purpose of the serial port (RS-232/UART) was to "dial out"; i.e. it had a serial connection to a modem, fax machine or a mainframe attached. Whatever it was, the primary function was to provide a data connection to the outer world, possibly incurring charges on a phone line. So, it is the other way round than you guessed: The computer communicated with the modem using a serial protocol named RS-232 or UART.
Therefore, all serial ports have been secured to not allow access, except for the user group "dialout". This has been retained as default, even for emulated and virtual serial ports -- like, for example, serial port over USB.

So if I want my arduino to emulate a modem would the arduino's (Arduino UNO) typical out of the box USB communication be considered one that also modems use as well?

@DimitriosDesyllas Yes. A "serial connection" is basically just a bidirectional channel to send and receive bytes. What those bytes mean is up to the programs at either end and it is irrelevant whether this connection is a classic serial port, an emulated Serial-over-USB port or anything else. All your modem dialer program needs to know is "the modem is on serial port /dev/ttyS0". The dialer just sends a series of "AT commands" onto the serial line, waits for the modem to connect and acknowledge, then assumes that the same serial line is now connected through to its destination.


text:
Communication between two ESP32s using WiFi
I have two ESP32s. One is acting as webserver and the other is acting as a client that will send a GET request to the server ESP32. Both of the ESP32s are connected to the same WiFi AP.
For sending the request I need to know the server address, but I don't want to enter it into the code manually.
Is there any way with which I can figure out the IP address of the server ESP32 using the other ESP32?

Have a look into mDNS. I think there are already libraries for this on the ESP32

isn't that for esp32 and web browser?

What do you mean by that? mDNS is a way to give your device a name without having a dedicated DNS server. That way you can set the name of each device on the device itself. The client can then refer to this name of the device.

@chrisl In may case client is another esp32.

The other ESP32 also only does web requests, just like a webbrowser. mDNS just helps you to get the current IP address to the predefined name. Lets say Esp1 calls itself service1 and anounces that name through mDNS. Then Esp2 can ask mDNS for the IP address of service1 and then make a web request to that address. There should be examples and tutorials available online


text:
Is Arduino's USB communication protocol the same as USB modems use?
An Arduino Uno uses for the default USB communication either an FTDI chip in early versions or a microcontroller that emulates/replicates the FTDI chip communication.
Is this type of USB communications the same as the Conexxant CX930xx modems use as well?
What I want to achieve is to emulate the nessesary AT commands using the ATCommand library to replicate the modem's AT command instruction set. The things that I want to emulate are:

The modem USB communication
The subset of AT commands required for enabling/disabling an incomming call with Caller id
Returning a "fake" incoming call with or without CallerId depending on the provided options from the PC via the AT commands

For the last two I can somehow manage. But I don't know whether the existing FTDI chip/USB microcontroller uses the nessesary protocols that modems use as well. I mean would it be enough if I just replace the hardware and vendor ID or do I need to emulate another type of USB communication as well?
The modem that I want to emulate is the: https://support.lenovo.com/us/en/solutions/pd003647-lenovo-usb-modem-overview
What I want to achieve is to fake an incomming call instead of using the actual modem. The reason why is, because I want to provide my own data towards modem-interfacing desktop application that use CallerId. Instead of using the actual modem I would love to have a fake one where I can emulate various scenarios.

What modem are you talking about. They also make modems that are RS232 which would be a bit easier to interface with. I would suggest using a Mega because it has a second serial port, other boards will work as well. Try these links they may have something you may like: https://www.radi.com/modular29.htm or https://www.radi.com/modular51.htm

I am talinkg for this modem https://www.easytechnology.gr/plerophorike-kai-tablet/upologistes/diktuaka/exoteriko-usb-fax-modem-me-anagnorise-kleseon-oem It is a USB one and is used for CallerId applications. I want to emulate it and send to the PC fake incomming calls like a normal modem would do.

to the OS, the arduino looks like a serial port without a connected modem

Commonly USB modems use two layers of communication that are relevant for your issue.

A virtual serial communication device, known as CDC/ACM, Communication Device Class, and Abstract Control Model, respectively.

Modem control protocol, known as Hayes command set, vulgo "AT command set", on top of this.

Both layers are generally independent of each other. You can use the virtual serial communication for any other purpose. And you can transport the Hayes commands and replies over any other communication stream.
Most Arduino compatible devices reveal themselves as CDC/ACM to a PC, you can check this for example on Windows in the Hardware Manager. Therefore, the underlying transport layer exists for you.
But to answer your concrete question: No, the second layer (AT commands) is missing. It is not necessary for the upload process or the serial monitoring.
But you can write a sketch that implements that set of commands you would like use use for your application.

So I need to change the Vendor Id at Uno's Mega 16u2/8U2 and just make it to be seem as any modem I want to and via the sketch on MEGA 328p to emulate the AP command instruction set right;

In the comment above assume that I already have a sketch that emulates the hayes command set.

Yes, that should work. Does the PC application or the PC driver need this specific VID/PID to accept the device? CDC/ACM was meant to be VID/PID independent...

Well some applications that I need to use may require that (eg. during modem detection)


text:
How do you remove a number of characters from a parsed string?
Using this code - advertisedDevice.getServiceDataUUID().toString().c_str()); returns the following string -
0000feaa-0000-1000-8000-00805f9b34fb
How can I adjust the code to do that it omits the first nine characters leaving only -
0000-1000-8000-00805f9b34fb
Thank you.

not an arduino question ... it is a general programming question

Note: Even if this question is about general C++ programming, this might help other Arduino users, too. Better ask at StackOverflow the next time. ;-)
The result of your chain of method calls returns a pointer to non-writable chars. You can add any offset to this, in the range from 0 to the number of characters.
In your case:
const char* result = advertisedDevice.getServiceDataUUID().toString().c_str() + 9;


text:
LM7805 gets very hot with four servo motors
I'm making a robotic arm using three SG90s and one Futaba s3003 servo motors and an ESP32 dev_kit_V4.
The problem is when I am controlling the arm, the voltage regulator gets so hot that I can't touch it. After a minute or so the servos stop rotating and I have to restart the ESP32 to control the servos and the cylce continues.
I tried to connect the ESP32 to a power bank alone but the issue isn't solved. Can you help me?
The schematic for wiring:

Depending on load, your servos can draw 250ma of current or more when actuated. This means that your 7805 may need to supply >1 amp of current at 5V.
In order to get 5V from a 12V adapter the 7805 will need to drop 7V (The LM7805 is a linear regulator, essentially a variable resistor). 7V at 1 amp (peak) is 7 watts, which is what your regulator will dissipate during peak current draw.
With effective heat sinking your circuit will work. According to the datasheet, if you are running at room temperature with no heat sink you are limited to ~2.5 watts of dissipation.
If the 7805 chip temperature exceeds 150 degrees C it will go into thermal shutdown, which is probably what you're seeing.
Solutions would be to install an appropriate heat sink on the 7805, use a 7.5 volt power adapter (brings 7805 power dissipation down to ~2.5 watts), use multiple 7805 chips, or power everything with a 5V power adapter.

thanks , I will add a heatsink and see if it fixes the problem

I've added a heatsink and it works , thank you

Linear regulators especially the older ones like to go into oscillation at a relative high frequency. This may be load dependent.  The data sheet will recommend the appropriate capacitors to connect to it to prevent that. You would typically use a scope to see this. That oscillation will cause them to get hot rapidly even if they do not have a large load. You can look at the data sheet and determine the temperature rise of the die per watt of power. That you can determine by multiplying the drop across the regulator by the current. You can also apply this to heatsinks and pick one accordingly. There are conditions on this to be sure you have adequate ventilation to get rid of the heat on a air cooled heatsink. Liquid are similar but the numbers are much different.
In your case I would recommend you go to a switch mode regulator, commonly known as a buck or SEPIC regulator. The buck will drop the voltage from a higher voltage. The SEPIC does the same thing but if the input voltage goes below the output setpoint within its range it will boost the voltage keeping it at setpoint. As BobT explained the excess voltage is dropped through the regulator, it sort of acts like a variable resistor. This is dissipated as heat. The current on the input is about the same as the output. A switch mode regulator will operate in the efficiency range of maybe 80% - 95% efficiency, dissipating much less heat. They actually turn on and off very rapidly but the output is filtered so you do not see it.

I would recommend you to go with lm2596. That will solve your problem. Its output is adjustable. So set the output voltage first before connecting anything to it.

thanks for your reply,but I can't get it now because there is no electrical stores near to me


text:
Can I use this approach so I can sniff both TX and RX signals using a Second arduino?
Based upon this answer I can hook up 2 arduinos like this:

But AFAIK The main microcontroller uses an RS232 protocol and AtMegau16 (or ATMegau8) converts it into USB one emulating an FTDI chip.
But in my case, I need just the RX port from the second in order to just sniff data. So I looked on how I can pirate the RS232 signal and I found this schematic:

Resulting to this monstrocity:

But would this allow me the secoind UNO to capture both RX AND TX signals?

You only need the diode on the TX line, and you only need the resistor on the RX line.

You can try this, but your sniffer will only work satisfyingly if the communication protocol is half-duplex. This means, that TX and RX are never transmitting at the same time. If the protocol is full-duplex, and both wires transmit at the same time, their signals are mixed together, resulting in erroneous data. To tackle this situation, you need two serial receiver channels, one for TX and one for RX.

This approach may work in some cases but will not work in all cases.
Assuming the intent is to listen to both the transmit and the receive side of an RS232 type signal.
An RS232 signal may swing from -12 to +12 Volts.  Many logic inputs behave unexpectedly when driven by voltages higher than their supply rail.  A resistor may mitigate this problem.  A logic level shifter would be better.
The circuit diagram in the question is an example of a wired OR connection.  If either serial transmit line is high the data from the other will be blocked.  As illustrated in this diagram from wikipedia.org.

So this circuit diagram will only work reliably for half duplex communications.  If full duplex monitoring is required, two independent receivers / monitors will have to be used.


text:
AfMotor Shield Library does not work with template programming
I am able to move motors using AfMotor Shield Library. ( https://github.com/adafruit/Adafruit-Motor-Shield-library )
Like :
AF_DCMotor insertionMotor(1);
AF_DCMotor pumpMotor(2);

void setup()
{
  insertionMotor.setSpeed(255);
  pumpMotor.setSpeed(255);
  insertionMotor.run(RELEASE);
  pumpMotor.run(RELEASE);
  insertionMotor.run(FORWARD);
  pumpMotor.run(FORWARD);
}

But if I want to write it like this, only the motor with the template expansion that I called last works.
enum class direction {
  FRW = 0x01,
  BCKW,
};

template<int n, direction type>
class Motor : public AF_DCMotor {

public:

  Motor() : AF_DCMotor(n) {
    setSpeed(255);
    run(RELEASE);
    run(type);
  }
};
Motor<1, direction::FRW> fanMotor;
Motor<2, direction::FRW> pumpMotor;

Only the pumpmotor is running. Or if I call the fanMotor after the pumpMotor, it still works.If I remove pumpmotor and leave only fanMotor, the fanMotor also works. Is there something I overlooked?

Your code gives me a compiler error: in
run(type);

the run() method expects a uint8_t, but it is given a direction.
Adding an explicit cast to uint8_t makes it compile.
Now, as a general rule, I would advice you to never touch the hardware
in a constructor. The problem is, if you create a global object (like
you are doing here), the constructor gets called before main(), thus
before the Arduino core has had a chance to initialize the hardware. If
your constructor touches any hardware register, this may conflict with
the initialization the core is going to perform right at the start of
main().
The usual idiom for doing any hardware initialization is to define in
your object a method called begin(), and call it from setup():
template<int n, direction type>
class Motor : public AF_DCMotor {
public:
  Motor() : AF_DCMotor(n) {}

  void begin() {
    setSpeed(255);
    run(RELEASE);
    run((uint8_t) type);
  }
};

Yes you should do casting. (static_cast maybe more suitable). But it is not related about my problem.
Also with these lines, the constructor gets called before main()
AF_DCMotor insertionMotor(1);
AF_DCMotor pumpMotor(2);


text:
What components can be connected to pins 0/1 (RX/TX) without preventing uploading of code?
For a robot project I am using an Arduino Uno, and am running out of pins. The simplest solution would be to use digital pins 0/1. I know this means that I won't be able to use Serial communication (which is fine), but I also know that these pins are also used when uploading code to the board, and connecting components to these pins can interfere with the upload.
Are there certain types of components/interfaces that can be connected to these pins that won't interfere with the upload (without having to disconnect them every time I want to upload)?
In my case, I can choose between either using these pins to drive inputs for an L298N motor driver (TTL inputs), or to read quadrature motor encoder signals. My guess would be that the latter won't work, as these signals may be high and interfere (and I don't know whether applying a voltage to the encoder outputs would cause damage - I have no datasheets for them).
However maybe the TTL inputs of the L298N would be fine? Or do I have no choice but to either have a switch to disconnect the when uploading or find some other way to reduce pin usage (or go for a bigger Arduino)?

a two position dip switch or four header pins with two jumpers ... https://duckduckgo.com/?q=dip+switch&iax=images&ia=images

This is a general electronic problem, not specific to pins 0/1 of the Arduino.
The basic rule is:

An input can only accept one signal

But

One signal can go to many inputs

In other words any INPUT pin can only accept a signal from one place, but an OUTPUT pin can send its signal to many places at once.
The Arduino's serial connection has two signals - one input (RX) and one output (TX).  The input pin (RX) can only get its signal from one place, and when programming that "one place" needs to be the USB to UART converter's TX pin.  So anything connected to that pin that "sends a signal" will confuse everything and communication will fail.
Similarly the USB to UART converter's RX pin can only receive a signal from one place - in this case the Arduino's TX pin - connecting anything to this pin that could output a signal would confuse things and break communication.
So to round that up: you should be fine connecting anything that only receives a signal of some form (i.e., anything that is an INPUT, such as an RX pin or some form of control input like your motor controller) to either of those pins, but do not connect anything that can send a signal.
There is one caveat though: whatever you connect will receive the serial communication used while programming. That could have unintended consequences, like a motor spinning when you program the board.

Thanks, this is largely what thought. However, I would assume that some inputs may cause loading on the pin that would interfere? Such as an input with a pull up/down resistor will hold the voltage at a certain level, preventing correct operation?

And unwanted inputs to the motor drivers should be fine - when programming I wouldn't have the motors powered, and even they were these inputs would only be the direction controls - the pwm input should still be 0.

@Rustony The idea of a pullup or pulldown resistor is to provide a steady state when no logic signal is being applied. Any logic signal (such as the serial communication from the PC) should happily override a pullup or pulldown resistor.


text:
Multiply char with float
I have a value for led brightness that is stored as an unsigned char (0-255)
unsigned char* colors[3];
colors[0] = 255;
colors[1] = 0;
colors[2] = 0;

I want to multiply a brightness percentage to that value.
float percent = 0.5;
auto red_brightness = colors[0] * percent

Since colors[0] is of type char and percent is of type float. It gives error Invalid operands of types 'unsigned char*' and 'float' to binary 'operator*'
unsigned char brightness;
float percent;
unsigned char* colors[3];

void setup() {
  Serial.begin(9600);
  colors[0] = 255;
  colors[1] = 0;
  colors[2] = 0;
}

void loop() {
    brightness = 127;
    float percent = (float)brightness / 255;
    float newRed = (float)colors[0] * percent;

    Serial.println(percent);
    Serial.print("red ");
    Serial.print(newRed);
    Serial.println("");
    delay(1000);
}

How can I multiply colors[0] (255) by 0.5 to get 127?

What I've tried

Cast colors[0] to a float or int

    # invalid cast from type 'unsigned char' to type 'float'

    float newRed = (float)colors[0] * percent;

strtod

Using this conversion website, I've tried converting like so:
    float tempColor = (float)strtod(colors[0],NULL);
    float newRed = tempColor * percent;

While this compiles, it always returns 0 (not 127 like I expect)
unsigned char brightness;
float percent;
unsigned char* colors[3];

void setup() {
  Serial.begin(9600);
  colors[0] = 255;
}

void loop() {
    brightness = 127;
    float percent = (float)brightness / 255;
    float tempColor = (float)strtod(colors[0],NULL); // <- returns 0.00

    Serial.print("tempColor");
    Serial.println(tempColor);
    delay(1000);
}

How can I multiply 255 by 0.5 to get ~127 ?

Solution
Thanks to the pointer by st2000 and this sparkfun article on datatypes
I avoided floating point and char arrays and converted everything to byte and now my code works as expected. Thank you
byte brightness;
byte percent;
byte colors[3];

void setup() {
  Serial.begin(9600);
  colors[0] = 255;
}
void loop() {
      percent = 50;
      auto foobar = colors[0] * percent / 100;
      Serial.print("foobar: ");
      Serial.println(foobar);

11:12:19.833 -> foobar: 127

Using "floats" is expensive both in required space and execution time.  Consider avoiding the problem entirely and use uint8_t or byte for everything.
Then just assume
percent = 50;

... is 50%.  Then try:
tempColor =  colors[0] * percent / 100;

... where all variables are of type uint8_t or byte.

@spuder, please follow  up to let us know if the above code suggestion works.  I think C uses type int for intermediate values in which case the worst expected case (255*100) should not exceed the limits of a type int variable.  Otherwise casting one of the variables to a type uint16_t would likely make the code more portable / less likely to break.

You wrote:

I have an led brightness that is stored as an unsigned char (0-255)
unsigned char* colors[3];

This is not an array of unsigned char, this is an array of
pointers to unsigned char. If you instead write
unsigned char colors[3];

Everything should work as expected.
But then, st2000 has very good advice on how to avoid expensive floating
point operations.

Oooo, good catch @edgar!


text:
ESP32, ArduinoOTA.h LittleFS.h and data file upload OTA
I'm having a sketch, that works perfectly fine - connects to WiFi, uploading files using Esp32 LittleFS data Upload using Arduino IDE (when still connected to my PC), and sketch updates  via OTA (using ArduinoOTA.h library).
But when I try to Esp32 LittleFS data Upload when MCU is not connected to my PC, I get an error messages:
espota : /home/guy/snap/arduino/70/.arduino15/packages/esp32/hardware/esp32/1.0.6/tools/espota.py

[LITTLEFS] data   : /home/guy/Documents/Dropbox/Arduino/sketch_jul26a/data
[LITTLEFS] start  : 2686976
[LITTLEFS] size   : 1472
[LITTLEFS] page   : 256
[LITTLEFS] block  : 4096
/sketch_param.json
/sketch_param_32.json
/myIOT2_topics.json
/myIOT_param.json
/sketch_param_8266.json
[LITTLEFS] upload : /tmp/arduino_build_103180/sketch_jul26a.littlefs.bin
[LITTLEFS] IP     : 192.168.2.132

Sending invitation to 192.168.2.132 ..........
20:10:59 [ERROR]: No response from the ESP
LITTLEFS Upload failed!

Just to clarify:
A) sketch OTA works as expected (yes, I changed local USB to the remote one).
B) Tested on 2 different ESP32 MCU's, and failure is the same.
Question:

Is it possible to OTA data files using ESP32, ArduinoOTA.h, LittleFS, ArduinoIDE ? (It works when using ESP8266).

Guy

I can confirm that I've uploaded littlefs data to an ESP32 over OTA using PlatformIO. I haven't tried with ArduinoIDE but it should be possible. Have you tried uploading while monitoring the serial output (i.e. leave it connected to the PC). If you see something in the output, it might be format error coming from the ArduinoIDE upload tool, but I suspect it's just failing to connect.
Is it definitely connecting with the same IP between sketch upload and file upload? When I have these types of problems, it's usually because I've done something in the sketch to disable WiFi or the OTA check. Have you tried uploading the sketch again over OTA?

Uploading sketch, as mentioned, works flawlessly. And entire procedure on ESP8266 works both sketch and data files (sketch fits both MCUs).


text:
Arduino alternating between high and low signal without button press
I have connected my LCD with arduino uno. I am controlling contrast with the library and not the potentiometer. I am trying to read input from the button, it is connected to pin 9 of arduino. The resistor in the image is grounded, now arduino is not sensing signal from the button it keeps printing this even though in the timestamp below I have not touched the button. The resistor is 1k ohm.
20:03:30.808 -> button not pressed
20:03:31.816 -> button pressed
20:03:32.798 -> button pressed
20:03:33.827 -> button not pressed
20:03:34.821 -> button pressed
20:03:35.849 -> button not pressed
20:03:36.847 -> button not pressed
20:03:37.842 -> button pressed

#include <LiquidCrystal.h>

const int buttonNumPad1 = 9;

int buttonNumPad1State = 0;

int Contrast = 127.5;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{
  Serial.begin(9600);
  pinMode(buttonNumPad1State, INPUT);
  analogWrite(6, Contrast);
  lcd.begin(16, 2);
}
void loop()
{
  buttonNumPad1State = digitalRead(buttonNumPad1);

  if (buttonNumPad1State == HIGH){
    Serial.println("button pressed");
    lcd.setCursor(0, 1);
    lcd.print("pressed");
  } else {
    Serial.println("button not pressed");
  }

  lcd.setCursor(0, 0);
  lcd.print("Hello");

  delay(1000);

  lcd.clear();
}

Top view of my breadboard

is it something related to? https://docs.arduino.cc/learn/microcontrollers/digital-pins

Input pins make extremely small demands on the circuit that they are sampling, equivalent to a series resistor of 100 megohm in front of the pin. This means that it takes very little current to move the input pin from one state to another

is it a breadboard with the power rails separated in the middle?

@Juraj yes it is a breadborad with power rails separated in the middle

Then have you connected these two parts of the power rail? The described behavior suggests that you have a floating input pin. Maybe the resistor isn't actually grounded

@chrisl do you want me to connect both power rails? I uploaded a top view of my breadboard(note the lcd is just kept on the breadboard and it is not connected)

@chrisl also which parts of the rails are you talking about

What Juraj meant with "separated in the middle" was, that in your top view of the bread board the power rails are separated not only between top and bottom of the image, but also between left and right. Then you would need a connection at the middle, connecting the left part of the row with the right part. Or you could try to put the button and its connections also on the left side of the board.

@chrisl do you mean something like that(added a picture in the question)

I tried this and then also this https://imgur.com/a/JRLFEMt but still it arduino sends random high low values

Regarding the rail test, they're more or less asking you to do this. Either those two points will test as continuity (or near-0 ohms) or it will be open.

Look at this breadboard image:

I have marked the power rail connections with green and red lines. Do you see, that they are not connected in the middle, right there where I've drawn the blue dotted line. Often the power rails of breadboards are not connected internally at that place. If that is the case for your breadboard you would need to bridge that gap with some jumper wires.
If you don't do that, your button and pulldown resistor are not connected to anything but the digital input pin. So there is nothing setting the state of that pin (HIGH or LOW). Its just like you simply connected a wire to the digital input pin. And that's called a floating pin. It is not actively pulled in one direction, so any noise, that comes by, might change the state of the input pin.
Make sure your button and pulldown resistor are actually electrically connected to ground. Bridge any gaps in the power rails, that your breadboard might have.


text:
Convert Int to HEX, HEX to string and to byte? General converting problem
Since Cpp is not my main language, I struggle to find the best way to convert between types for my needs.
So my starting point is
struct can_frame {
    canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
    __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};

So first I needed it bo send to Serial as a hex string, so solution I've found and used was
String frame = "CAN:";
char dataString[1] = {0};
sprintf(dataString, "%03X", can1Msg.can_id);
frame += dataString;
for (int i = 0; i < can1Msg.can_dlc; i++) {  // print the data
  char dataString[1] = {0};
  sprintf(dataString, "%02X", can1Msg.data[i]);
  frame += " " + String(dataString);
}

Doesn't seem elegant byt it did the job.
But then I needed to do some checking of ID and specific bytes
So I've saved all String ins String bytes[8]
So  now I could something like
if (id == "2A0" && bytes[0] == "A0") {

And that was almost over, but then I realized that I need to do some checking of Integer number that is saved on 3 bytes.
E.G byte[2] + byte[3] + byte[4] which would something like 0020A0 whih will be 8352 as an Int
But converting things around gave all the problems such us String to const char* etc.
I wanted to convert __u8 to byte array so I can do checks and conversions and eventually convert it to string, but I've failed.
Can anyone suggest best approach for this ?

Note that you are overflowing the 1-cell arrays dataString. This is probably corrupting some of your memory.

The main problem that you are having is a lack of understanding in what "hex", "byte", etc are.
You are trying to work with four data types (int, hex, string and byte) when in reality there are only two types: String and binary. Everything else is just a representation we as humans use to make easier sense of the binary data.
You have a "source" type (can1Msg.data) which is, at one and the same time, binary, integer, hex and byte. The only thing it is not is String and you create that manually with your sprintf calls.
To compare the third "hex pair" value in your data you simply:
if (can1Msg.data[2] == 0x42) { ...

That is, compare the 8-bit binary value stored in array slice 2 (arrays count from 0 so 2 is the third entry) with the binary value represented by the hex notation 42.  The exact same thing can be done with:
if (can1Msg.data[2] == 66) { ...

66 is the decimal (base 10) equivalent of 0x42.  You can also use binary or octal. These two are also exactly the same:
if (can1Msg.data[2] == 0102) { ... // octal
if (can1Msg.data[2] == 0b01000010) { ... // binary

If you need to examine groups of bytes, such as if you have two bytes that form a 16-bit integer, you simply combine those two bytes into an integer, taking care to obey the correct endianness of the values.  For example if you have a 16 bit integer that is stored as can1Msg.data[7] and can1Msg.data[8] in big endian form, you can use:
uint16_t val = (can1Msg.data[7] << 8) | can1Msg.data[8];

Then simply compare the numeric (binary) integer value at will.  All that line does is take the first 8 bit value and "shift" it 8 bits to the left to make it a 16 bit value with the lower 8 bits set to 0, then overlay the second value over those lower 8 zeroes, to make it a single 16-bit value.

Thank you very much. My mistake was that for some reason I assumed that what I have in data is not a byte and it got stuck in my head that I need to convert it to byte.


text:
boards.txt - how to create sub-menu (NOT new board!!!)
Arduino 1.8.19
Is it possible to create a sub-menu inside boards.txt that would allow having the boards grouped for example by the manufacturer?
If it is possible, please provide an example or at least documentation for the language which is used for boards.txt.
I don't want to add a new board.

No, it's not possible.
The board menu (defined here) is a single flat menu with "scroller" added to it.
To have multiple layers of menu you'd have to rewrite that entire part of the IDE.

Thank you very much, this is truly a great answer!


text:
displaying double variable problem (Arduino)
so I have a problem with displaying a double variable in OLED & IR remote calculator, like this (using u8g2):
displayTextOnRight(String(100000, 0)); //ex. of an void and a number

It displays: " "
But when I set to ex. 99999 it displays: "99999"
The same is with
displayTextOnRight(String(1000.00, 2));

It also displays nothing. (100.00 displays 100.00)
I tried values below zero and it crashes. When I try 6 it's empty whatever I type on my remote.
Please help.

What's this "displayTextOnRight()" function? What code are you using? Where did you get it? What is it supposed to do?

When the first argument to the String constructor is an integer type, it tries to interpret the second argument as a number base and not as a number of decimal places.
So, in String(100000, 0));, it kind of thinks you're asking for the number to represented in the String in base 0 as opposed to decimal (DEC), hexadecimal (HEX), binary (BIN), etc and base 0 isn't a thing.
With a floating point type first argument like 1000.0 the second argument takes on the meaning of decimal places (seen an decimalPlaces in the documentation).
If you want ".00" after an integer number when it's converted to a String it's probably better to just print it in a second .print() call, or to concatenate it to the string. And if you want you can manually type convert integer expressions to floating point type to force selection of the other constructor, e.g. int a = 10000; whatever.print(String(float(a), 2));


text:
Connect Arduino + ESP8266 to Azure IoT Hub Device via X509 certificate
I would like to connect ESP8266 with Azure IoT Hub Device via X509 certificate. Currently, I can connect using the symmetric key connection to my device, but I have devices that I want to authenticate with X509 certificate.
I found a solution, but is for Arduino Nano 33 IoT, which is probably using another chip and it has encryption slot.
I am trying to do this using the Azure IoT SDK C library, but without much success. Here is a code that is using Mqtt and WiFiClientSecure plus BearSSL in order to connect via certificate. Unfortunately, the only solution that I found was to generate ECCX09 certificate with a chip that have encryption and to just use the thumbprint. Here is my try to use the certificate:
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT

// C99 libraries
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <cstdlib>

// Libraries for MQTT client, WiFi connection and SAS-token generation.
#include <ESP8266WiFi.h>
#include <ArduinoBearSSL.h>
#include <ArduinoMqttClient.h>

// Additional sample headers
#include "secrets.h"

// Utility macros and defines
#define LED_PIN 2

// Translate iot_configs.h defines into variables used by the sample
static const char* ssid = SECRET_WIFI_SSID;
static const char* password = SECRET_WIFI_PASS;
static const char* host = SECRET_BROKER;
static const String device_id = SECRET_DEVICE_ID;

// Memory allocated for the sample's variables and structures.
static WiFiClientSecure wifi_client;
static BearSSLClient ssl_client(wifi_client);
static MqttClient mqtt_client(ssl_client);

// Auxiliary functions
static void connectToWiFi()
{
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to WIFI SSID ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.print("WiFi connected, IP address: ");
  Serial.println(WiFi.localIP());
}

/*
 * Establishses connection with the MQTT Broker (IoT Hub)
 * Some errors you may receive:
 * -- (-.2) Either a connectivity error or an error in the url of the broker
 * -- (-.5) Check credentials - has the SAS Token expired? Do you have the right connection string copied into arduino_secrets?
 */
void connectToMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(host);
  Serial.println(" ");

  while (!mqtt_client.connect(host, 8883)) {
  // failed, retry
    Serial.print(".");
    Serial.println(mqtt_client.connectError());
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  mqtt_client.subscribe("devices/" + device_id + "/messages/devicebound/#");
}

unsigned long getTime() {
  // get the current time from the WiFi module
  // return WiFi.getTime();
  return time(NULL);
}

static void establishConnection()
{
  // Set the username to "<broker>/<device id>/?api-version=2018-06-30"
  String username;

  // Set the client id used for MQTT as the device id
  mqtt_client.setId(device_id);

  username += host;
  username += "/";
  username += device_id;
  username += "/api-version=2018-06-30";
  mqtt_client.setUsernamePassword(username, "");

  if(WiFi.status() != WL_CONNECTED) {
    connectToWiFi();
  }

  if (!mqtt_client.connected()) {
    // MQTT client is disconnected, connect
    connectToMQTT();
  }
}

// Arduino setup and loop main functions.

void setup()
{
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

  Serial.begin(9600);

  // Set the X.509 certificate
  // ssl_client.setEccCert(CLIENT_CERT);
  ssl_client.setEccSlot(0, CLIENT_CERT);

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);

  establishConnection();
}

void loop() {}

This fails on setting the Certificate and to use the ecc slot 0, because I am using ESP8266 that does not have cryptography in it (or at least I do not know). I saw in the library that there is another method in the BearSSL - void setEccCert(br_x509_certificate cert); , but I do not know how to initialize br_x509_certificate (here is the ref).
I decided to try something else, too, reading the certificate with SPIFFS, then adding to WiFiClientSecure. Unfortunately, I cannot load the private key to make client connection.
#include "FS.h"             // File system commands to access files stored on flash memory
#include <ESP8266WiFi.h>    // WiFi Client to connect to the internet
#include <PubSubClient.h>   // MQTT Client to connect to AWS IoT Core
#include <NTPClient.h>      // Network Time Protocol Client, used to validate certificates
#include <WiFiUdp.h>        // UDP to communicate with the NTP server
#include "secrets.h"

// Utility macros and defines
#define NTP_SERVERS "pool.ntp.org", "time.nist.gov"

// Translate secrets.h defines into variables used by the sample
static const char* ssid = SECRET_WIFI_SSID;
static const char* password = SECRET_WIFI_PASS;
static const char* iot_hub_broker = SECRET_BROKER;

// callback function that will be called when the device receive a message
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

// Memory allocated client variables
static WiFiUDP ntp_UDP;
static NTPClient time_client(ntp_UDP, "pool.ntp.org");
static WiFiClientSecure esp_client;
static PubSubClient mqtt_client(iot_hub_broker, 8883, callback, esp_client);

// Auxiliary functions
static void configureX509CertificateConnection() {
  time_client.begin();
  while(!time_client.update()) {
    time_client.forceUpdate();
  }

  esp_client.setX509Time(time_client.getEpochTime());
  Serial.println("Time client and ESP client are set up.");

  // Attempt to mount the file system
  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount file system");
    return;
  }

  // Load certificate file from file system
  File cert = SPIFFS.open("temperature-sensor-1-all.pem", "r");
  if (!cert) {
    Serial.println("Failed to open certificate from file system");
  } else {
    Serial.println("Successfully opened certificate file");
  }

  // Load private key file from file system
  File private_key = SPIFFS.open("/temperature-sensor-1-private.pem", "r");
  if (!private_key) {
    Serial.println("Failed to open private key from file system");
  }
  else {
    Serial.println("Successfully opened private key file");
  }

  delay(1000);

  // Load private key to client connection
  if (esp_client.loadPrivateKey(private_key)) {
    Serial.println("Private key loaded to client connection");
  }
  else {
    Serial.println("Private key not loaded to client connection");
  }
}

static void connectToWiFi() {
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to WiFi: ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("WiFi connected, IP address: ");
  Serial.println(WiFi.localIP());
}

/*
 * Establishses connection with the MQTT Broker (IoT Hub)
 * Some errors you may receive:
 * -- (-.2) Either a connectivity error or an error in the url of the broker
 * -- (-.5) Check credentials - has the SAS Token expired? Do you have the right connection string copied into arduino_secrets?
 */
void connectToMQTT() {
}

static void establishConnection() {
  if (WiFi.status() != WL_CONNECTED) {
    connectToWiFi();
  }

  configureX509CertificateConnection();
}

// Arduino setup and loop main functions.
void setup() {
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  Serial.begin(115200);

  establishConnection();
}

void loop() {}

P.S. I have it up and running on Raspberry Pi, but I have to make some experiments using the Arduino and ESP8266.
P.S.2. I am using Arduino with Atmega328P with integrated ESP8266 chip, but working only with the ESP8266. Additionally, I am using Arduino IDE 1.8.19 and installed the Azure IoT SDK C library (and some other required ones).
P.S.3. Additionally, I could find X509 certificate sample, but it is using the Paho Mqtt Client and I am not able reproduce it on Arduino.


text:
PSF WiFi module - Is it similar to ESP8266
Some products (as TUYA and SONOFF) are using a PSF wifi module. In this link, PSF-B04 is reffers as ESP8285 design.
does anyone flash a sketch to such chip ? should it be reffered as ESP8285 when selecting chip type in Arduino IDE ?
Guy

This is actually an ESP8285 (not 8265) design, which is a version of the ESP8266 with integrated 1MB or 2MB Flash memory. From a programming perspective, aside from the memory size, it's identical to the ESP8266. The ESP8266 Arduino Core also supports this chip.

@StarCat That was a typo, thank you. So chip wise, I can upload sketch as any other esp8266 (without any change is MCU type at Arduino IDE ) ?

Did you look in the boards menu for the esp8266 support package?

@timemage what do you mean? I saw pics of a Tuya unit, and I want to know if my code can be uploaded to it (as any other ESP8266)

ESP8285 is supported by esp8266 Arduino. You can select it in Tools menu.


text:
Cannot upload sketch to DFRduino nano
I previously succeed in uploading the code to DFRDuino Nano (Arduino Nano Compatible) (with wrong digital pins) but after changing pin I cannot upload it again.
From the document, I changed back the pins 0 (RX) and 1 (TX) are used for serial communication.
In arduino ide (1.8.19), I choosed board: Arduino Nano and Processor: ATmega328P(Old Bootloader)
The error:
. . .

avrdude: Version 6.3-20190619

        Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

        Copyright (c) 2007-2014 Joerg Wunsch

        System wide configuration file is "C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.57.0_x86__mdqgnx93n4wtt\hardware\tools\avr/etc/avrdude.conf"

        Using Port                    : COM3

        Using Programmer              : arduino

        Overriding Baud Rate          : 57600

avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00

avrdude done.  Thank you.

An error occurred while uploading the sketch

I have reset both the board and computer but without luck. I changed another board and got the same error.
Any idea how to solve it?
UPDATE:
I uploaded the empty code to reset the board but it yielded the same error.

What do you mean by "uploading with wrong digital pins" and with "changed back the pins 0 (RX) and 1 (TX)"? On the Nano you cannot choose the pins of the Hardware Serial interface. They are literally hardwired

@chrisl I mean at first I used other digital pins for serial communication (d11 d12) using SerialSoftware and did not notice that d0 d1 are hardwired and used for serial com.

What you are doing with SoftwareSerial in your sketch doesn't matter for the bootloader (which is handling the upload). Have you tried resetting the board right after you clicked on upload? It might take some tries to get the timimg right

Assuming "I changed another board and got the same error." means that you tried with another Arduino. Then the problem is on your PC. Did you select the right board and port?

@thebusybee I changed other DFRduino. I selected Arduino Nano and right COM since it was the only one)

Does the Hardware Manager show the DFRDuino? Did you double-check any connection, and that the correct Nano (there are several of them) is selected as the linked page suggests?

@thebusybee I cannot see any DFRDuino from Boards Manager. From the document (above) in programming section, it states The DFRduino Nano can be programmed with the DFRduino software (download)...Nano w/ ATmega328P(Old Bootloader)" from the Tools > Board menu

I did not mean the Board Manager in the IDE. I meant the Hardware Manager of your PC, presumed that you use Windows (any other reasonable OS will have something similar).

@thebusybee it does not show any DfRDuino at all

Then you need to debug the USB connection. Try other USB devices, other Arduinos, other USB cables, other USB ports, ...


text:
ESP8266 TIMEOUT: 428
this is the code I used:
#include <Wire.h>
#include "WiFiEsp.h"
// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(18, 19); // RX, TX
#endif

char ssid[] = "Vodafone-A61356555";            // your network SSID (name)
char pass[] = "xxxx";        // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status
int reqCount = 0;                // number of requests received

WiFiEspServer server(80);

int MPU = 0x69;
int MPU1 = 0x69;
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
int16_t AcX1, AcY1, AcZ1, Tmp1, GyX1, GyY1, GyZ1;
int gyro_state = 2;
int gyro_state_1 = 3;
int RED_LED = 8;
int GREEN_LED = 9;

void setup(){
  pinMode(gyro_state, OUTPUT);
  pinMode(gyro_state_1, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  digitalWrite(gyro_state, HIGH);
  digitalWrite(gyro_state_1, HIGH);
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(115200);
  // initialize serial for ESP module
  Serial1.begin(9600);
  // initialize ESP module
  WiFi.init(&Serial1);

  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true);
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  Serial.println("You're connected to the network");
  printWifiStatus();

  // start the web server on port 80
  server.begin();
}

void loop(){
  // listen for incoming clients
  WiFiEspClient client = server.available();
  if (client) {
    Serial.println("New client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          Serial.println("Sending response");

          // send a standard http response header
          // use \r\n instead of many println statements to speedup data send
          client.print(
            "HTTP/1.1 200 OK\r\n"
            "Content-Type: text/html\r\n"
            "Connection: close\r\n"  // the connection will be closed after completion of the response
            "\r\n");
          client.print("<!DOCTYPE HTML>\r\n");
          client.print("\r\n");
          client.print("
\r\n");
          client.print("Accelerometro X: ");
          client.print(AcX);
          client.print("
\r\n");
          client.print("\r\n");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(10);

    // close the connection:
    client.stop();
    Serial.println("Client disconnected");
  }
  digitalWrite(gyro_state, HIGH);
  digitalWrite(gyro_state_1, LOW);

  do{
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 14, true);       // request a total of 14 registers
    AcX = Wire.read() << 8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY = Wire.read() << 8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ = Wire.read() << 8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp = Wire.read() << 8 | Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX = Wire.read() << 8 | Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY = Wire.read() << 8 | Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ = Wire.read() << 8 | Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

    Tmp = Tmp / 340 + 36.53;

    digitalWrite(gyro_state_1, HIGH);
    digitalWrite(gyro_state, LOW);
    delay(1000);

  }while(digitalRead(gyro_state)== HIGH);

  do{
    Wire.beginTransmission(MPU1);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU1, 14, true);       // request a total of 14 registers
    AcX1 = Wire.read() << 8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY1 = Wire.read() << 8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ1 = Wire.read() << 8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp1 = Wire.read() << 8 | Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX1 = Wire.read() << 8 | Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY1 = Wire.read() << 8 | Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ1 = Wire.read() << 8 | Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

    Tmp1 = Tmp1 / 340 + 36.53;

    digitalWrite(gyro_state, HIGH);
    digitalWrite(gyro_state_1, LOW);
    delay(1000);

  }while(digitalRead(gyro_state_1) == HIGH);
}

void printWifiStatus()
{
  // print the SSID of the network you're attached to
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print where to go in the browser
  Serial.println();
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
  Serial.println();
}

This is what I see in the serial monitor with a baud of 115200:
[WiFiEsp] Initializing ESP module
[WiFiEsp] Initilization successful - 1.5.4
Attempting to connect to WPA SSID: Vodafone-A61356555
[WiFiEsp] Connected to Vodafone-A61356555
You're connected to the network
SSID: Vodafone-A61356555
IP Address: 192.168.1.30

To see this page in action, open a browser to http://192.168.1.30

[WiFiEsp] Server started on port 80
[WiFiEsp] New client 0
New client
GET / HTTP/1.1
Host[WiFiEsp] TIMEOUT: 428
Client disconnected
[WiFiEsp] New client 0
New client
GET / HTTP/1.1
Host[WiFiEsp] TIMEOUT: 428
Client disconnected

please add a this is my question section to your post

it is a known problem of the WiFiEsp library which is not maintained anymore. if you can update the AT firmware,, you can use my WiFiEspAT library

I tried to change the library but it tells me to change WiFiEspServer to WiFiServer and for WiFiEspClient it tells me Compilation error: 'WiFiEspClient' was not declared in this scope

of course. it is a different library


text:
Share interrupt service between class
I would like to share interrupt routine between class. I followed this tutorial.
But I need to call a member function in callback function, I have the issue :

This is my code :
Timer.h
static void (*__handleISR)(void);

class Timer
{
    public:
        Timer();
        ~Timer();
        static void init();
        static void handleISR(void (*function)(void));
};

Timer.cpp
Timer::Timer()
{
}

Timer::~Timer()
{}

void Timer::init()
{
    TCCR2A = 0; //default
    TIMSK2 = 0b00000001; // TOIE2
}

ISR (TIMER2_OVF_vect)
{
    // 256-6=250 --> (250 x 16uS = 4mS)
    // Recharge le timer pour que la prochaine interruption se declenche dans 4mS
    TCNT2 = 6;

    __handleISR();
}

Device.h
class Device
{
    public:
        Device();

    private:
        void isr();
};

Device.cpp
Device::Device()
{
    Timer::init();
    Timer::handleISR(isr);
}

void Device::isr()
{
    // Do my stuff
}

If I set function isr() static, it works. But I need to call member from Device in isr().
How I can call non static member function ? Or another solution ?

Do none of these results help you? https://arduino.stackexchange.com/search?q=invalid+use+non+static+member

nop the solution is with static member

This is not an Arduino specific question but a C++ question, and as such you might get more or better answers on StackOverflow. Anyway, I'll suggest a possible solution.
A member method always receives a pointer to its object as a hidden first argument that we know as this. Only via this argument such a method is able to access member attributes or member methods.
A class method does not have this parameter.
The function type you define is compatible only to functions or class methods.
So you need to provide a pointer (or reference) to the Device object.
I reduced your example and replaced the interrupt macro with something a standard C++ compiler accepts, as this is not part of the issue.
Timer.h
#ifndef TIMER_H
#define TIMER_H

#include "Device.h"

class Timer
{
    public:
        static void setCallback(void (*function)(Device*), Device*);
};

#endif

Timer.cpp
#include "Timer.h"

#define ISR(f) void f()

static void (*_function)(Device*);
static Device* _device;

void Timer::setCallback(void (*function)(Device*), Device* device)
{
    _function = function;
    _device = device;
}

ISR(TIMER2_OVF_vect)
{
    _function(_device);
}

Device.h
#ifndef DEVICE_H
#define DEVICE_H

class Device
{
    public:
        Device();

    private:
        static void isr(Device* device);
        void isr();
};

#endif

Device.cpp
#include "Device.h"
#include "Timer.h"

Device::Device()
{
    Timer::setCallback(isr, this);
}

void Device::isr(Device* device)
{
    device->isr();
}

void Device::isr()
{
    // Do my stuff
}

If you don't need the Device object, you don't need a member method. Then go with a class method, as you already found out.

it works, thank you very much :)


text:
String() vs char for simple flow control
I am newbie in Arduino and writing a program where I want to control the flow by using Serial monitor input (PI controller).
I've read that using String() although easier it is slower than using char. But to use char I would need more lines of code to convert the input into a string for comparison and more knowledge to make the program robust. For the control I will enter small strings like Ramp, Increase, Decrease, Lock, Stop and any other inputs will not be used. Generally, there are not going to be much inputs. The strings are basically going to be put into if-statements leading to functions.
if(Serial.available()){

string = Serial.readString()
or some function to read out all the bytes of the string and return a char containing it;

if(string="Ramp") {
do_this();
}
else_if(string="Increase"){
do_that()
}
//If nothing matches, continue with code.
}

Since I need to finish this project soon, I am wondering if it's going to increase the loop time significantly if I use String() or I shouldn't bother learning and using char right now (at a later stage, for sure).

Ramp, Increase, Decrease, Lock, Stop  can be represented by single byte commands r, i, d, l, s

Yes, String has a bit more overhead than plain c-strings (aka char arrays), though the additional execution time will be way too small for you to notice (especially when you type the commands in by hand).
It will be no problem to use String in your sketch, though you should do it right and use String.reserve() to allocate enough memory space in the String object to hold the longest string, that you have. Also don't just add Strings together. That way you can avoid memory fragmentation (effectively making swiss cheese out of your RAM) and still use String.
Though when you are not in a hurry anymore, learning how to use c-strings will be worthwhile.

And what happens if I use char or byte and send command longer then expected? The rest of the bytes stay in the serial buffer and then on further read I get wrong command or it empties out the buffer once it fills?

What happens then depends on your programming. A common way is to end the string and throw away the rest of the incoming data for this message. That way you can recover from that. Though you have a limited list of commands, so there is a maximal length of commands for you

Using Serial.readString() will make your program very slow. This is
because readString() does not know when to stop reading. When the
serial input buffer gets empty, it will wait just in case more
characters may come later. Only when it times out does it return the
string that it could read. The default timeout is one second, so your
program will be unresponsive for a full second after receiving a command
and before acting on it.
You can shorten the timeout using Serial.setTimeout(), but this may
make your program harder to test interactively by typing commands on a
terminal emulator.
I recommend you add a terminating character (say, '\n') to each of
your messages, then replace Serial.readString() with
Serial.readStringUntil(). This method will return immediately when it
finds the terminating character. Note that this character will not
appear on the returned string object. readStringUntil() also obeys a
timeout, but only when it cannot find the terminating character.
Or you can learn the clean way to read Serial on the Arduino.
Yes, it is a bit harder, but not a horrible thing to do.


text:
Char Array in PreProcessor
I need to define an array, that later on will be the name of a class, and will be pointed to.
For example (in a non pre-processor way):
const char *button_names[4]={"b0","b1","b2","b3"};
and later on (when it will be define in pre-processor), in a function it will be called as :
static Button2 button_names[i]
How can I define it that array to be in pre-processor?
Edit2:
Button2 *Buttons[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; // Here I use an optional up to 8 Buttons.

and later on, after I read parameter file: i get the numSW
/* Below example is only to check if I can use such technique - I know it is not a good coding. Example here is only for up to 4 Buttons*/
void init_buttons()
{
        for (uint8_t i = 0; i < numSW; i++)
        {
                if (i == 0)
                {
                        static Button2 bt1;
                        Buttons[i] = &bt1;
                }
                else if (i == 1)
                {
                        static Button2 bt2;
                        Buttons[i] = &bt2;
                }
                else if (i == 2)
                {
                        static Button2 bt3;
                        Buttons[i] = &bt3;
                }
                else if (i == 3)
                {
                        static Button2 bt4;
                        Buttons[i] = &bt4;
                }

                Buttons[i]->begin(buttonPins[i]);
                if (buttonTypes[i] == 0) /* On-Off Switch */
                {
                        Buttons[i]->setPressedHandler(OnOffSW_ON_handler);
                        Buttons[i]->setReleasedHandler(OnOffSW_OFF_handler);
                }
                else if (buttonTypes[i] == 1) /* Momentary press */
                {
                        Buttons[i]->setPressedHandler(toggle_handle);
                }
                Buttons[i]->setID(i);
        }
}

Could you give some background on what you are trying to achieve?

@EdgarBonet - Well it is complicated... I do not want to hard code the number of Button/ Relays each board have. it can be a dual relay, and possibly up to 16 relays on-board.
The amount of Buttons/Relay are stored in a paramter file which obviously read after all classes have been defined and created. So .... see edit 2 in a sec.

I cannot see the usefulness of these preprocessor macros.Please, explain what you are trying to achieve rather than how (e.g. with the preprocessor) you think you may achieve it. So far this looks like an XY question.

@EdgarBonet I hope Edit 2 is clearing that up

My main goal is to be able to define, not in code but reading from a paramter file, the number of instances of Button2 I need, since I want to use same code, for 2,4,8,16 Relays board.

use dynamic allocation with new

@Juraj I hope I explained my self right :( .... did you understand my main goal ?- Can you exaplin with an example how new solves it? ?

@Juraj Thank you- it was so simple.

void init_buttons()
{

        for (uint8_t i = 0; i < numSW; i++)
        {
                Buttons[i] = new Button2;   // <--- **Thnx to Juraj**!!!
                Buttons[i]->begin(buttonPins[i]);
                if (buttonTypes[i] == 0) /* On-Off Switch */
                {
                        Buttons[i]->setPressedHandler(OnOffSW_ON_handler);
                        Buttons[i]->setReleasedHandler(OnOffSW_OFF_handler);
                }
                else if (buttonTypes[i] == 1) /* Momentary press */
                {
                        Buttons[i]->setPressedHandler(toggle_handle);
                }
                Buttons[i]->setID(i);
        }
}

why not  Button2* buttons = new Button2[numSW];? then you can do buttons[i].begin()

I need Buttons[] to be defined at the beginning of code, meaning "global" (to have access to instances). I define it inside a function, since that was I can use nunSW that was read from parameter file in flash.

sorry, yes, in setup() buttons = new Button2[numSW]; while Button2* buttons; is global


text:
GY-521 output and degrees
I am trying to make an observatory through 2 GY-521 gyroscopes and using the outputs I have to make a motor move, but I have a problem.
When I move one of the two gyroscopes the outputs change, but then as soon as I leave it it returns to the initial value, the data I see via an ESP8266 on an internet site, this is the code:
#include <Wire.h>
#include "WiFiEsp.h"
// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(18, 19); // RX, TX
#endif

char ssid[] = "Vodafone-A61356555";            // your network SSID (name)
char pass[] = "YgtHnkJHNpFAcPfH";        // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status
int reqCount = 0;                // number of requests received

WiFiEspServer server(80);

int MPU = 0x69;
int MPU1 = 0x69;
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
int16_t AcX1, AcY1, AcZ1, Tmp1, GyX1, GyY1, GyZ1;
int gyro_state = 2;
int gyro_state_1 = 3;
int RED_LED = 8;
int GREEN_LED = 9;

void setup(){
  pinMode(gyro_state, OUTPUT);
  pinMode(gyro_state_1, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  digitalWrite(gyro_state, HIGH);
  digitalWrite(gyro_state_1, HIGH);
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(115200);
  // initialize serial for ESP module
  Serial1.begin(9600);
  // initialize ESP module
  WiFi.init(&Serial1);

  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true);
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  Serial.println("You're connected to the network");
  printWifiStatus();

  // start the web server on port 80
  server.begin();
}

void loop() {
  // listen for incoming clients
  WiFiEspClient client = server.available();
  if (client) {
    Serial.println("New client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          Serial.println("Sending response");

          // send a standard http response header
          // use \r\n instead of many println statements to speedup data send
          client.print(
            "HTTP/1.1 200 OK\r\n"
            //"Content-Type: text/html\r\n"
            "Connection: close\r\n"  // the connection will be closed after completion of the response
            "Refresh: 5\r\n"
            "\r\n");
          client.print("<!DOCTYPE HTML>\r\n");
          client.print("\r\n");
          client.print("
\r\n");
          client.print("Accelerometro Telescopio X: ");
          client.print(AcX);
          client.print("  Accelerometro Cupola X: ");
          client.print(AcX1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Accelerometro Telescopio Y: ");
          client.print(AcY);
          client.print("  Accelerometro Cupola Y: ");
          client.print(AcY1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Accelerometro Telescopio Z: ");
          client.print(AcZ);
          client.print("  Accelerometro Cupola Z: ");
          client.print(AcZ1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Giroscopio Telescopio X: ");
          client.print(GyX);
          client.print("  Giroscopio Cupola X: ");
          client.print(GyX1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Giroscopio Telescopio Y: ");
          client.print(GyY);
          client.print("  Giroscopio Cupola Y: ");
          client.print(GyY1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Giroscopio Telescopio Z: ");
          client.print(GyZ);
          client.print("  Giroscopio Cupola Z: ");
          client.print(GyZ1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Temperatura Telescopio: ");
          client.print(Tmp);
          client.print("  Temperatura Cupola: ");
          client.print(Tmp1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("\r\n");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(100);

    // close the connection:
    client.stop();
    Serial.println("Client disconnected");
  }
  digitalWrite(gyro_state, HIGH);
  digitalWrite(gyro_state_1, LOW);

  do {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 14, true);       // request a total of 14 registers
    AcX = Wire.read() << 8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY = Wire.read() << 8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ = Wire.read() << 8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp = Wire.read() << 8 | Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX = Wire.read() << 8 | Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY = Wire.read() << 8 | Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ = Wire.read() << 8 | Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

    Tmp = Tmp / 340 + 36.53;

    Serial.println("First Gyro");
    Serial.println(GyZ);

    digitalWrite(gyro_state_1, HIGH);
    digitalWrite(gyro_state, LOW);
    delay(1000);

  } while(digitalRead(gyro_state)== HIGH);

  do {
    Wire.beginTransmission(MPU1);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU1, 14, true);       // request a total of 14 registers
    AcX1 = Wire.read() << 8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY1 = Wire.read() << 8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ1 = Wire.read() << 8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp1 = Wire.read() << 8 | Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX1 = Wire.read() << 8 | Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY1 = Wire.read() << 8 | Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ1 = Wire.read() << 8 | Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

    Tmp1 = Tmp1 / 340 + 36.53;

    Serial.println("Second Gyro");
    Serial.println(Gy1);

    digitalWrite(gyro_state, HIGH);
    digitalWrite(gyro_state_1, LOW);
    delay(1000);

  } while(digitalRead(gyro_state_1) == HIGH);

  if (GyY > GyY1) {
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
  }
  else if (GyY < GyY1) {
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print where to go in the browser
  Serial.println();
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
  Serial.println();
}

Output:
First Gyro
1503
Second Gyro
3730
First Gyro
1558
Second Gyro
-162
First Gyro
1498
Second Gyro
-164

Can anyone explain to me why once I stop moving the gyroscope, the value returns to the initial position? And if it is possible to convert to degrees?

You know, thats what gyroscopes do. They measure angular velocity, not the angle. When you stop turning the sensor the angular velocity drops to zero. Normally one would combine the accelerometer and the integrated gyroscope data to get a stable angle value

See this question on the Electrical Engineering Stackexchange: MPU6050 losing orientation

The GY-521 and the MPU6050 are the same functionally, and you need to use one of the several libraries to get what you want.  It appears you are retrieving angular rate values, but what you want is relative heading. The angular rate will return to zero (or whatever the initial value was) once it stops moving, but the heading will (with proper treatment) stay constant.
I have used the MPU6050 in several projects with success, using Jeff Rowberg’s I2CDevLib library, and although getting everything set up is complicated, I recommend it.  See this post for basic setup.
Also, I note that most of your program has nothing at all to do with the gyroscope.  I recommend you use the smallest and simplest possible program to work out the hardware issues before adding the more complex bits.