text:
What is the best technique to design a 20 push button circuit
I will be controlling a robot with more than 10 motors which means I'll need 2 buttons each to control moving forward and backward. My controller is an Arduino mega. Is 1 pin = 1 button the best solution here? Or should I use another IC for this?

"best solution" depends on your preferences. As the Arduino Mega has enough I/O pins, you might use them without additional hardware. If you want not to rely on the board used (e.g., switch to other/faster MCU in the future), you might use I/O multiplexers like MCP23017, which gives you 16 additional I/Os via I²C, and you can use up to 8 of them on one I²C line. We actually use four of them for 61 touch switches. There are also breakout boards with these chips.

For 20 buttons you can use a Keypad Matrix arrangement (plenty of examples online) where you would use only 9 pins (5 columns of 4 rows is 5+4 pins). It's slightly more involved that simple 1:1 buttons to pins, but thankfully there is a Keypad.h library that takes the hard work out of it for you.
If you want to be able to press multiple buttons at once you need to include diodes in your matrix to prevent "ghosting".
Nick Gammon has a great writeup on it here.

Upvoted. Nice alternative ... can I assume the benefits of yours are less ICs, simultaneous input, and the benefit of mine is less input pins?

Yup. 3/4 as opposed to 9.

Yes this is actually one of my solutions in mind. Maybe apply multiple matrix no?

The more buttons you have in your matrix the more efficient it gets on pins.

The example project below can control 16 switches. If you have a membrane keypad with 5 x 4 or 5 x 5 then you can meet your requirement.

I will shortly add an example of using shift registers to have multiple inputs (the main use case of shift registers is the same)
Link

Below is the example using shift registers. You need three shift registers as @Michael mentioned in his answer. Here is one example where you can control 32 switches maximum. You are only using 3 data pins and two power pins. This is the main application of the shift register. You don't have to do any selection, whenever you read the serial input data, you will automatically get the status of all the 32 switches in one Go.

Here is the code
// File : Cascade165.ino
//
// Version 1, 5 August 2021, by Koepel
//     Initial version.
// Version 2, 5 August 2021, by Koepel
//     Layout of the wiring made better.
// Version 3, 13 August 2021, by Koepel
//     Changed 'SCK' to 'clockPin'.
//
// Cascade of four 74HC165 shift-in registers.
// Only three pins are used on the Arduino board, to read 32 switches.
//
// Using the 74HC165 is safe, because a pulse to the Latch pin
// ('PL' on the 74HC165) will make a new start every time.
// In case of an error or a wrong clock pulse by noise,
// it synchronizes the data when inputs are read the next time.
//
// Based on:
//   (1)
//     Demo sketch to read from a 74HC165 input shift register
//     by Nick Gammon, https://www.gammon.com.au/forum/?id=11979
//   (2)
//     74HC165 Shift register input example
//     by Uri Shaked, https://wokwi.com/arduino/projects/306031380875182657
//
//

const byte latchPin = 9;        // to latch the inputs into the registers
const byte clockPin = 13;       // I choose the SCK pin
const byte dataPin = 12;        // I choose the MISO pin
uint32_t oldOptionSwitch = 0;   // previous state of all the inputs

const int pulseWidth = 10;      // pulse width in microseconds

void setup ()
{
  Serial.begin( 115200);
  Serial.println( "Turn on and off the switches");
  Serial.println( "Top row is switch 0 (right) to switch 7 (left)");
  Serial.println( "Second row is 8 to 15, and so on");

  pinMode( clockPin, OUTPUT);   // clock signal, idle LOW
  pinMode( latchPin, OUTPUT);   // latch (copy input into registers), idle HIGH
  digitalWrite( latchPin, HIGH);
}

void loop ()
{
  // Give a pulse to the parallel load latch of all 74HC165
  digitalWrite( latchPin, LOW);
  delayMicroseconds( pulseWidth);
  digitalWrite( latchPin, HIGH);

  // Reading one 74HC165 at a time and combining them into a 32 bit variable
  // The last 74HC165 is at the bottom, but the switches start numbering
  // at the top. So the first byte has to be shifted into the highest place.
  uint32_t optionSwitch = 0;
  for( int i=24; i>=0; i-=8)
  {
    optionSwitch |= ((uint32_t) ReadOne165()) << i;
  }

  for( int i = 0; i<32; i++)
  {
    if( bitRead( optionSwitch, i) != bitRead( oldOptionSwitch,i))
    {
      Serial.print( "Switch ");
      if( i < 10)
        Serial.print( " ");
      Serial.print( i);
      Serial.print( " is now ");
      Serial.println( bitRead( optionSwitch, i) == 0 ? "down ↓" : "up   ↑");
    }
  }

  oldOptionSwitch = optionSwitch;
  delay( 25);      // slow down the sketch to avoid switch bounce
}

// The ReadOne165() function reads only 8 bits,
// because of the similar functions shiftIn() and SPI.transfer()
// which both use 8 bits.
//
// The shiftIn() can not be used here, because the clock is set idle low
// and the shiftIn() makes the clock high to read a bit.
// The 74HC165 require to read the bit first and then give a clock pulse.
//
byte ReadOne165()
{
  byte ret = 0x00;

  // The first one that is read is the highest bit (input D7 of the 74HC165).
  for( int i=7; i>=0; i--)
  {
    if( digitalRead( dataPin) == HIGH)
      bitSet( ret, i);

    digitalWrite( clockPin, HIGH);
    delayMicroseconds( pulseWidth);
    digitalWrite( clockPin, LOW);
  }

  return( ret);
}

Link to the shift register project: https://wokwi.com/arduino/projects/306024460940476993

there are so many versions of this shift register.     https://www.digikey.com/en/products/base-product/texas-instruments/296/74HC165/16       how do you decide which one to use?

you can use a so called shift register. One very common one is a 74HC165 shift register (https://playground.arduino.cc/Code/ShiftRegSN74HC165N/).
With one of such IC you can connect 8 buttons, however you can daisy chain max 4 to get 4 * 8 = 32 button inputs, only using 4 digital pins of the Arduino. In your case you would need 3 ICs to get 24 (thus 20) button inputs.

A shift register is not a multiplexer. A shift register shifts out all inputs, and a multiplexer selects one-of-N inputs to pass through.

@Majenko yes you are right, I fixed it (thanks)

Thats the problem i have with multiplexer. I need it able to function independently without needing to be "selected"

With this IC you don't need to 'select'', or at least you get all inputs.

@Julius With a multiplexer you program the Arduino so that it selects each button and then checks whether it is pressed, in turn. Because the Arduino is much faster than the human finger, it still sees all the button presses.

Max buttons for min pins (via electrical engineering and busy wait in interupt)
Hook up each button to an interrupt and an analog pin. You can use the same interrupt and analog pins for all buttons, if you use resistors to discern between the buttons.
Use the interrupt pin to get notified, when a button is pushed. Use the resistors to have a different target voltage for each button in a voltage divider. Then in the interrupt handler use the analog pin to measure the voltage.
The main problem is that the voltage will take some time to stabilize after the interrupt already fired. I'd check for at least 3 consecutive identical readings (~30ms delay after the voltage stabilized).
Make sure you have some tolerance, e.g. by shifting at least the two least significant bits out (value = AnalogRead(PIN) >> TOLERANCE_BIT_COUNT;). With the analog pins' 10 bit resolution (1024 values, AFAIR), 2 bits lost for tolerance and an additional bit lost for difference between HI and LO (needed to trigger the interrupt), there are at least 7 bits left, which could suffice for up to 127 buttons.
Yes, you can hook up a keyboard with 2 pins, if you implement part of the logic in hardware (127 carefully designed voltage dividers) and part in software (detecting stabilized voltage). However the identification which button is pressed can be susceptible to deviations in voltage as small as 4.8 mV (a difference of 1 in the value of AnalogRead, which might carry over the tolerance). Also you can not detect multiple buttons being pushed at the same time. However if the electrical design has been carefully engineered, no failure detection may be needed for multiple buttons being pushed, because the interrupt would not fire, depending on how the target voltages stack up.
Electrical engineering problems to be solved:

Designing the voltage dividers is left to the reader, because you can crank up the tolerance, if you need less buttons. This may mitigate the susceptibility to small deviations in voltage. My proposal would be to get X identical resistors of R Ohm for X buttons. Connect the resistors in series and fork the voltage between the resistors via the buttons. Connect all forks after their respective button to the analog pin and another resistor (of X times R Ohm) to either ground or Vcc (depending on the choice of interrupt HI vs. LO). Add a pull-up/down resistor to the end of the resistors in series as necessary.
You might need to make sure not to lose too many bits too early, because otherwise there might be consecutive "identical" values without the voltage having stabilized.
Check, if the interrupt should fire for HI->LO or LO->HI, as one might offer more distinct target voltages than the other. I just assumed that the first AnalogRead will return a value of about 512 either way.
I remember that you can remap the values of AnalogRead to regain the 1 bit lost to HI-LO vs. LO-HI transition. This is not recommended as it might interfere with the behaviour of other analog pins. However in a pinch this may either double the number of buttons possible or add another bit for tolerance.
A small capacitor might help to filter bumping out of the buttons' switching action, so you don't get multiple interrupts for a single button push. However this may increase the time needed for the voltage divider to stabilize at the target voltage. So choose the smallest capacitor and resistors, you can get away with.

A different take
Use an app to make on-screen virtual controls instead of using physical buttons, and send press events over bluetooth or wifi or ESPNOW.
Advantages

no parts needed if you have a phone/laptop already
no soldering
no flaky parts wearing out
complete control over button layout
easy to upgrade/modify control layout based on field experience
one less part to carry
trivial to have extra backup remotes
opens the door to macros (eg. auto-land), test routines, etc
lets you log data from the robot for debugging
EASILY add cool control hardware like gamepads, voice, or camera
much easier to code buttons in, eg. HTML+JS than C++
separates programming concerns and allows detached evolution
allows possibility of internet/remote control
can be developed on laptop, moved to portable raspPi or phone
can control more than one (or a new) robot from the remote control

Disdvantages

needs code in two languages
extra part (eg. ESP8266), though buttons are expensive too
slightly increased latency (but buttons should be debounced anyway)
might not be as satisfying as a 80+ hour hand-built controller
requires a bit of security consideration (maybe)

All in all, I think the advantages FAR outweigh the drawbacks. If you need soldering practice and human-held hardware design experience, a physical remote is a decent project, but you can always do that later once you get the robot working with abstract commands; you don't have to build and debug both at the same time, which is huge to me...
If you NEED a physical remote
You can still get many of the above benefits in a physical remote if you put an MCU/SBC in the remote. Then talk to the robot with uart/wifi/bt/etc. Uart lets you run just 4 wires to the remote instead of dozens. There's lots of existing 4+wire connectors (USB-B, RJ-45, XLR, DIN, etc) that you can use for this; thin, light, cheap, replaceable. Such a config  allows serial debugging, logging, etc. It frees the robot CPU from having to deal with interrupts and library footprints.
All in all, it will make making faster for the small cost of a cheap MCU like a nano/bluepill/esp32...


text:
Interfacing IOT- GA6 to Arduino
Good evening guys,
Looking for any help on interfacing the above GSM/GPRS module with arduino.
Connections:
VCC and GND of module- separate power supply, 5v 3A
URX to pin 2
UTX to pin 3
Common GND between arduino and separate supply.
Tried AT command code for A6 module, getting +CREG:3 on serial monitor.
Same connections as above with GSM send messages code example on arduino-
Doesn't go past "Sms messages sender

what is your question?

Is there a way to interface the ga6 module with arduino. I saw some posts say you must flash the module to A6

Also is there a GA6 module code I could use

Would this help: https://create.arduino.cc/projecthub/EasyMades/a6-gsm-gprs-module-at-commands-34835a

source: Stack Exchange

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

sort: votes


text:
Issue displaying on Adafruit display when enabling GSM communication
I am trying to write to the adafruit display using Arduino MKR1500 when it is connected to the internet. The issue I am facing is when I add the code to connect to the cloud, the display stops working. If I removed that piece of code, the display outputs correctly.
As of now I am just printing "hello world" on the screen.
Below is the code without the cloud connection:
/**************************************************************************
  This is a library for several Adafruit displays based on ST77* drivers.

  Works with the Adafruit 1.8" TFT Breakout w/SD card
    ----> http://www.adafruit.com/products/358
  The 1.8" TFT shield
    ----> https://www.adafruit.com/product/802
  The 1.44" TFT breakout
    ----> https://www.adafruit.com/product/2088
  The 1.14" TFT breakout
  ----> https://www.adafruit.com/product/4383
  The 1.3" TFT breakout
  ----> https://www.adafruit.com/product/4313
  The 1.54" TFT breakout
    ----> https://www.adafruit.com/product/3787
  The 2.0" TFT breakout
    ----> https://www.adafruit.com/product/4311
  as well as Adafruit raw 1.8" TFT display
    ----> http://www.adafruit.com/products/618

  Check out the links above for our tutorials and wiring diagrams.
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional).

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 **************************************************************************/
#include <Adafruit_Fingerprint.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce2
//#include <EEPROM.h>
#include <FlashStorage.h>

#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32
#define TFT_CS         14
#define TFT_RST        15
#define TFT_DC         32

#elif defined(ESP8266)
#define TFT_CS         4
#define TFT_RST        16
#define TFT_DC         5

#else
// For the breakout board, you can use any 2 or 3 pins.
// These pins will also work for the 1.8" TFT shield.
#define TFT_CS        1 // D v25 changes to use pin 1 for CS in MKR1500
#define TFT_RST        -1 // Or set to -1 and connect to Arduino RESET pin // D v25 changes to use built in reset pinout in MKR1500
#define TFT_DC         2 // D v25 changes to use pin 2 for CS in MKR1500
#endif

//D v15 for audrino to connect to fingerprint sensor
//D v2
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 4);

#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1

#endif

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 use:
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // D v21 uncomment this and comment the line below to use 1.44inch display.Need to change the display font in case I use 1.44"

// For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789:
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // D v22 uncommment to use this display

#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>
#include <MKRNB.h>

// Debug options
#define PRINT_AT        true   // Show or hide AT command output from the modem

// PIN Number
const char PINNUMBER[]     = "";
char apn[] = "soracom.io";
char user[] = "sora";
char pass[] = "sora";

// Server details
const char server[] = "unified.soracom.io";
const int  port = 80;

NBClient client;
GPRS gprs;
NB nbAccess(PRINT_AT);
HttpClient http(client, server, port);

// connection state
  bool connected = false;

// Publish interval
long previousMillis = 0;
long interval = 1000; // milliseconds // D v2orginial value: long interval = 20000; chnages the time interval in which it will report

void setup(void) {

  // tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  tft.init(240, 240);           // Init ST7789 240x240  // D v22 uncommment to use this display

  // tft print function!
  tftPrintTest();

  pinMode(SARA_RESETN, OUTPUT);
  digitalWrite(SARA_RESETN, LOW);
  pinMode(SARA_PWR_ON, OUTPUT);

  //Initialize serial and wait for port to open:
  Serial.begin(115200);

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

  start_and_connect_modem();

  }

 void loop() {
  tft.invertDisplay(true);
  delay(500);

  tft.setTextColor(ST77XX_GREEN);
  tft.setCursor(0, 10);

    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);

    tft.println("hello world");

    }

void tftPrintTest() {
  tft.setRotation(3);
  tft.setTextWrap(true);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(2);
}

Below is the code with the cloud connection added
/**************************************************************************
  This is a library for several Adafruit displays based on ST77* drivers.

  Works with the Adafruit 1.8" TFT Breakout w/SD card
    ----> http://www.adafruit.com/products/358
  The 1.8" TFT shield
    ----> https://www.adafruit.com/product/802
  The 1.44" TFT breakout
    ----> https://www.adafruit.com/product/2088
  The 1.14" TFT breakout
  ----> https://www.adafruit.com/product/4383
  The 1.3" TFT breakout
  ----> https://www.adafruit.com/product/4313
  The 1.54" TFT breakout
    ----> https://www.adafruit.com/product/3787
  The 2.0" TFT breakout
    ----> https://www.adafruit.com/product/4311
  as well as Adafruit raw 1.8" TFT display
    ----> http://www.adafruit.com/products/618

  Check out the links above for our tutorials and wiring diagrams.
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional).

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 **************************************************************************/
#include <Adafruit_Fingerprint.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce2
//#include <EEPROM.h>
#include <FlashStorage.h>

#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32
#define TFT_CS         14
#define TFT_RST        15
#define TFT_DC         32

#elif defined(ESP8266)
#define TFT_CS         4
#define TFT_RST        16
#define TFT_DC         5

#else
// For the breakout board, you can use any 2 or 3 pins.
// These pins will also work for the 1.8" TFT shield.
#define TFT_CS        1 // D v25 changes to use pin 1 for CS in MKR1500
#define TFT_RST        -1 // Or set to -1 and connect to Arduino RESET pin // D v25 changes to use built in reset pinout in MKR1500
#define TFT_DC         2 // D v25 changes to use pin 2 for CS in MKR1500
#endif

//D v15 for audrino to connect to fingerprint sensor
//D v2
#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 4);

#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1

#endif

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 use:
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // D v21 uncomment this and comment the line below to use 1.44inch display.Need to change the display font in case I use 1.44"

// For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789:
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // D v22 uncommment to use this display

#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>
#include <MKRNB.h>

// Debug options
#define PRINT_AT        true   // Show or hide AT command output from the modem

// PIN Number
const char PINNUMBER[]     = "";
char apn[] = "soracom.io";
char user[] = "sora";
char pass[] = "sora";

// Server details
const char server[] = "unified.soracom.io";
const int  port = 80;

NBClient client;
GPRS gprs;
NB nbAccess(PRINT_AT);
HttpClient http(client, server, port);

// connection state
  bool connected = false;

// Publish interval
long previousMillis = 0;
long interval = 1000; // milliseconds // D v2orginial value: long interval = 20000; chnages the time interval in which it will report

void setup(void) {

  // tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  tft.init(240, 240);           // Init ST7789 240x240  // D v22 uncommment to use this display

  // tft print function!
  tftPrintTest();

  pinMode(SARA_RESETN, OUTPUT);
  digitalWrite(SARA_RESETN, LOW);
  pinMode(SARA_PWR_ON, OUTPUT);

  //Initialize serial and wait for port to open:
  Serial.begin(115200);

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

  start_and_connect_modem();

  }

 void loop() {
  tft.invertDisplay(true);
  delay(500);

  tft.setTextColor(ST77XX_GREEN);
  tft.setCursor(0, 10);

    tft.setCursor(0, 0);
    tft.fillScreen(ST77XX_BLACK);

    tft.println("hello world");

    }

void tftPrintTest() {
  tft.setRotation(3);
  tft.setTextWrap(true);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(2);
}

void post_data(String postData) {
 //Serial.println("making POST request");
  String contentType = "application/json";

  http.post("/", contentType, postData);

  // read the status code and body of the response
  int statusCode = http.responseStatusCode();
  String response = http.responseBody();

  /*Serial.print("Status code: ");
  Serial.println(statusCode);
  Serial.print("Response: ");
  Serial.println(response);*/

}

void start_and_connect_modem(){
  pinMode(SARA_RESETN, OUTPUT);
  digitalWrite(SARA_RESETN, LOW);
  pinMode(SARA_PWR_ON, OUTPUT);

  // Send Poweron pulse
  digitalWrite(SARA_PWR_ON, HIGH);
  delay(150);
  digitalWrite(SARA_PWR_ON, LOW);
  delay(500);
  // Turn on the modem
  if (Serial) Serial.print(">>> Turning on modem...");
  if (MODEM.begin()) {
    if (Serial) Serial.println(" done!");
  } else {
    if (Serial) Serial.println(" error, could not turn on modem! Try power-cycling.");
    return;
  }

  while (!MODEM.noop());
  MODEM.sendf("ATI9");
  MODEM.waitForResponse(2000);

  // Run AT commands to reset the modem to global default settings
  Serial.print(">>> Resetting modem to default settings...");
  MODEM.sendf("AT+CFUN=0");
  MODEM.waitForResponse(6000);
  MODEM.sendf("AT+UMNOPROF=2");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+CFUN=15");
  MODEM.waitForResponse(6000);
  MODEM.sendf("AT+CFUN=0");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+UMNOPROF=0");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+CFUN=15");
  MODEM.waitForResponse(2000);
  MODEM.sendf("AT+URAT=7");
  MODEM.waitForResponse(2000);
  //D v33
  /*MODEM.sendf("AT+UBANDMASK?");
  MODEM.waitForResponse(6000);*/
  Serial.println(" done!");

  delay(2000);
  // attempt to connect to GSM and GPRS:
  Serial.print("Attempting to connect to GSM and GPRS");
  //Serial.println();
  connect_modem();

}

void connect_modem(){
  // After starting the modem with GSM.begin()
  // attach the shield to the GPRS network with the APN, login and password
  while (!connected) {
    if ((nbAccess.begin(PINNUMBER, apn, user, pass) == NB_READY) &&
        (gprs.attachGPRS() == GPRS_READY)) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }

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

Can someone please let me know what I am missing?

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


text:
What is the REF pin for -- pin 9 on ATSAMD21G18-QFN48?
32-bit ARM-Based microcontroller SAM D21E / SAM D21G /SAM D21J
I have a Seeeduino XIAO PDF to schematic which uses a ATSAMD21G18-QFN48 chip. Pin D1 on the Seeeduino is pin 9 on the chip; which is labeled as PA4/EIC/REF/AIN4/SCOM0PAD0/TC0.

What would the REF pin be used for; and how would the pin be addressed in the code?
Based on this post is sound like it is ADC related.
There is no indication about this on the https://wiki.seeedstudio.com/Seeeduino-XIAO/ website. Only this image:

PA04 pin can be a normal GPIO or a voltage reference pin (similar to VDDANA). So, the ADC input will be compared to this VREF pin in the application if needed. If you have configured it as GPIO, then it will behave as a normal IO pin. It depends on how you configure it.


text:
Prevent flash cloning
I need a way to prevent someone from cloning code from arduino. Without protection it can be cloned with advdudees in 2 min. I'm using atmega328p chip on nano. In this state arduino acts as a handshake for windows program i need to protect. There is nothing special or of value on arduino, but the custom handshake. One arduino for one .exe file. All arduino code is uploaded from arduino ide.
I did research and here it is.

Lock fuse bits. As i understood once locked flash and eeprom cant be read. When they are unlocked flash and eeprom are erased. I need one more arduino to act as programator.
Use some other unique hard to copy module like rfid card or bluetooth/wifi mac address. This is bad because it takes too much pins on nano.
Subtly solder 2 digital pins and set one to output and other to input. If not connected break loop.
Usb hardware dongle licence. I have no idea how to create one and it seems like some relic of the past. Custom file system or something...

I'd like to keep arduino nano for deployment.
There is no internet involved. If program had access to internet i'd just use db.
Thanks in advance.

what is your question? ... you provided a solution to the problem of preventing the copying of flash memory ... the handshake can only be protected by preventing physical access to the windows pc

I need to known if this is a good idea and would it work. I have one attempt to get it right. And if anyone has any better solutions.

So you are developing your own protection dongle. Well, why don't you simply use a proven product?

Note that setting the lock bits is pointless, while the Arduino bootloader is installed. The bootloader can still read out the program, even with the lock bits set. You'd have to remove the bootloader and upload the code using the ISP interface (ArduinoAsISP).

You could save a GUID in EEPROM that matches one in the compiled file. The sketch reads EEPROM, and compares the saved value, quitting if they don't match. This might require flashing a simple stand-alone sketch that only writes the EEPROM before flashing your main program. It's not skilled hacker-proof, but it would stop the unaltered sketch from running anywhere but the original MCU.

Using the lock fuse bits is definitely the correct step here. Unlocking is not a problem, since the memory will be erased in that step and you cannot prevent reflashing anyway.

Very important note from Gerben in the comments:

Note that setting the lock bits is pointless, while the Arduino bootloader is installed. The bootloader can still read out the program, even with the lock bits set. You'd have to remove the bootloader and upload the code using the ISP interface (ArduinoAsISP).

The lock bits only work for the ISP interface, which can be used to program the Arduino. The bootloader (which is part of the program on  the Arduino) still can read the program memory (it has to, since it is executed from there). Thus to prevent someone from reading out the program through the bootloader, you need to remove the bootloader. Programming is then done just like you are setting the fuses: Through ISP (for example via a second Arduino).

You didn't include details on the handshake. An important attack route would be to just sniff on the Arduinos Serial interface. Unless your handshake itself is encrypted locking the Arduino will not prevent attackers from getting it.
There are encryption libraries for Arduino (like this one on github). Based on your thread model and the needed resources (since the Uno is rather constrained especially in RAM) you can choose a fitting library and a fitting encryption algorithm. One important attack route would be a replay attack, where the attacker just resends the serial data, that he recorded in the last successfull transmission. One way to prevent that would be a rolling code (like modern garage door openers often use). Or you can create One-Time-Passwords (for example by combining the handshake secret with a timestamp and encrypting/hashing that; you need synchronized time for that).

Handshake works by sending 4 ints hardcoded in .exe. Those 4 ints are hardcoded on arduino, it connects if they match. Before sending i do some basic math operations and reverse them on arduino. Then i send multiple random numbers, do some math ℅ 6 = inc. One byte is one command so i increment command bytes on both sides by inc. Every time arduino connects command bytes are different. If attacker was only sniffing data, he would get random numbers and would need to find a pattern and reverse enginner math operations.

@gagicf2 That is better than transmitting the plain secret, though not impossible to reverse engineer the pattern. I think with a number of sniffed transmissions one could do a statistical analysis and guess the pattern. Though - as stated - it comes down to your thread model. You can decide, that this level of security is enough.

Instead of sending the secret (even obscured) generate a random nonce and send that instead. The Arduino hashes a stored secret concatenated to the incoming nonce, and returns that hash to the computer, which performs the same steps itself (the EXE knows the secret), and compares the two hashes to validate. In this role, you can even use something cryptographically weak but CPU cheap like sha1 or even md5, as long as your nonce is longer than 16 chars, or 24, or 32, whatever you need to sleep. Tiny stand-alone hash functions fit better into MCUs than a whole lib of crypto tools you don't need.


text:
Is there a VESC firmware implementation that runs on Arduino?
I am looking to use an Arduino in a motor control application, and have found that the VESC^ project has done some good work in this. I would like to have some fine-grain control over the motor drive, but using the VESC foundation looks great.
Research so far on Arduino and VESC discusses using an Arduino to interface with VESC hardware, however I'd be more interested in having the VESC firmware running on the Arduino, with output driving a power stage.
Is there a reason why this is not possible? (where the most powerful Arduino being insufficient on processing, not enough memory, etc.)
^VESC is an open Electronic Speed Control infrastructure for motor control that in completeness includes hardware, firmware and parameterisation/control sotfware. VESC Project website.

It might help if you define VESC.

@PMF Description added.


text:
Writing to a specific I2C register
I am trying to write to a specific register, but value doesn't change.
Working with SenseAir Sunrise CO2:
Info from i2c guideline from sensor manufacter
https://rmtplusstoragesenseair.blob.core.windows.net/docs/Dev/publicerat/TDE5531.pdf

Measurement Period (EE) 0x96 (MSB) 0x97 (LSB)
Measurement period in seconds (range from 2 to 65534). Odd numbers
will be rounded up to nearest even number. A system reset is required
after changing configuration. Default value is 16.

And that's my code snippet
#include <Wire.h>

/* WARINING!!!
  Some wire driver implementations do not corectly implement Wire.endTransmission(false) function,
  so please check this before disable WIRE_WORKAROUND!
  For example, known "bad" implementations are: Nucleo STM32
 */
#define WIRE_WORKAROUND   (0)

#define LED_BUILTIN 2

/* Define serial EN pin */
const int       SUNRISE_EN              = 4;

/* Sunrise communication address, both for Modbus and I2C */
const uint8_t   SUNRISE_ADDR            = 0x68;

/* Amount of wakeup attempts before time-out */
const int       ATTEMPTS                 = 5;
/* It takes 25ms to write one EE register */
const int       EEPROM_UPDATE_DELAY_MS   = 25;

/* Register Addresses */
const uint8_t ERROR_STATUS             = 0x01;
const uint8_t MEASUREMENT_MODE         = 0x95;
const uint8_t METER_CONTROL            = 0xA5;

/* Reading period, in milliseconds. Default is 4 seconds */
int readPeriodMs = 2000;

void setup()
{
  /* I2C */
  /* Initialize I2C and use default pins defined for the board */
  reInitI2C();

  Serial.begin(115200);

  Serial.println("Initialization complete\n");

  change_measurement_period(SUNRISE_ADDR);

  /* Read the sensor's configs */
  Serial.println("Sensor Measurement Configurations:");
  read_sensor_config(SUNRISE_ADDR);
  Serial.println();
}

void change_measurement_period(uint8_t target) {
  /* Function variables */
  int error;

  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    /* FATAL ERROR */
    while(true);
  }

  Serial.println("Changing Measurement Period...");

  uint16_t mPeriod = 12;

  Wire.beginTransmission(target);
  Wire.write(0x96);
  Wire.write(highByte(mPeriod));      // sends MSB
  Wire.write(lowByte(mPeriod));       // sends LSB
  error = Wire.endTransmission(true);
  delay(EEPROM_UPDATE_DELAY_MS);

  if(error != 0) {
    Serial.print("Failed to send request. Error code: ");
    Serial.println(error);
    /* FATAL ERROR */
    while(true);
  }

  Serial.println("\n\n\nSensor restart is required to apply changes\n\n\n");
}

/**
 * @brief  Reads and prints the sensor's current measurement mode,
 *         measurement period and number of samples.
 *
 * @param  target: The sensor's communication address
 * @note   This example shows a simple way to read the sensor's
 *         measurement configurations.
 * @retval None
 */
void read_sensor_config(uint8_t target) {
  /* Function variables */
  int error;
  int numBytes = 7;

  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    return;
  }

  /* Request values */
  error = WireRequestFrom(target, numBytes, MEASUREMENT_MODE /* from address*/, true /* STOP*/);
  if(error != numBytes ) {
    Serial.print("Failed to write to target. Error code : ");
    Serial.println(error);
    return;
  }

  /* Read values */
  /* Measurement mode */
  uint8_t measMode = Wire.read();

  /* Measurement period */
  uint8_t byteHi = Wire.read();
  uint8_t byteLo = Wire.read();
  uint16_t measPeriod = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* Number of samples */
  byteHi = Wire.read();
  byteLo = Wire.read();
  uint16_t numSamples = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* ABCPeriod */
  byteHi = Wire.read();
  byteLo = Wire.read();
  uint16_t abcPeriod = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* Most propable that the sensor will not go into sleep mode, but to be insure...*/
  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    return;
  }

  /* Request values */
  error = WireRequestFrom(target, 1, METER_CONTROL /* from address*/, true /* STOP*/);
  if(error != 1 ) {
    Serial.print("Failed to write to target. Error code : ");
    Serial.println(error);
    return;
  }

  uint8_t meterControl = Wire.read();

  Serial.print("Measurement Mode: ");
  Serial.println(measMode);

  readPeriodMs = measPeriod * 1000;

  Serial.print("Measurement Period, sec: ");
  Serial.println(measPeriod);

  Serial.print("Number of Samples: ");
  Serial.println(numSamples);

  if((0U == abcPeriod) ||  (0xFFFFU == abcPeriod) || (meterControl & 0x02U)) {
    Serial.println("ABCPeriod: disabled");
  } else {
    Serial.print("ABCPeriod, hours: ");
    Serial.println(abcPeriod);
  }

  Serial.println("MeterControl: ");
  Serial.println("Bit [0]:" + (String)bitRead(meterControl,0));
  Serial.println("Bit [1]:" + (String)bitRead(meterControl,1));
  Serial.println("Bit [2]:" + (String)bitRead(meterControl,2));
  Serial.println("Bit [3]:" + (String)bitRead(meterControl,3));
  Serial.println("Bit [4]:" + (String)bitRead(meterControl,4));
  Serial.println("Bit [5]:" + (String)bitRead(meterControl,5));
  Serial.println("Bit [6]:" + (String)bitRead(meterControl,6));
  Serial.println("Bit [7]:" + (String)bitRead(meterControl,7));
  Serial.println(meterControl, BIN);

}

/* Initialize I2C bus and pins */
void  reInitI2C() {
  /* Initialize I2C and use default pins defined for the board */
  Wire.begin();
  /* Setup I2C clock to 100kHz */
  Wire.setClock(100000);
}

/* Workaround regarding BAD implementations of Wire.endTransmission(false) function */
int WireRequestFrom(uint8_t dev_addr, uint8_t bytes_numbers, uint8_t offset_to_read, bool stop) {
 int error;
#if (WIRE_WORKAROUND == 1)
 error = Wire.requestFrom((uint8_t)dev_addr, (uint8_t)bytes_numbers /* how many bytes */, (uint32_t)offset_to_read /* from address*/, (uint8_t)1/* Address size - 1 byte*/, stop /* STOP*/);
#else
  Wire.beginTransmission(dev_addr);
  Wire.write(offset_to_read); //starting register address, from which read data
  Wire.endTransmission(false);
  error = Wire.requestFrom((uint8_t)dev_addr, (uint8_t)bytes_numbers /* how many bytes */, (uint8_t)stop /* STOP*/);
#endif
  return error;
}

/**
 * @brief  Wakes up the sensor by initializing a write operation
 *         with no data.
 *
 * @param  target:      The sensor's communication address
 * @note   This example shows a simple way to wake up the sensor.
 * @retval true if successful, false if failed
 */
bool _wakeup(uint8_t target)
{
  int attemps = ATTEMPTS;
  int error;

  do {
    uint8_t byte_0;
    /* */
    Wire.beginTransmission(target);
    error = Wire.endTransmission(true);
  } while(((error != 0 /*success */) && (error != 2 /*Received NACK on transmit of address*/) && (error != 1 /* BUG in STM32 library*/)) && (--attemps > 0));
  /* STM32 driver can stack under some conditions */
  if(error == 4) {
    /* Reinitialize I2C*/
    reInitI2C();
    return false;
  }
  return (attemps > 0);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Mostly i use that code, but it's not have an snippet with writing random number in register with MSB&LSB:
https://github.com/Senseair-AB/Sunrise-Examples---Arduino/blob/master/examples/i2c/sunrise_i2c_continuous/sunrise_i2c_continuous.ino
i reset sensor hardware(physically push the reset button and toogle power from sensor) after data was written and also i wait until all bytes are written
delay(EEPROM_UPDATE_DELAY_MS);
Also i read the sensor configuration after startup, and i see that values of registers doesn't change.
Problem in function change_measurement_period
What am i doing wrong? maybe someone can help with that?

You’re not checking the error return. And you don’t appear to be resetting the system, as the documentation you quoted says you must.

it's not full code, i check the error code and it's ok.
And do the system reset, but value in register doesn't change

It helps if you share the full code. At least share all the code relevant to the question, a complete minimal viable example that demonstrates the problem. Not just a snippet.

@romkey i mostly use that code, but it's not have an snippet with writing random number in register with MSB&LSB: https://github.com/Senseair-AB/Sunrise-Examples---Arduino/blob/master/examples/i2c/sunrise_i2c_continuous/sunrise_i2c_continuous.ino

Can you make up a  minimal example that actually compiles and runs, which sets the register and then checks the register. We can't really debug "I mostly use that code" sort of stuff.

@NickGammon i added a code example that compile and runs at esp32.

My main goal was to use the opportunity to get the value compensated by atmospheric pressure.
But for this it was necessary to understand how to write in registers.
And did not understand what was the problem in the examples of code provided by the manufacturer, it did not correctly work with writing to register 2 bytes data or і did something wrong (most likely).
So I rewrote it with the help of a man from the Arduino forum, and now everything works fine.
    //Write pressure value to register BAROMETRIC_PRESSURE_VALUE
    int16_t co2Pre = 9772; //977.2 hPa

    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(BAROMETRIC_PRESSURE_VALUE);
    Wire.write(highByte(co2Pre));      // sends MSB
    Wire.write(lowByte(co2Pre));       // sends LSB
    error = Wire.endTransmission(true);
    delay(50);

    if( error != 0) Serial.println( "ERROR, can't find the sensor");

  int WireRequest(byte target, byte regAddr, int numBytes) {
  // The wake-up is a write command to the I2C address of the sensor.
  Wire.beginTransmission(target);
  Wire.endTransmission();                   // ignore the return value

  // Set register address of the sensor
  Wire.beginTransmission(target);
  Wire.write(regAddr);                        // register address
  int error = Wire.endTransmission(false); // false for a repeated start

  if( error != 0) {
    Serial.println( "ERROR, can't find the sensor");
    return 1;
  }

  // Read the temperature (two bytes, representing a signed integer)
  int n = Wire.requestFrom(target, numBytes);       // request 2 bytes

  if( n != numBytes) {
    Serial.println( "ERROR, can't read data");
    return 1;
  }

  return 0;
}

    //read BAROMETRIC_PRESSURE_VALUE
    error = WireRequest(SUNRISE_ADDR, BAROMETRIC_PRESSURE_VALUE, 2);
    if(error != 0) {
      Serial.println( "Failed to write to target.");
      while(true);
    }
    msb = (byte) Wire.read();
    lsb = (byte) Wire.read();
    int16_t co2Pressure = word( msb, lsb);
    float co2PressureValue = float( co2Pressure) / 10;
    Serial.println("BAROMETRIC_PRESSURE_VALUE: " + (String) co2PressureValue);

And also working code snippets for writing registers, that need sensor restart, later i physically restart the sensor, but now do it in code.
    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(MEASUREMENT_PERIOD);
    Wire.write(highByte(mPeriod));      // sends MSB
    Wire.write(lowByte(mPeriod));       // sends LSB
    error = Wire.endTransmission(true);
    delay(50);

    if( error != 0) Serial.println( "ERROR, can't find the sensor");

    //RESTART SENSOR
    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(SENSOR_RESTART_SCR);
    Wire.write(0xFF);
    error = Wire.endTransmission(true);
    if( error != 0) Serial.println( "ERROR, can't find the sensor");

    Serial.println("\n\nSensor restart to apply changes\n\n");

    delay(2500); //Wait after sensor restart

As written on page 14 of the linked document (emphasis by me):

All new written data to register (EE) can be read back after a sensor reset is completed.

But it seems as if you don't reset the sensor.
You will need to wait as documented, until all bytes are written.

i reset sensor hardware(physically push the reset button and toogle power from sensor) after data was written and also i wait until all bytes are written delay(EEPROM_UPDATE_DELAY_MS);
Also i read the sensor configuration after startup, and i see that values of registers doesn't change. I use that code: https://github.com/Senseair-AB/Sunrise-Examples---Arduino/blob/master/examples/i2c/sunrise_i2c_continuous/sunrise_i2c_continuous.ino

Well, you did not show this in your question. Please add these important information by editing your question. -- However, then it is another problem.

ok.
I think that may be problem in my function of writing to register, i never to that later.

i added a full code example, maybe you see where the problem might be


text:
What are SerialNina and SerialHCI supposed to be used for? (Arduino Nano RP2040 Connect)
Essentially, I'm trying to figure out how I can use Bluetooth Classic using the on-board U-blox w102 Wifi/Bluetooth module. I'm assuming that SerialNina and SerialHCI are somehow connected to it and maybe the way to use Bluetooth Classic on the Nano RP2040.
The ArduinoBLE library uses SerialHCI in HCIUartTransport.cpp. It also messes with NINA_RESETN and SPIWIFI_SS a bit in  BLELocalDevice.cpp, but I'm not too worried about those.
The WiFiNINA library uses SerialNina to update the wifi firmware in SerialNINAPassthrough.ino and ESP32BootROM.cpp.
From this, I'm assuming that SerialHCI can be used to control BLE and SerialNina updates the Wifi's firmware. Am I right about this? If so, what part of the Nina-w102 module is SerialHCI connected to?

what part of the Nina-w102 module is SerialHCI connected to?

from ArduinoCore-mbed/variants/NANO_RP2040_CONNECT/pins_arduino.h
#define SerialNina      Serial3
#define SerialHCI       Serial2

#define SERIAL2_TX          (digitalPinToPinName(25))
#define SERIAL2_RX          (digitalPinToPinName(26))
#define SERIAL2_CTS         (digitalPinToPinName(27))
#define SERIAL2_RTS         (digitalPinToPinName(28))
#define SERIAL3_TX          (digitalPinToPinName(25))
#define SERIAL3_RX          (digitalPinToPinName(26))

Serial2 is configured with flow control pins, but both Serial2 and Serial3 use the same RX/TX pins wired to ESP32 NINA RX/TX.

the way to use Bluetooth Classic on the Nano RP2040:

To use classic Bluetooth on Arduino boards with esp32 NINA module you have to replace the Arduino nina-fw in the esp32 with the SerialToSerialBT.ino sketch for esp32 Arduino core.
You can flash NINA over the host MCU (rp2040) with SerialNINAPassthrough.ino sketch of WifiNINA library. More details about that are in this Arduino forum thread. (Ignore the part before my first comment there).
But with this modification there is no nina firmware, so no WiFi, no cloud. The esp32 is then like a HC-05.

Yeah I went through that thread a few times before and it seems it only worked for people with certain boards. I uploaded SerialNINAPassthrough.ino to my RP2040 without any errors. Then I attempt to upload SerialToSerialBT.ino to my RP2040 as the esp32 u-blox NINA-w102 with an upload speed of 115200. I get the error "serial.serialutil.SerialException: could not open port 'COM3': WindowsError(5, 'Access is denied.') Failed to execute script esptool the selected serial port Failed to execute script esptool  does not exist or your board is not connected." The builtin led flashes a bunch of times.

"Access is denied"? do you have the Serial Monitor open?

I closed the Serial Monitor and retried it. Now I'm getting the error "serial.serialutil.SerialTimeoutException: Write timeout Failed to execute script esptool An error occurred while uploading the sketch." I'm following the same steps I listed above. Also, the builtin led doesn't flash this time.

maybe try the upload with esptool from command line and disable the reset before upload  with -before no_reset


text:
Arduino Nano Every: get board name in the code
I would like to identify the target where I'm downloading my Arduino code. Following this example:
How to get board type
I'm able to recognize for example Arduino Mini, etc.. but Arduino Every, quite new board is not in the list and I don't understand where to find the correct "define" name to add in the list.
Can someone help me?
Thanks Andrea.

there really isn't much magic behind it.  Depending on your selection, ide includes a particular core folder from inside hardware so in theory you could look there also.  that specific method is tied to an arduino bootloader- the thing that runs at boot before your program.  As it said, search for avr_cpunames.h header and see if _AVR_CPU_NAME_ helps.

Thanks but I wrote here because searching into Arduino IDE installation I did not found nothing related to "Arduino Every" or even "AT mega 4809" etc.. nothing that seems in the list. So, if someone is more expert to me.. also the file avr_cpunames.h contains nothing related. I tried with many names that could make sense but trying by tentatives.. not so good. Arduino IDE version 1.8.13. With IDE installed I can use Arduino Nano Every perfectly.

default behavior does something evil for downloaded packages - also check %HOMEPATH%\AppData\Local for an Arduino folder.  The Arduino.h header it uses is likely there under packages\arduino\hardware\megaavr

Arduino Nano Every is using the ArduinoCore-megaavr, designed for new chips like AT mega4808/09. For Uno/Nano/Pro Mini, it is using the ArduinoCore-avr. If you can't find your board on IDE or your file system, the chance is that you have not install the ArduinoCore-megaavr.

According to documentation the macro to identify the Arduino board is generated as as ARDUINO_{build.board} where {build.board} is from boards.txt file of the 'platform'.
Nano Every has in boards.txt nona4809.build.board=AVR_NANO_EVERY.
So the macro to identify Nano Every is ARDUINO_AVR_NANO_EVERY.

Great! I was not aware of this documentation. It works perfectly, thanks a lot! I also found that if you need to know if the emulator mega 328 is selected, you can use:     #elif defined(AVR_NANO_4809_328MODE)
#define BOARD F("Every 328 emul")
#elif defined(ARDUINO_AVR_NANO_EVERY)
#define BOARD F("Every") But your answer solved my problem. Many thanks


text:
No response from instrument via serial communication
I am using a Teensy 3.6 to communicate with an external instrument via a serial connection. However, I am not able to get the instrument to respond to my commands.
The idea is to send a command from the computer via the serial monitor to the Teensy, which then can send it to the instrument (I know that the Teensy is not needed with this configuration but this is just for testing of a more complex set-up).
The instrument uses an RS232 connector so I use this RS232 shifter to connect it to the Teensy. The serial communication settings of the instrument are: 38.4k baud rate, 8 data bits, 1 stop bit, no parity and a carriage return character should mark the end of the command string.
A simple example of my code to read the input from the serial monitor and send a command to the instrument:
#define FILTser Serial1
char Command;

void setup() {
  Serial.begin(9600);
  FILTser.begin(38400);
  Serial.println("<Teensy is ready>");
}

void loop() {
    Command = 'X';
    recvCmd();

    // Start sampling command
    if (Command == 'S') {
       FILTser.write("pumpctl=1\r");
       FILTser.write('\n');
       Serial.println("Sampling started");
    }
}

void recvCmd() {
    if (Serial.available() > 0) {
        Command = Serial.read();
    }
}

If I read the output from the Teensy on the Serial1 port with Putty I get the message correctly. If I send the same command directly to the instrument with Putty or Python I get the instrument to respond as I expect. This means that the instrument is working and the serial output from the Teensy is also fine so I really don't understand what could be wrong.
I know that the instrument is not responding because I would expect a pump to turn on when it receives the command. Additionally, I tried to read the answer of the instrument on the serial port and I was receiving a -1 but I would expect OK for a good command and ERR if the command is not recognized.
To read the instrument answer on the serial port I tried using both a single character with Response = FILTser.read(); and also a full string using the code from here.
An example of the Python code that I use to send commands to the instrument is the following:
import datetime
import serial
import io
import time

# =============================================================================
# Configure serial port
# =============================================================================
ser = serial.Serial()
ser.baudrate = 38400
ser.port = 'COM5'
ser.timeout = 1

#%% Define FILT functions
def FILT_send(commnd):
    ser.write(commnd.encode('ascii'))
    time.sleep(0.5)
    value_read = ser.readline().decode('ascii')
    return(value_read)

def FILT_control():
    global q
    user_input = input('Type:\n \
    - S to start sampling\n \
    - E to end sampling\n \
    - Q to quit the program\n')

    if user_input == 'S':
        FILT_send('pumpctl=1\r')
        print('Sampling started')

    if user_input == 'E':
        FILT_send('pumpctl=0\r')
        print('Sampling ended')

    if user_input == 'Q':
        print('The end')
        q = False

#%% Main
ser.open()
q = True
while q:
    FILT_control()
ser.close()

Comments are not for extended discussion; this conversation has been moved to chat.

The Sparkfun RS232 shifter is not a great device. It relies on whatever it's connected to (on the 9-pin port) providing the negative rail for the EIA-232 voltage levels.
That's fine when you connect to something that has those voltages available, such as a computer, but many "devices" don't - they will themselves have a similar shifter inside and will rely on whatever they are plugged in to for providing the needed negative voltage.
Put the two together and no-one will provide that negative voltage.
Instead you should use a MAX232 (or MAX3232 for 3.3V operation) based converter. This has a built-in voltage doubler and voltage inverter to convert the 5V into +/-10V to give a proper EIA-232 compliant signal which the device should then be happy with.


text:
Two-Wire Interface (TWI) Frequency and SMBus Compatibility
Have I understood the ATmega328P datasheet correctly regarding the TWI clock frequency?
From §21.5.2 Bit Rate Generator Unit, the TWI clock frequency is calculated as follows:

Then solving for TWBR:

However, §8.12.2 CLKPR – Clock Prescale Register mentions that the CPU frequency is prescaled by CLKPR. So should the equation be:

And solving for TWBR:

Is the following code a correct implementation of the equations?
void SetFrequency(uint32_t twi_freq)
{
    if (smbus)
    {
        // SMBus clock frequency is 10 kHz to 100 kHz.
        if (twi_freq > 100000u)
        {
            twi_freq = 100000u;
        }
        else if twi_freq < 10000u)
        {
            twi_freq = 10000u;
        }
    }
    else if (twi_freq > 400000u)
    {
        // Up to 400 kHz data transfer speed.
        // §21.1 Features
        twi_freq = 400000u;
    }

    // TWI prescaler of 1.
    // Table 21-8. TWI Bit Rate Prescaler
    // TWPS1 = 0, TWPS0 = 0
    TWSR &= B11111100;

    // Achievable maximum TWI frequency with current CPU frequency, CLK prescaler and minimum TWBR with TWI prescaler of 1.
    // Rounded down to nearest integer.
    const uint32_t TWI_FREQ_MAX = F_CPU / ( ( 1 << CLKPR ) * ( 16 + 2 * 0x00 * 1 ) );

    // Achievable minimum TWI frequency with current CPU frequency, CLK prescaler and maximum TWBR with TWI prescaler of 1.
    // Rounded up to nearest integer.
    const uint32_t DIVISOR = ( ( 1 << CLKPR  ) * ( 16 + 2 * 0xFF * 1 ) );
    const uint32_t TWI_FREQ_MIN = (F_CPU + (DIVISOR - 1)) / DIVISOR;

    if (twi_freq > TWI_FREQ_MAX)
    {
        twi_freq = TWI_FREQ_MAX;
    }
    else if (twi_freq < TWI_FREQ_MIN)
    {
        twi_freq = TWI_FREQ_MIN;
    }

    // TWI bit rate.
    // §21.5.2 Bit Rate Generator Unit
    // §8.12.2 CLKPR – Clock Prescale Register
    byte bit_rate = (F_CPU / (1 << CLKPR) / twi_freq - 16) / 2

    TWBR = bit_rate;

    // Check.
    const uint32_t twi_freq = F_CPU / ( ( 1 << CLKPR ) * ( 16 + 2 * TWBR * 1 ) );
}

Note that smbus is a flag set elsewhere (global or class member) to indicate SMBus mode.

Just to confirm, in case anyone else is wondering, the second pair of equations in my question are the correct ones which take the CPU clock prescaler (CLKPR) into account.
TWI clock frequency:

And solving for TWBR:


text:
Is a PWM phase duration set with OCR1A a reliable way to communicate values to other Arduinos?
I am working on communicating 4 switch states across multiple Arduinos using only one pin. It must be as fast as conceivably possible.
Currently I have a master Arduino reading all 4 switches (multiplexing) and encoding them as 4-bit values: 0001 = 0, 0010 = 1, 0011 = 2 and so on up to 1111 = 15. I am thinking of assigning the low and high pulse duration/width, (+1) to produce a PWM square wave. So 1+0=1, 1+1=2, 1+2=3 ... 1+15=16. The high width (or low width) will hold the muxed value (+1.) Each slave would read this muxed value and demux it to get the state of all 4 switches.
Now to my concern: Is this approach safe and reliable? Or should I triple up the values: 1=3, 2=6, 3=9 ... to build in some tolerance and prevent some time misread due to some miss-interpolations? My switches control motors and a misread could have some unpleasant consequences.
I am using the Arduino's internal crystal, nothing external.
As a side note: I am actuality using Seeeduinos XIAO and not an Arduino. I started working on the timer based PWM writing and reading aspect, but it turns out to be quite complicated as there is not a lot of exaples to be found.

Please define "reliable" in aspects of hardware and software. -- HW: How long are the wires between the reading Arduino and the motor Arduinos? How much interferences do you expect? -- SW: You could use multiple readings in the receivers and a majority decision. -- Radio control servos get their position command by a pulse width, 1 to 2 ms every 20ms. The resolution is 1% or better. Expensive models in delicate conditions (think about high speed airplanes) are controlled by this. So PWM is a way with some reliability.

Why not just use Serial? You can use some pretty fast baud rates reliably and you only need 1 wire for transmission only.

The Arduino PWM output goes from 0 to 255, so you could multiply by 15 for a maximum value of 240 to give a greater margin of error. Though the serial option is better. You could send data packets with CRC/ECC for greater reliability.

Actually, you could do both PWM and serial. The receivers could compare the two and only act if they agree whilst flagging discrepancies.

This is presumably for an e-stop? Would you ever want to e-stoo a single motor? Is binary sufficient here?

@thebusybee You suggestions are exactly the directions I was heading. Thank you for mentioning interference! All wires are under 8 inches and should be hopefully not too close to anything discharging interference.

@Majenko serial is to slow. I want something supper fast.

@tim good point. I think I will be multiplying by 6, which will be giving me a 3 point offset in either direction.

The ATMega328P is capable of 2MBaud. That's 200,000 potential updates of your switches per second. Is that not "super fast" enough? Most of the slowdown of serial is the Arduino's libraries which are inefficient. Access the UART registers directly for extra speediness.

@DaveNewton It is true that a good portion of the logic is e-stop related. Which now gives me the idea of splitting up some of the logic. I could use a superseding e-stop very short pulse, to obtain a faster read, just when the main motor gets turned on. This would dramatically speed up things!

@MeSo2 That's the approach I would take, although in fairness, serial should be plenty fast enough. My view of an e-stop is "U STOPS ALL TEH THINGS NOW!" and post-e-stop comms can do whatever it wants. This also allows the e-stop to be tied to an interrupt pin as if each unit had its own e-stop slap switch. Any post-mortem comms can be handled once the unit is in the e-stop state.

@MeSo2 While I haven't tried anything like this for CNC/life-threatening-car-like-things, I have done it with robots using separate control modules, w/ serial protocols. High-priority msgs were handled extremely quickly, w/ e-stop equivalents handled in <1-2ms (500/sec). For comparison, the SawStop stops in ~5ms (200/sec), airbag deploys are ~50ms (20/sec).

@Majenko Access the UART registers directly ... I did not know you can do that with serial. Having to learn about timers was taxing as is; not sure if I have it in me to learn about UART registers.

In my opinion your timer approach has no benefits over using UART like majenko suggested. If it has to be fast you'd have to measure pulse lengths with high precision and it costs CPU time - even if you use interrupts.


text:
Softwareserial send wrong values
I'm trying to use softwareserial to exchange datas with a sensor.
After some tries without any answer from the sensor, I checked the arduino TX with my scope and what I've seen is not what I've sended.
My original byte array (before the setup function):
static byte simple_write[] = {0xfe, 0x41, 0x00, 0x80, 0x01, 0x10, 0x28, 0x7e};

What I got on my scope:
0X77 , 0x61 , 0x69 , 0x74 , ...
Every single sent byte is wrong. I don't understand why.
The only thing on the way is a bridge divider to reduce 5V TTL from the arduino to 3,3V CMOS.
If someone have an idea, thanks in advance.
EDIT2: I use IS.MDuino.21+ (ATmega2560)
EDIT: Here are the parts of my code who involve the softwareserial
    #include "SoftwareSerial.h"

    SoftwareSerial LP8_Serial(1, 0);

    static byte simple_write[] = {0xfe, 0x41, 0x00, 0x80, 0x01, 0x10, 0x28, 0x7e}; //Write 0x010 to address 0x0080

void setup(){
LP8_Serial.begin(9600); //Opens the virtual serial port with baud of 9600
}

void loop(){

LP8_val1 = GetDatas_uart();

}

int GetDatas_uart() {
  if (first_loop == 0) {
    //reset_device();  // includes a 500 msec delay
    sendRequest(simple_write, 8, 4); // send to address 0x0080 a 0x10
    first_loop = 1;
  }
  else
    sendRequest(write_to_0x20, 8, 4); // send to address 0x0080 a 0x10
  delay(2000);
  unsigned long valCO2 = getValue(response);
  delay(3000);
  Serial.println("Now reading 32 bytes");   //sendRequest(read_16_bytes,7,21);
  sendRequest(read_32_bytes, 7, 37);
  Serial.print("CO2 from 0x9a-0x9b = ");
  Serial.print(response[29], HEX);
  Serial.print(response[30], HEX);
  Serial.print(" = ");
  int decimal = 256 * response[29] + response[30];
  Serial.print(decimal);
  Serial.println("d");

  return decimal;
}

void sendRequest(byte packet[], int m, int n)
{
  while (!LP8_Serial.available()) //keep sending request until we start to get a response
  {
    Serial.println("waiting for Software.serial port availability");
    LP8_Serial.write(packet, m);
    //LP8_Serial.write(simple_write, m);
    delay(1000); // Necessary to get consistent loading of response[i]
  }
  int timeout = 0; //set a timeout counter
  while (LP8_Serial.available() < n ) //Wait to get a n byte response
  {
    timeout++;
    if (timeout > 10) //if it takes too long there was probably an error
    {
      while (LP8_Serial.available()) //flush whatever we have
        LP8_Serial.read();
      break; //exit and try again
    }
    delay(50);
  }
  for (int i = 0; i < n; i++)
  {
    response[i] = LP8_Serial.read();
    //    Serial.print("response[i] = ");
    Serial.print("response[");
    Serial.print(i);
    Serial.print("] = ");
    Serial.println(response[i], HEX);
  }
  Serial.print("\n\n");
  Serial.flush();
}

Please show us your code. How did you analyse the scope data? Through a function of the scope? Are you sure that is configured correctly?

The code is pretty big. It's the only function who don't work. I will add the concerned parts in the original message. But yes, it's through a function of my scope.

Then please create a smaller working example code, that shows your problem, by cutting away code, that does not have something to do with the SoftwareSerial code

@chrisl, it is ATmega2560 and OP uses SoftwareSerial on hardware Serial pins (on Mega!)

So than this answer might be fitting here

Sooo, I feel a little ashamed...
After re-reading the documentation of the Arduino from Industrial Shields I use (model 21+), I discovered that using Serial0 on this board is unadvised because these pins are shared with USB.
I connected my serial wires to the Serial1 connection and now, my scope show me exactly what I wanted to see on my TX line.
Sorry for that. Like often, the problem whas between the screen and the chair.
Thanks,

so you used SoftwareSerial on hardware serial pins? Arduino Mega has 4 hardware Serials. don't use SoftwareSerial library with Arduibo Mega

Yes. I did. When I use Arduino, I rarely bother to use hardware serial except for debugging. I needed a "ready to use" electronic system for a project.

I don't meant an external USB-to-TLL-Serial, but the on chip UART peripheral

This module (Industrial Shields M21+) provide only TTL and RS232 level serials.
Moreover, I wanted to go fast with a new sensor and someone wrote an arduino library for it. The example use a softwareserial, so basicaly "Copy / Paste / Check".

and then quick to Stack Exchange


text:
How do I check if my board is connected to the internet?
Let me get this straight, I'm trying to see my ESP32 is connected to the internet or not, not Wi-Fi, as at times the board is able to connect to Wi-Fi, but not able to contact any servers, due to router issues.
I want to check, if the board is connected the internet or not, how do I do this?
What I have so far:-
char ssid[] = "Youreally";
char pass[] = "WannaKnow";

void setup(){
WiFi.begin(ssid, pass);
Serial.begin(115200);
}

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

ping a known server

I usually ping 8.8.8.8 - Google's DNS servers.

@Majenko What is the maximum frequency allowed for those

and where can I find information about this

No idea. It's a massive cluster of globally distributed servers, and a few pings would disappear amongst the huge amount of DNS traffic.

So, I can contact it frequently without getting banned

Depends what you term "frequently". Once every few minutes or so is no problem.

What does "freaquently" mean for you? Once a second, once per hour? Isn't it enough to check right after the wifi setup? Whatever service you use on the internet would give you an error once it is not reachable...

To make Pinging easier FabGL has a ping example and an ICMP class.

@Majenko Maybe around 5 seconds

5 seconds is way too often, and short polling is not needed for low-lag detection. Just connect to any public websocket server, pass a callback to onEvent, listening for WStype_DISCONNECTED event type, upon which you can be 90% sure the internet is out. I would then use an http request to try to download my own website's robots.txt to confirm. No pinging, no policy violations or ISP consternation.

As you would be having some sort of connectivity except WiFi you could check that on regular basis in your loop, for instance when using MQTT I would check:
if (!mqttClient->connected())

and then based on the result I would test:
if (WiFi.status() != WL_CONNECTED)

so I can handle the relevant layer.


text:
Is SoftwareSerial possible for Samd21 boards?
I have a SAMD21G18A-MUT custom board, which has 6 'grove' connectors, of which two are I2C In and out (sharing the same MCU Pins) and also has 2 'special' 8 pin connectors attaching to Particulate Matter sensors that connect to :

PA 14, (9, 8)[Sercom 2 alt]; PB8,PA6 [PWM], PB23

PA 15,(11,10)[Sercom 0]; PB9, PA7 [PWM], PB22

which implement serial interfaces with additional control wires.
The Grove ports are :

ADC 0 (A0 & A1); Pins 9,10 [accessible only to SERCOM 0]
ADC 1 (A2 & A3); Pins 47,3 [not accessible by SERCOM]
GPIO D0/D1 [SERCOM4_ALT]; (used)  Pins 21,22
UART Tx/RX [Sercom 1]. Pins 27,28
I2C Pins (SDA, SCL), (Pins 31,32)  [SERCOM 1 PAD 0 & 1]  (only one I2C port  Used)
Debug Connector, ({ins 45,46) [SERCOM 1 PAD 2 & 3]
USB Pins (D+, D-, (Pins (33,34) [SERCOM 3]  (Used when programming)

SERCOM 5 appears to be unused, but not accessible by either ADC Port.
Do not ask me how the overloading of SERCOM 1 works...IDK
So, all but 1 Sercom ports are used up and yet I need to connect up 2 additional serial devices; a Wind sensor and a Rain Gauge.
Obviously I can connect one of them to UART Tx/Rx Sercom1; but the other one can physically connect only to one of the ADC Ports. But the only available Sercom for those pins is already used.
So, I think I need to implement SoftwareSerial on (say) A0 and A1 for the second device that I need to connect.
Any thoughts on if or how this can be done ?
My only current alternative is to add a whole new MCU Board, but that brings on space and mounting considerations.


text:
How or why is the Arduino keeping a LED on when the input putton is no longer pressed?
I'm trying to follow lesson 6 of the Adafruit Arduino lessons on digital inputs found here.
I have the same code and the board setup the exact same and the code it is working exactly as it should. I just can't figure out WHY.
Board:

Code:
    /*
Adafruit Arduino - Lesson 6. Inputs
*/

int ledPin = 5;
int buttonApin = 9;
int buttonBpin = 8;

byte leds = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
}

void loop()
{
  if (digitalRead(buttonApin) == LOW)
  {
    digitalWrite(ledPin, HIGH);
  }
  if (digitalRead(buttonBpin) == LOW)
  {
    digitalWrite(ledPin, LOW);
  }
}

Why does the light turn on when one of he buttons is pressed once and turn off when the other button is pressed once. I don't understand the mechanism of how the press is being remembered.
There doesn't seem to be anything in the code that can explain why the button stays on even when no longer pressed, so it should be some component? But what?
Can anyone help explain why this is working?

you are falling into the trap of thinking this ... if the button is pressed and the light turns on, then the light must turn off if the button is released ... which part of the code tells the light to turn off when buttonApin is released?

Look at the code carefully - If button A is low turn the led on and only if button B is low then will it turn off, so if you press button B it will turn off

The port manipulated by digitalWrite maintains a state, kind of like a variable.

I would like to add two more cents. It is a wonderful explanation already from @chrisl
Here is the simulation screenshot for your example:

if you consider mechanical switches, they really cut the connection so that the light will be OFF. When you want the light to be on, you will move the switch to the ON position(in this example, hold the button)

In the case of Microcontrollers, and in the given example, it is more like two people communicating.

The 1st person is looking at the switches. The 2nd person is
controlling the LED
1st person is instructed to notify the second person about anybody pressing the switches
whenever the ON switch is pressed, the 1st person will immediately tell the second person to turn on the LED
Whenever the OFF switch is pressed, the 1st person will tell the 2nd person to turn off the LED

The behaviour of the program much depends on the requirement.

if you would love to see the LED turn OFF when you want to, you can try this example

Code:
/*
  Adafruit Arduino - Lesson 6. Inputs
*/

int ledPin = 5;
int buttonApin = 9;
//int buttonBpin = 8;

byte leds = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
}

void loop()
{
  digitalWrite(ledPin, !digitalRead(buttonApin));
}

If you read the lesson below the first picture and above parts it states: "Pressing the button nearer the top of the breadboard will turn the LED on, pressing the other button will turn the LED off." Try pressing and expect the LED to turn off.

The press is not being remembered. Instead, the output pin "remembers" its state: digitalWrite(HIGH) sets the pin to high and the pin will remain high until you call digitalWrite(LOW).

It might be interesting to look at the reasons why the pin remembers its state (as described in other answers).
Every digital pin has dedicated digital output hardware, which can drive the pin to HIGH (Vcc, supply voltage) or LOW (ground). This output hardware is internally tied to a SFR (Special Function Register). A register is a piece of specific memory hardware in the microcontroller of the Arduino. The digital output hardware is electrically hardwired to some of those special function registers. Thus its state depends on what is saved in those registers. Since the registers hold their state during the running time of the Arduino (they are memory after all), the digital output hardware will also not change, until you change the corresponding registers (through executing digitalWrite()).
You can even manipulate the SFRs directly. This can help with programming time sensitive code or setting/reading multiple pins at once. All the digital pins are sorted into so called ports, which can hold up to 8 pins. For each port there are the following SFRs (the x stands for the character of the corresponding port, like PORTA, PORTB, ...), where the bits in these (1 byte big) registers correspond to one pin each:

DDRx: This register is the Data Direction Register. It controls if the corresponding pins are set as digital output or input.
PORTx: This register sets the output state. digitalWrite(pin, HIGH) will write a 1 to the corresponding bit of this register, which then sets the pin to HIGH. If the corresponding pin is set as input, setting a 1 in the corresponding bit of the PORT register will enable the interal pullup resistor of that pin.
PINx: This register holds the current state of the corresponding pins, so you can use it to read a digital pin.

You can also read this reference article. Also the datasheet of the used microcontroller also contains all information about what SFRs exist and how they are used to perform specific actions.


text:
How can i reduce my global variable use? Attiny85
I'm trying to compile my code but i keep exceeding my global variable memory by 12%.
Is there anything i can do in my code to further reduce RAM usage?
Or do i have to do modifications to the libraries I'm using?
Here is my main program:
    #include <MIDI.h>
#include <FastLED.h>
#include <SoftwareSerial.h>

#define LED_PIN 3
#define NUM_LEDS 60
#define LEDMAP 0xAB5AB5AB5AB5AB5
#define OFFSET 36
#define RANGECHECK if (pitch > 35 && pitch < 96)

SoftwareSerial softSerial(2, 4);
CRGB leds[NUM_LEDS];

MIDI_CREATE_INSTANCE(SoftwareSerial, softSerial, midiB);

void setup() {
  FastLED.addLeds<WS2811, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.clear(true);
  midiB.begin(MIDI_CHANNEL_OMNI);
  midiB.setHandleNoteOn(HandleOn);
  midiB.setHandleNoteOff(HandleOff);
}

void loop() {
  midiB.read();
}

void HandleOn(byte channel, byte pitch, byte velocity)
{
  RANGECHECK
  {
    leds[pitch - OFFSET] = bitRead(LEDMAP, (pitch - OFFSET)) ? CRGB::NavajoWhite : CRGB::Salmon;
    FastLED.show();
  }
}

void HandleOff(byte channel, byte pitch, byte velocity)
{
  RANGECHECK
  {
    leds[pitch - OFFSET] = CRGB::Black;
    FastLED.show();
  }
}

I've reached my limit in optimizing my RAM usage here. Any suggestions for optimizing my code would be appreciated.

Since i don't use sysex messages, i got my RAM usage down to 84% by setting the SysExMaxSize
in midi_settings.h
to 0.

FastLED needs to keep the colors of all the pixel in RAM, so that is using a lot of RAM.
To get around this, you could use a strategy that generates the pixel data on the fly as you send it out to the strings. Here is an example of a project that does that...
https://wp.josh.com/2021/04/21/build-a-live-scrolling-tickertape/
Also, SoftSerial keeps a buffer (looks like 64 bytes?) which also uses some RAM. You could use a different approach to serial communications that does not allocate such a large buffer. It would take work, but you could even process the midi bytes as they were received and not need any byte buffer.

I already tried redefining _SS_MAX_RX_BUFF in my code, but this had no effect on the global variables used


text:
which is the best way to declare Serial while creating Arduino library?
Well, I am trying make a library for HMI display. display and Arduino comminicate with Serial. So I will so many times Serial port. Generally I will use Serial.write commend. if I examine other libraries, there are lots way to declare serial. Why and which is the best I want to learn.
there I have seen declaring Serial methods.
Method 1
in library .h file
nothing

in library .cpp file
#include <SoftwareSerial.h>

SoftwareSerial SIM(RX_PIN,TX_PIN);

void KapadokyaGSM::basla(){
    SIM.begin(9600);
  _tampon.reserve(255);
}

Method 2
in library .h file
public:
EasyNex(HardwareSerial& serial);
...
private:
HardwareSerial* _serial;
...

in library .cpp file
EasyNex::EasyNex(HardwareSerial& serial){  // Constructor's parameter is the Serial we want to use
_serial = &serial;
}

void EasyNex::begin(unsigned long baud){
_serial->begin(baud);  // We pass the initialization data to the objects (baud rate) default: 9600
delay(100);            // Wait for the Serial to initialize

Also I have seen declaring with Stream but now i didnt find example codes. So finally Can anyone tell me what is the best for declearing Serial in library. it can be for only hardware serial or both

The basic concept that you're asking about is called dependency injection.

As regards the use of Stream:
I usually use Stream instead of HardwareSerial because:

It allows the use of other serial devices, like SoftwareSerial or USBSerial that aren't "Hardware" UARTs.
It even allows the use of non-serial systems, like sending data over networks or wireless devices

However it means:

The user has to manually initialize their serial object / device as Stream has no facility for setting things like baud rates.

Can you show me a tutorial, or github library which is using Stream.

@mehmet try this one: https://github.com/MajenkoLibraries/ICSC/tree/master/src

There is no best way, the first is using a global variable, being static. The second is dynamically (or at least to pass a serial instance).
It depends on your use

If you want your code always to work with the same declared serial (hardware or serial) instance, you can use the first method, as it is the easiest.
If you want your serial hardware port to be flexible (your code to work e.g. with a selectable hardware serial port on an Arduino Mega), you need the second.
If you want to your serial port to be either software or hardware, you can use the second method, but you need another type (not the mentioned HardwareSerial class. I don't know by head the parent class of SoftwareSerial and HardwareSerial (The Stream class you mentioned could be a common parent class).

there is no Serial base class

Can i ask a last question, why second method uses "->" and Why not "." Such us _serial.begin(baud). Is this totally same

If you have access to the object itself, e.g., Serial, you can say Serial.println(). If your library only has a pointer to the object, you have use ->, the dereference operator: serialPtr->println(). The result is the same: calling the object's 'println()' member. The difference is in how the compiled code gets you to that member.

@Juraj Thanks for that addition (I was not sure, so I removed the comment about not being sure and the statement in my answer).

@mehmet, it is common C++ object member access you asked about


text:
WiFi.h library, Issues with client.print()
I have an esp32 development board that I am trying to use to get Bitcoin price data using the Coinbase api.
On the Coinbase developers website, they give this example Curl command to get Bitcoin price data:
curl https://api.coinbase.com/v2/prices/spot?currency=USD

I put this into a command prompt on my computer and it works as expected. So I used this as a template for my HTTP get statement in my Arduino sketch.
if (!client.connect("api.coinbase.com",80)) {
  Serial.println("Connection failed.");
}
delay(100);
client.print("GET /v2/prices/spot?currency=USD HTTP/1.1\r\nHost: api.coinbase.com\r\n\n");

However, when sent from my esp32, I get a "301 Moved Permanently" error. But the new Location specified in the response is exactly where I was accessing in the first place!
HTTP/1.1 301 Moved Permanently
Date: Sun, 22 Aug 2021 22:15:50 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: max-age=3600
Expires: Sun, 22 Aug 2021 23:15:50 GMT
Location: https://api.coinbase.com/v2/prices/spot?currency=USD
Set-Cookie: __cf_bm=ea2a2031c3fa42b910632c627d2ed4c48824323d-1629670550-1800-ARKBVsdI9BWVOOTWmKXp+cMv0hcxMU4YAOR1JyHtH2Q49TEBkGuGNXLxSMIanzC7W8Ga9uXBCtdo+Th7Fgir8Jc=; path=/; expires=Sun, 22-Aug-21 22:45:50 GMT; domain=.coinbase.com; HttpOnly
X-Content-Type-Options: nosniff
Server: cloudflare
CF-RAY: 682f764a88f3a3eb-PIT

Why does this HTTP request work with Curl, but not when sent from the esp32?

HTTP != HTTPS...

It's not an error, it's an HTTP redirect.
The HTTP request worked as expected on the ESP32. Curl automatically handles the redirect. Your homegrown HTTP implementation does not.
The Coinbase API requires you to use HTTPS and does not allow HTTP. This protects private information, like API keys and information the API may return. It also verifies that you're talking to the real Coinbase API server and not an impersonator.
You'll need to use port 443 and the WiFiClientSecure library instead of WiFiClient library. Or even better, you could use an HTTP client that already implements the HTTP protocol, like HTTPClient.


text:
Why are transistors necessary before LEDs?
Below is the small RGB LED circuit I'm trying to build. My question is why are the 3 transistors necessary, and can I not link the LEDs directly?

I doubt if the LEDs will ever light up with 4.7k base resistor and 4.7k resistor in series with LEDs

@SBF they will not. They’re NPN transistors on the wrong side of the load. Also, the LEDs will not be driven higher than about 0.5mA each, which might be enough, but will not be very bright.

We don't know what the supply voltage is from that circuit. It's not a good circuit at all.

@StarCat They're not on the "wrong" side of the load. There's no "wrong" side. They're just not on the "traditional" side for simple saturation switching. Instead they (and their resistors) form part of the base current path and severely limit the amount of base current that can flow. Your current of 0.5mA for each LED is bang on though. I make it 594uA per LED. A pitiful current.

@Majenko, agreed, when I said "wrong" I meant this was not the most logical or efficient placement of the switching NPN transistors. Your explanation is correct of course.

@StarCat would you care to explain why it is inefficient and how this circuit could be improved (apart from the way too big resistors)? Thanks.

NPN transistors in this configuration will not fully turn on because the amount of current they can pass between collector and emitter is limited by the current that flows from the base through the emitter (which is limited because of the high base resistance and the small voltage difference between base and emitter). There will be a 0.7V voltage drop between collector and emitter. A better placement of NPN transistors would be between ground (connected to the emitter) and the negative pins of the LEDs (to the collectors). This allows the transistors to turn fully on (more like a switch).

The port pins of your Nano can deliver current in a quite limited range, and six LEDs need a lot more to shine brightly. The transistors are amplifying the available current.
However, 4k7 resistors in series with each LED will not allow enough current to let them shine well. Reduce the resistors by a factor of at least 10. Read the LEDs' data sheet and apply Ohm's law.

The transistors are connected as an emitter follower, not as a switch. The transistors are acting as current amplifiers. The emitter voltage will rise to approximately the voltage on its base - about 0.7V. That places the voltage at about (5 - 0.7 = 4.3V) at the emitter. Since the collectors of transistors are powered by Vin I would guess you have at least 6 volts available assuming a 5V Nano so the extra voltage drop across the transistors will be dissipated as heat. The base resistors are not needed but should not affect performance much. The available current at the emitter would be the Hfe of the transistor times the base current. Each LED will consume about 2 milliamps making the load on each of the transistor around 12 milliamps. It should work fine. You can divide the 12 milliamps of the LEDs by the Hfe of the transistor to get the base load.

Each LED consumes up to 20mA and You are using three LEDs at each I/O port in Arduino Nano. In other word, each part consumes 120mA.
The important thing is Arduino Nano I/O provides 20mA at maximum. So if you want to control 120mA by I/O ports, you must use transistor to support huge current.
Transistor can afford current up to 500mA.

I see 6 LEDs controlled by one pin

How do you know how much current the transistor can handle? The OP did not specify the transistor used...

He said "Why transistors are necessary" not "Why this transistors are necssary"

@Juraj I see 12 LEDs controlled by pins 6/10

3 transistors on pins D2, D6 and D10 and 18 LEDs

The emitors of the transistors to D6/D10 are connected ;-)

yes I see, but I guess that is only an error on the schematics and not on the real circuit


text:
ArduinoJson library parsing error
I am trying to retrieve JSON mqtt message I received in ESP32.
void mqttMsgCallback(char* topic, byte* payload, unsigned int length) {
    payload[length] = '\0';
    String _message = String((char*)payload);
    String _topic = String(topic);
    if (_topic.equals("Sys.GetInfo/"+getMacAddr()) == 1)
    {
      Serial.println("Message arrived for sys.GetInfo");
      StaticJsonDocument <256> msg1;
      Serial.println(_message);
      deserializeJson(msg1,_message);
      String callbackTopic = msg1["callbackTopic"];
      Serial.println(callbackTopic);
    }
}

The issue is when I publish mosquitto_pub -t "Sys.GetInfo/2462ABFC2CD0" -m "{"callbackTopic" : "1234"}" it works well like callbackTopic as 1234.
but when I publish mosquitto_pub -t "Sys.GetInfo/2462ABFC2CD0" -m "{"callbackTopic" : "xyz"}"  it prints callbackTopic value as null.
Please point me if I an missing something.
Arduino version 1.8.15
ArduinoJson : 6.18.2
Borad : ESP32
Thanks

Check the return value of deserializeJson() to see if it can even parse it as valid JSON.  Maybe you need '{"callbackTopic" : "xyz"}' (single quotes round the outside) to preserve the quotes on the inside.

@Majenko it works when i publish like '{"callbackTopic" : "xyz"}'. Thanks
why the message with "" works when callbackTopic value is numeric

Probably because the value is numeric. 1234 is a valid "thing" - xyz isn't.  "xyz" is, though, and if your shell is stripping the " because it's not either escaped or encapsulated within single quotes, then it can't parse xyz as a valid "thing".

payload[length] = '\0'; how do you know there is a length + 1 position available?

Your shell is stripping the " from inside the string. If you run the command:
$ echo "{"callbackTopic" : "xyz"}"

you get:
{callbackTopic : xyz}

so you see all the quotes are stripped. xyz isn't something that ArduinoJSON can parse. But 1234 is, so with the quotes stripped it's still considered valid.
You need to ensure the quotes aren't removed. There's two ways of doing this: escaping them, or encapsulating the string in single quotes which gives a more "literal" interpretation of the contents than double quotes:
Escaping:
"{\"callbackTopic\" : \"xyz\"}"

Single quotes:
'{"callbackTopic" : "xyz"}'

Either of those when used as a parameter to a command work - like:
$ echo '{"callbackTopic" : "xyz"}'
{"callbackTopic" : "xyz"}

To parse an ArduinoJSON one simply needs to
  String JSONpayload = "some JSON here";
  StaticJsonDocument <512> geoLocationInfoJson;
  DeserializationError error = deserializeJson(geoLocationInfoJson, JSONpayload);
  if (error) {
    this->mserial->printStrln("Error deserializing JSON");
  }

To use the values within the StaticJsonDocument one first needs to
if ( geoLocationInfoJson.isNull() == true ){
  String dataStr="NULL geoLocation data.\n";
  Serial.print( dataStr);
  return true;
}

next, is required to verify if a key exists. If TRUE, then is mandatory first to get the desired value into a corresponding data type, like below, and only afterward work on it, for instance, send it as a BLE message string:
if(this->interface->geoLocationInfoJson.containsKey("lat")){
  float lat = this->interface->geoLocationInfoJson["lat"];
  dataStr += "Latitude: "+ String(lat,4) + "\n";
}
if(this->interface->geoLocationInfoJson.containsKey("lon")){
  float lon = this->interface->geoLocationInfoJson["lon"];
  dataStr += "Longitude: "+ String(lon,4) + "\n";
}

if(this->interface->geoLocationInfoJson.containsKey("regionName"))
  dataStr += String(this->interface->geoLocationInfoJson["regionName"].as<char*>()) + ", ";

The full code above is available on this GitHub repository:
https://github.com/aeonSolutions/aeonlabs-ESP32-C-Base-Firmware-Libraries

what question does this answer?

The one of successfully parsing an arduinojson object. And access key, value pairs it holds

that is not the question asked on top of this page

Read between the lines ?

the existing accepted answer shows what the problem was

As I mentioned before. Read between the lines.


text:
5-bit communication method?
OK, I'm working on a project where I want to have multiple toggle switches create a "code" to determine further actions. This is essentially 5-bit communication process that will create output with a 32-bit range of outcomes from 00000 to 11111.
I'm testing the method with three switches, so if the first and third switch are HIGH/on it will read 101. Second and third, 011 etc. I'm not versed enough to know if there is a better method here, but is there a better way to do this?
    // Define the pins being used
int pin_switch = 10;
int pin_switch2 = 11;
int pin_switch3 = 12;

// create int for 3-digit code
int code = 000;

void setup()
{
    Serial.begin(9600);
    pinMode(pin_switch, INPUT);
    pinMode(pin_switch2, INPUT);
    pinMode(pin_switch3, INPUT);
}

void loop()
{

if pin_switch == HIGH;
    {code += 100;}

if pin_switch2 == HIGH;
    {code += 10;}

if pin_switch3 == HIGH;
    {code += 1;}

Serial.print(code);

// operate based on code output
if code == 101;
    {do 101 stuff}

if code == 001
    {do 001 stuff}

// reset code for next loop so numbers don't keep rising
code = 000;
}

Note: don't write leading zeros in a decimal number in C or C++ (or a bunch of other languages) - the numbers will be treated as octal rather than decimal which is very rarely what you want.

It would be more convenient and less typing if you put all your switch pins in an array. That way you can loop over it to configure the ports and read them rather than copy/pasting the "same" code over and over.
The calculation of the resulting code is a classic "shift and add" loop. I put both the decimal version you seem to want and the more "usual" binary version in the snippet below.
The idea behind that sort of loop is:

start with an empty (zero) code
multiply the code by 10 (or left-shift once for binary)
read a switch, add 1 to the code if it is HIGH
go back to step 2 if there are more switches.

The value of the switches already read get "pushed" one slot to the left before reading the next switch, resulting in the code you want.
The order in which you list the ports in the array is important: the first port in the array will change the leftmost (most significant) digit/bit in the code.
const uint8_t switch_pin[] = { 10, 11, 12 };
const uint8_t num_switches = sizeof(switch_pin)/sizeof(switch_pin[0]);

void setup() {
  // Set all switch pins to input mode
  for (uint8_t i = 0; i < num_switches; ++i) {
    pinMode(switch_pin[i], INPUT);
  }
  Serial.begin(9600);
}

void loop() {
  int code = 0;
  // Read each switch and compute the code
  for (uint8_t i = 0; i < num_switches; ++i) {
    // If the code is supposed to be in decimal
    code = code * 10;
    code += digitalRead(switch_pin[i]);
    /* For a binary version, code only needs to be 8 bits long:
    code <<= 1;
    code |= digitalRead(switch_pin[i]);
    */
  }

  // Do stuff with the code
  Serial.println(code);
  delay(200);
}

Oh thank you Mat, I think Shift and Add is the terminology I was lacking!
I think I do want to go Binary, I'm thinking I will expand this to five switches so the shifting aspect simplifies that in my mind.
Looking at your code here: code <<= 1;
How would I shift and add for the other parts of the code? The prior would output 010, right? Would I just need to do <<<=1; AND <<= 1 to get 110?
Thank you for the help.

If code is 1010, code <<= 1 (which is the same as code = code << 1) will result in 10100 (shift left, insert a zero at the right). The code |= 1; would "fill" the last position to 10101. code |= 0; would do nothing.

Unfortunately your code is all over the place. You have to use C/C++ syntax, which you don't. Also you don't actually read any input.

if statements look like this:
  if(condition){
      my_code();
  }

if(pin_switch == HIGH) (corrected syntax) will always be false, since pin_switch is of value 10. Its just the pin number. To actually read the pin, you need to use digitalRead() like this:
  if(digitalRead(pin_switch) == HIGH)

or even simpler
  if(digitalRead(pin_switch))

It seems that you want to manipulate the bits with code += 100;, but the compiler takes numbers as decimal. So you are adding 100 to code. Please look into the bitwise operators. Also: You can actually write numbers in binary or hex by using 0b101 or 0xF3 respectively (the values here are just examples). This also means, that int code = 000; is the same as int code = 0;.

To build the 3 digit code from input you could put them together via bitwise operators:
code = (digitalRead(pin_switch3) << 2) | (digitalRead(pin_switch2) << 1) | digitalRead(pin_switch);

Depending on your used Arduino and the used pins you can get this even easier. The pins are sorted into ports. Each port has a Special Function register, which holds the current state of the pins. You can mask away any unwanted pins and shift the number to be right justified. For example: On the Uno and Nano pins 2 to 7 belong to PORTD. So, if you use pins 2 to 4 for your 3 switches, you could get the code like:
code = (PIND & 0b00011100) >> 2;

This is a bit more difficult to understand, but it will help you later on, when pursuing Arduino more.

For deciding what action to do based on the code, it is normally easier to use a switch case statement:
switch(code){
    case 0b101:
        do_something();
        break;
    case 0b011:
        do_something_else();
        break;
}

Thank you! Yes my code was thrown together hastily from an example to test the method.
Really appreciate the direction here, I'll dig into bitwise operators more!

@Mulcch oops, corrected a small error. I used PORTD instead of PIND. The former is used to set the output state of a pin, the latter reflects the current input state.

Thanks for catching! I'm not sure I'll go that route, but really helpful to know about that.