message:
Using MAX30100 SpO2 value to turn on LED

max30100 i2c sensor gives heartrate and spo2 reading in serial and also can show values in lcd display. I want to show it's indication via LED.

If SpO2 value <94 , it will turn on Red led in digital pin 4

If SpO2 value >=94, it will urn on Green led in digital pin 5

Here **pox.getSpO2()** gives the SpO2 value.

How can I use this value to toggle between two digital pin. I understand it's easier to read analog pin value for toggling but I am searching for guidelines how I2C values can be use for this condition.

Thank you.

Here is the minimalistic code of SpO2

    #include <Wire.h>
    #include "MAX30100_PulseOximeter.h"
    #define REPORTING_PERIOD_MS     1000

    PulseOximeter pox;
    uint32_t tsLastReport = 0;

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

        Serial.print("Initializing pulse oximeter..");

        if (!pox.begin()) {
            Serial.println("FAILED");
            for(;;);
        } else {
            Serial.println("SUCCESS");
        }
    }

    void loop()
    {

        pox.update();

        if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
            Serial.print("SpO2:");
            Serial.print(pox.getSpO2());
            Serial.println("%");

            tsLastReport = millis();
        }
    }

body:
You've done all the hard work already by setting the sensor up and managing to read from it.

I'd define a constant for the SpO2 threshold near the top, and convenient names for the pins:

    const uint8_t SpO2_threshold = 94;  // percent
    const uint8_t red_pin = 4;
    const uint8_t green_pin = 5;

Then set the pins to output mode in the `setup()` as usual. (Maybe set them both HIGH (or LOW) too in there, to indicate that no reading has been done yet.)

In the loop, inside the reporting section, simply grab the value and toggle the pins:

    ...
    uint8_t spo2 = pox.getSpO2();
    // Print it out to serial if needed, then:
    if (spo2 < SpO2_threshold) {
      digitalWrite(green_pin, LOW);
      digitalWrite(red_pin, HIGH);
    } else {
      digitalWrite(red_pin, LOW);
      digitalWrite(green_pin, HIGH);
    }

---

A more involved version that pulses one LED (short on time, variable off time) depending on the value read from the sensor. It uses the same technique as the sensor reading timing (the one used in the "blink without delay" example).

Sensor readings are clamped (any value at or below `spo2_min` will result in the fasted blink time, over `spo2_max` the slowest). Then that range is mapped to a range of led off times. Don't use the values in this example, I'm not a medical doctor :-)

    // pin mapping
    const uint8_t led_pin = LED_BUILTIN;

    // sensor readings (%)
    const int spo2_min = 85;
    const int spo2_max = 100;

    // led timings (ms)
    const unsigned long led_off_min = 50;
    const unsigned long led_off_max = 5000;

    unsigned long led_off_time = led_off_max; // variable off time
    const unsigned long led_on_time = 50;     // fixed, short on time

    // sensor reading timing (ms)
    const unsigned long sensor_interval = 1000;

    // led state
    uint8_t led_state = LOW;

    // "timer" state
    unsigned long last_reading = 0;
    unsigned long last_led_toggle = 0;

    void setup() {
      pinMode(led_pin, OUTPUT);
      digitalWrite(led_pin, led_state);

      Serial.begin(9600);

      Serial.print("Initializing pulse oximeter..");
      if (!pox.begin()) {
        Serial.println("FAILED");
        for (;;);
      } else {
        Serial.println("SUCCESS");
      }
    }

    void loop() {
      pox.update();
      unsigned long current_millis = millis();

      /* sensor reading "timer" */
      if (current_millis - last_reading >= sensor_interval)
      {
        last_reading = current_millis;

        int spo2 = pox.getSpO2();

        // clamp reading to expected range
        int clamped = constrain(spo2, spo2_min, spo2_max);
        // map to off time range
        led_off_time = map(clamped,
                           spo2_min, spo2_max,
                           led_off_min, led_off_max);

        char buff[128];
        sprintf_P(buff, PSTR("reading: %d (%%) -> interval: %lu (ms)"),
                  spo2, led_off_time);
        Serial.println(buff);
      }

      /* led toggling "timers" */
      unsigned long led_elapsed = current_millis - last_led_toggle;

      if ((led_state == LOW) && (led_elapsed >= led_off_time))
      {
        last_led_toggle = current_millis;
        led_state = HIGH;
        digitalWrite(led_pin, led_state);
      }
      else if ((led_state == HIGH) && (led_elapsed >= led_on_time))
      {
        last_led_toggle = current_millis;
        led_state = LOW;
        digitalWrite(led_pin, led_state);
      }

    }


sender: user

message:
Comparison of a string received from MQTT/Cloud/Arduino

I am trying to compare the string of data which I am receiving from the MQTT broker. If I receive the keyword faster I want to print "increase motor speed" and when I get slower keyword or any other keyword, I want to print "decrease motor speed". I am not sure how to store the data I receive from mqttClient.read()and then store it in string to then compare it
Below is the snippet of the code where I have added it and it seems not to work correctly in my case. can you look at it and let me know what is the mistake?
````
while (mqttClient.available()) {
Serial.print((char)mqttClient.read());
String ipstring= String("(char)mqttClient.read()");
String fast ="faster";
if((char)mqttClient.read()==fast)
{
Serial.println("increase motor speed");}
else
{
Serial.println("decrease motor speed");
}*
}
````

I have also attached the code for reference.
Thank you!

````
/*
  Azure IoT Hub NB

  This sketch securely connects to an Azure IoT Hub using MQTT over NB IoT/LTE Cat M1.
  It uses a private key stored in the ATECC508A and a self signed public
  certificate for SSL/TLS authetication.

  It publishes a message every 5 seconds to "devices/{deviceId}/messages/events/" topic
  and subscribes to messages on the "devices/{deviceId}/messages/devicebound/#"
  topic.

  The circuit:
  - MKR NB 1500 board
  - Antenna
  - SIM card with a data plan
  - LiPo battery

  The following tutorial on Arduino Project Hub can be used
  to setup your Azure account and the MKR board:

  https://create.arduino.cc/projecthub/Arduino_Genuino/securely-connecting-an-arduino-nb-1500-to-azure-iot-hub-af6470

  This example code is in the public domain.
*/

#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include <utility/ECCX08SelfSignedCert.h>
#include <ArduinoMqttClient.h>
#include <MKRNB.h>

#include "arduino_secrets.h"
int sensorValue;

/////// Enter your sensitive data in arduino_secrets.h
const char pinnumber[]   = SECRET_PINNUMBER;
const char broker[]      = SECRET_BROKER;
String     deviceId      = SECRET_DEVICE_ID;

NB nbAccess;
GPRS gprs;

NBClient      nbClient;            // Used for the TCP socket connection
BearSSLClient sslClient(nbClient); // Used for SSL/TLS connection, integrates with ECC508
MqttClient    mqttClient(sslClient);

unsigned long lastMillis = 0;

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

  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  // reconstruct the self signed cert
  ECCX08SelfSignedCert.beginReconstruction(0, 8);
  ECCX08SelfSignedCert.setCommonName(ECCX08.serialNumber());
  ECCX08SelfSignedCert.endReconstruction();

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

  // Set the ECCX08 slot to use for the private key
  // and the accompanying public certificate for it
  sslClient.setEccSlot(0, ECCX08SelfSignedCert.bytes(), ECCX08SelfSignedCert.length());

  // Set the client id used for MQTT as the device id
  mqttClient.setId(deviceId);

  // Set the username to "<broker>/<device id>/api-version=2018-06-30" and empty password
  String username;

  username += broker;
  username += "/";
  username += deviceId;
  username += "/api-version=2018-06-30";

  mqttClient.setUsernamePassword(username, "");

  // Set the message callback, this function is
  // called when the MQTTClient receives a message
  mqttClient.onMessage(onMessageReceived);
}

void loop() {
  if (nbAccess.status() != NB_READY || gprs.status() != GPRS_READY) {
    connectNB();
  }

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

  // poll for new MQTT messages and send keep alives
  mqttClient.poll();

  // publish a message roughly every 5 seconds.
  if (millis() - lastMillis > 5000) {
    lastMillis = millis();

    publishMessage();
  }
}

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

void connectNB() {
  Serial.println("Attempting to connect to the cellular network");

  while ((nbAccess.begin(pinnumber) != NB_READY) ||
         (gprs.attachGPRS() != GPRS_READY)) {
    // failed, retry
    Serial.print(".");
    delay(1000);
  }

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

void connectMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(broker);
  Serial.println(" ");

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

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

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

void publishMessage() {
  Serial.println("Publishing message");

  // send message, the Print interface can be used to set the message contents
  mqttClient.beginMessage("devices/" + deviceId + "/messages/events/");
  mqttClient.print("hello ");
  sensorValue = analogRead(A0);
  mqttClient.println(sensorValue);
  //mqttClient.print(millis());

  mqttClient.endMessage();
}

void onMessageReceived(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.print("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  while (mqttClient.available()) {
    Serial.print((char)mqttClient.read());
    String ipstring= String("(char)mqttClient.read()");
    String fast ="faster";
    if((char)mqttClient.read()==fast)
    {
      Serial.println("increase motor speed");}
      else
      {
        Serial.println("decrease motor speed");
        }
  }
  Serial.println();

  Serial.println();
}
````

sender: assistant

body:
As I read the comments, I see the project requirements are evolving. The `0 = Off` command structure will severely limit what you can do, but it is a good starting point.

Regarding the first block of code starting with `while (mqttClient.available()) {`, then adding your one digit / char commands idea, I have this test sketch for you to try.

You don't need the `String` object to accomplish your goal. You may have to do something like this though  `input = (char)mqttClient.read()` where the test sketch uses this `input = Serial.read();`.

```lang-c++
char input;

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

void loop(){

  if(Serial.available() > 0){

    input = Serial.read();

    if(input == '0'){
      Serial.println("Turn Off");
    }

    else if(input == '1'){
      Serial.println("Turn On");
    }

    else if(input == '2'){
      Serial.println("Decrease Speed");
    }

    else if(input == '3'){
      Serial.println("Increase Speed");
    }
  }
}

```

To take it a step further, let's say you want to send commands that start with a single letter, then after the letter, the remaining digits, or chars have a purpose, if you want them to. For example, lets say you send the following command `d50`. The `d` could mean decrease speed, and the `50` could mean 50%, 50 steps, etc.

The following test sketch illustrates my point.

```lang-c++
char inputBuffer[64 + 1];

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

void loop(){

  while(Serial.available() > 0){

    Serial.readBytesUntil('\n', inputBuffer, sizeof(inputBuffer));

    if(inputBuffer[0] == 'f'){
      Serial.println("Letter 'f' entered");
    }

    // Letter "r". Everything after the "r" should be digits.
    else if(inputBuffer[0] == 'r'){
      Serial.print("Letter 'r' entered\t");
      // Change the letter "r" to the digit 0 to keep atol() happy.
      inputBuffer[0] = B110000;
      Serial.print("Number entered = ");
      Serial.println(atol(inputBuffer));

      // Your code here that uses the number parsed using atol().

    }

    // Letter "s". Everything after the "s" should have a max
    // length of up to 64 chars long for a 64 + 1 char buffer.
    else if(inputBuffer[0] == 's'){

      // MAX CHARS example with a 64 byte buffer:
      // s123456789a123456789b123456789c123456789d123456789e123456789f + CR + NL
      Serial.print("Letter 's' entered\tText entered = ");

      // Print out the chars in the buffer.
      for(int i = 1; i < strlen(inputBuffer); i++){
        Serial.print(inputBuffer[i]);
      }
      Serial.println();

      // Your code here that uses the char data after the letter "s" is entered.

    }
    memset(inputBuffer, 0, sizeof(inputBuffer));
  }
}

```


message:
How to switch 12V with esp32?

Hello i want to switch electric door lock (12V, 170mA) with esp32(3.3V). If is it possible I want use tranzistor. I tried to use IRF520, but it only worked with 5V. My sugestion is use 2 tranzistors one would switch 5V to IRF520 which would switch 12V. Can someone pro provide me some schematic, how to solve it? Thanks.

body:
[![enter image description here][1]][1]

BC549 provides strong pull-down for IRFR5305, which is provides up to +12V at 16A with less than 0.09 Ohm channel resistance.

This circuit works well with ESP8266, I use it in some of my devices.

Don't forget about placing the flyback diode ([EEV Blog][2], [Wiki][3]) in reverse polarity, parallel to the magnet. Place it as close as possible to the magnet!

  [1]: https://i.stack.imgur.com/nLIiv.png
  [2]: https://www.youtube.com/watch?v=hReCPMIcLHg
  [3]: https://en.wikipedia.org/wiki/Flyback_diode


body:
A single, reasonably tough general purpose BJT is all you need here if you really want a simple solution.  The 2N4401 supports up to 600mA of current and has a 40V Vce max.  As long as the solenoid on the door lock has a snubber it doesn't need to be any more complicated than this unless you need isolation or have other constraints.

Note that below I've drawn a relay because it was easy, but you can just as well put your door lock's solenoid coil where the relay is drawn below (they're effectively the same type of device).

[![enter image description here][1]][1]

I have exactly this setup on an ESP8266 controlling a 24V relay and it works great.  I'm using an old 2N2222, which are long since obsolete, but the 2N4401 would do just the same.

  [1]: https://i.stack.imgur.com/MDZZn.png


message:
Arduino UNO won't move servo

I have a simple MG996 servo motor and I am trying to make it move with my Arduino Uno. I tried different ways of wiring but nothing seems to work as fully expected.

For the wiring I followed this video: https://www.youtube.com/watch?v=b_xvu6wWafA and at 9:02 min the guy is showing how the wiring is done. As you can see in my photo, I have done the same thing (as you can see in the "my wiring" picture), with an external battery pack and everything but my code still does not work. No errors or anything, compiles and uploads perfectly. The code I was trying to execute is:

    #include <Servo.h>

    Servo myservo;

    void setup() {
      myservo.attach(8);
    }

    void loop() {
      myservo.write(0);
      delay(1000);
      myservo.write(90);
      delay(1000);
    }

This code is essentially trying to move the servo from 0 to 90 degrees back and forth. The pin is the correct one (#8). The arduino is receiving the right code (because I tried it with exemplary ones).

Important note: One thing I tried, however, was to not even have an external battery pack. Just connect the wires like so but instead of the 2 GNDs, only 1 GND and 1 +5V pin. That way I was able to move the servo only forward but never backwards! And every time I wanted to move it I had to write a higher degree value.

So the question is, is my wiring bad? I must be missing something.

Photos: [![My wiring][1]][1]

  [1]: https://i.stack.imgur.com/258V8.jpg

body:
You have not connected the supply pin properly.
here is the connection diagram for the standard basic Arduino example
I also verified this on the video you have linked. Connect the 5V and you should be good to go.

https://wokwi.com/arduino/projects/306894988845777472

[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/mLQQ5.png
  [2]: https://i.stack.imgur.com/TiTAA.gif


message:
ESP32 powered for atleast a year

How to power esp32 board [this one][1] with soil humidity sensor that sends data to server via wifi every 30 minutes for something around a year on battery? What battery type and capacity should I use for that? Or is there any better board you would recommend for this pourpouse? The setup will be indoors.

  [1]: https://www.laskarduino.cz/lolin-32-esp-32s-2-4ghz-dual-mode-wifi-bluetooth--cp2102--nabijeni-baterie/

body:
Okay, let's do some calculations.

Assume that device sends data for 5 seconds (turn on, connect to the Wi-Fi, and so on) and drains (according to the docs) about 0.2A.

So, it works for 5 (secs) * 48 (turn-on's) / 60 minutes per day for 365 days.

So, it works for 5 * 48 / 3600 hours per day for 365 days.

So, it works about 24 hours per year.

0.2A for 24 hours is 4.8A for 1 hour.

Assume that efficiency of the power regulator is 80%

4.8  - 80 %
X    - 100%

X = 6 A*h

So, take three (to compensate self discharge and have some headroom) standard Li-Ion cells, or mid-size (about 8000 mAh) power bank, and you well be fine.

But you shall add some external clock (powered by own CR2032 cell), that will be turn power regulator and esp-device ON every 30 minutes.


message:
Arduino Hanging Not sure if software or hardware issue

I am trying to run a very simple program to glow LEDs in a certain fashion, I connected 9 LEDs to the GPIOs or digital pins, 2 To 10, via 220 Ohm resistors; when I am running the program it is hanging the Arduino after some time interval and LEDs stops glowing, not sure if it is a hardware issue or some bug in the software/code.

Here is the code:

    int outGPIOsarr[9] = {2,3,4,5,6,7,8,9,10};

    void setup() {

      for(int i=0; i<10; i++)
    pinMode(outGPIOsarr[i], OUTPUT);
    }

    void loop() {

    for(int i=0; i<10; i++)
     {
    digitalWrite(outGPIOsarr[i],HIGH);
    delay(10);
     }

    for(int i=0; i<10; i++)
     {
    digitalWrite(outGPIOsarr[i],LOW);
    delay(10);
     }

    }

body:
This is the UB!

The indexes in array in `C++` counts from `0`;

So, the last index in your array of `9` elements is **`8`**.

All cycles must stop at **`8`**. Yours are stops at `9`.

Access beyond the existing element in the array is the Undefined Behavior - it hangs the MCU.


message:
İs that possible to a function return String OR Int depends on address

Well, I'm trying to use a HMI display and this HMI storing datas in separeta addreses. Such as integers addr. is between 0x80000 to 0x9ffff and also for string's addr is between 0 to 0x1ffff.

**At this point I want to make function which is return integer if addr is a integer addr OR it will return string if addr is String addr. is that possible to make two kind of return type for a method.**

I will detect integer or string from addr value like this:

    ????    HMT_SendCMD_ReadVPN16(INT32U Addr)

    if((Addr > 0x00080000) || (Addr < 0x0009FFFF))
        {
            return int (); // at here it call a fonction and it will return integer
        }

    else if(Addr < 0x0001FFFF)
        {
             return String (); // at here it call a fonction and it will return String
        }

body:
>  is that possible to make two kind of return type for a method

No. Functions are *declared* with a single return type. What is the point anyway of returning a blank string?

You need to redesign.


body:
If the task were to store something different at the given address,

or if you would want to return a String representation of the integer,

you might be able to do so, but Majenko's comment and Nick's response, suggesting a different approach, are better.


message:
Getting constant PWM value based on user input from serial monitor

I am trying to get a constant PWM value from the PWM pin based on the user input. For example: the user hits 1, the output PWM value is 100, if it is 2 the output would be 200. This will continue till the user enters a new number.
The issue I am having with my code is when I enter a number, the output of the PWM goes to that value for about a second and then goes back to 0. Can you please let me know what I am missing?

````
// Sketch: Blinking two LEDs by user
int test_pin=2; // declare pin10 as ledpin
int PWMvalue; // variable to store the number of blinks
void setup()
{
  Serial.begin(9600);
}
void loop()
{
  Serial.println("What is the new speed?"); //Prompt User for Input
 while (Serial.available() == 0) {
    // Wait for User to Input Data
  }
  PWMvalue = Serial.parseInt(); //Read the data the user has input

  if (PWMvalue==0)
  {
    analogWrite(test_pin,0);
    }
    else if (PWMvalue==1)
    {
      analogWrite(test_pin,100);
      }
      else if (PWMvalue==2)
    {
      analogWrite(test_pin,200);
      }
      else if (PWMvalue==3)
    {
      analogWrite(test_pin,300);
      }
      else if (PWMvalue==4)
    {
      analogWrite(test_pin,400);
      }
      else if (PWMvalue==5)
    {
      analogWrite(test_pin,500);
      }
      else if (PWMvalue==6)
    {
      analogWrite(test_pin,600);
      }
      else if (PWMvalue==7)
    {
      analogWrite(test_pin,700);
      }
      else if (PWMvalue==8)
    {
      analogWrite(test_pin,800);
      }
      else if (PWMvalue==9)
    {
      analogWrite(test_pin,900);
      }
      else
    {
      analogWrite(test_pin,1023);
      }

  Serial.print("The user has choosen the number:");
  Serial.println(PWMvalue);
  Serial.println(" ");
}
```

body:
You wait for user input with a `while (Serial.available() == 0)`, the you read the input with `Serial.parseInt()`. [parseInt][1] will wait a second for digits. It will end on a non digit character or timeout and return the number corresponding to received digits. If no digits were received a 0 is returned.

Serial Monitor has Line end setting. If there is some line ending selected, it will send line ending character(s).

Your waiting loop `while (Serial.available() == 0)` will end on line ending character which followed the number processed in previous loop. `parseInt` will not find a digit so it times out after a second and returns a 0, which causes setting the PWM to 0.

  [1]: https://www.arduino.cc/reference/en/language/functions/communication/serial/parseint/


message:
Swap Serial pins of ESP8266?

I have designed and manufactured a PCB which contains an ESP8266 (ESP-WROOM-02D) chip with the serial uart pins connected to a 30pin connector. I made a mistake on the layout (first time designing a PCB), and have the RX (Pin 3) and TX (pin 1) pins connected incorrectly (swapped).

Is there a way to switch these pins in software? There's no nice way to physically modify and I was hoping to not have to have the boards manufactured again if I can avoid it.

Thanks!

body:
You could potentially still fix this by using `SoftwareSerial`.
Instead of using the hard-wired serial, you can create one in software and use any pins you'd like... Have a look at [this github project](https://github.com/plerup/espsoftwareserial).
This work-around however requires you to have two unused pins to assign to SoftwareSerial.


message:
Parallel I/O - maybe use Machine code function call

I'm a newbie to arduino but been programming lots.
I have a project where I would like to output 4 bits to adjacent pins and read 4 bits from another (4) adjacent pins. (Imagine a matrix keyboard application).
To do it in C-C++ would take lots of instructions (and time) but machine code

OUTPUT:
OR (mask) -> output port      ; this clears bits target bits while leaving other bits as they were
AND (newdata) -> output port  ; this sets new data into target bits

INPUT:
port -> register
AND (register) (mask) -> register

Is there a way of implementing this as a call from IDE for instance.
I have come across many systems where multi language components can be compiled into one executable.

If it is not normally done, why not? Is it something that I should avoid for some reason?

Thanks
Dave

body:
You can manipulate the I/O ports directly from C++ without having to resort to assembly code.

The AVR micro in your Arduino (ATmega328P) has three ports (PORTB, PORTC and PORTD) with eight pins each (Px0, Px1, ... Px7). You control the ports using three 8-bit registers. Each bit in a register represents one physical pin (LSB is pin 0, MSB pin 7):

- DDRx: data direction register. A bit set to "1" corresponds to output mode, "0" to input.
- PORTx: data register. In output mode, "1" sets the port HIGH, "0" sets it LOW. In input mode, controls whether pull-ups are enabled ("1") or not ("0").
- PINx: input and toggle register. Read it to get the status of all eight pins of the port at once. Writing to it toggles (LOW -> HIGH or HIGH -> LOW) the selected pins (e.g. `PINC = 0b00100001;` toggles pins PC0 and PC5).

With an Arduino, you don't have access to all the pins of all the ports. To get the mapping between Arduino pin names and ports, look at any good Arduino pinout reference (e.g. on the [Arduino Uno page](https://store.arduino.cc/arduino-uno-rev3) in the "Documentation" tab). You can see for example that all pins of port D are available as Arduino digital pins D0 to D7 on an Uno for example. The analog pins are from PORTC.

[![Arduino Uno Rev 3 pinout][1]][1]

Macros are provided (by the AVR toolchain) for port and pin names to make things easier.
For example, `PORTB` is an alias for the PORTB register, you can assign to it as if it was a regular C++ variable. `PB5` is the index of pin 5 in port B. So setting port B pin 5 to output without affecting the others can be written as:

    DDRB |= (1 << PB5);

If you wanted to set the 4 lower pins of port D to output, and the 4 others to input, you could:

    DDRD = 0b00001111; // or 0x0f

Here's an example of a minimal blink sketch:

    void setup() {
      // Set PB5 (D13 - builtin led) LOW
      PORTB &= ~(1 << PB5);
      // Set PB5 mode to OUTPUT
      DDRB |= (1 << PB5);
    }

    void loop() {
      delay(1000);
      // toggle PB5
      PINB |= (1 << PB5);
    }

The assembly generated is optimal, single instructions to set or clear a bit in I/O memory:
(See https://arduino.stackexchange.com/questions/21401/see-compiled-assembly-output-visual-micro for how to get it)

    // setup
      PORTB &= ~(1 << PB5);
     1f4:   2d 98           cbi     0x05, 5 ; 5
      DDRB |= (1 << PB5);
     1f6:   25 9a           sbi     0x04, 5 ; 4

    // loop
      PINB |= (1 << PB5);
     246:   1d 9a           sbi     0x03, 5 ; 3

Another example, that blinks a led connected to A3 only when A2 is high:

    void setup() {
      // Set PC2 and PC3 LOW (A2 and A3)
      PORTC &= ~((1 << PC2) | (1 << PC3));
      // Set PC2 to input, PC3 mode to output
      DDRC = (DDRC & ~(1 << PC2)) | (1 << PC3);
    }

    void loop() {
      delay(1000);
      // toggle PC3 only if PC2 is high
      if (PINC & (1 << PC2)) {
        PINC = (1 << PC3);
      }
    }

Again, assembly generated is quite terse:

      if (PINC & (1 << PC2)) {
        PINC = (1 << PC3);
     202:   18 e0           ldi     r17, 0x08       ; 8
     252:   32 99           sbic    0x06, 2 ; 6
     254:   16 b9           out     0x06, r17       ; 6

(The SBIC instruction is fun: skip the next instruction if a bit in I/O memory is clear.)

You can even save the use of that register `r17` by using `PINC |= ...` in this case:

      // toggle PC3 only if PC2 is high
      if (PINC & (1 << PC2)) {
        PINC |= (1 << PC3);
     250:   32 99           sbic    0x06, 2 ; 6
     252:   33 9a           sbi     0x06, 3 ; 6

Of course you can also resort to inline assembly, but that is an art in and of itself, and the syntax a bit peculiar. But for simple things, it is straightforward:

    asm("sbi 0x03, 5;"); // toggle PB5

Some references:

- ATmega328P Datasheet linked from here: [Microchip ATMega328P page](https://www.microchip.com/en-us/product/ATmega328P#document-table). See section 14 "I/O ports", and 36 "Register summary" for the I/O port addresses.
- The [AVR Instruction Set Manual](https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-Instruction-Set-Manual-DS40002198A.pdf) (PDF) if you want to dive into that.
- The [AVR-GCC Inline Assembler Cookbook](https://www.nongnu.org/avr-libc/user-manual/inline_asm.html) for details on using GCC's flavor of inline assembly for AVR

  [1]: https://i.stack.imgur.com/y2jyd.png


message:
ESP32 OTA update over MQTT using "update.h"

I am trying to do OTA over MQTT using update.h library. I am publishing firmware file over MQTT in a specified chunk size. The file is receiving at ESP32 end. I am supplying the received data to ```update.write```. In start ~150 packet are written successfully. But after that update.write started to give error **Wrong Magic Byte**.

Here is the code snippet which I am using inside ESP32

    #include "mqtt_handler.h"
    StaticJsonDocument <256> root;
    uint8_t temp[100] = {0};
    size_t length ;
    void otaHandler(byte *msg, unsigned int len)
    {
    deserializeJson(root,msg);
    String command = root["command"];
    if (command.equals("ota.start"))
    {
        Serial.println("OTA.START via MQTT");
        if (!Update.begin(UPDATE_SIZE_UNKNOWN))
        {
            Update.printError(Serial);
        }
    }
    else if (command.equals("ota.write"))
    {
        Serial.println("OTA.WRITE via MQTT");
        memset(temp, 0, 100);
        length = root["length"];
        String data = root["data"];
        for (int i = 0; i < length; i++)
        {
            temp[i] = data[i];
        }

        Serial.println(data);
        if (Update.write(temp, length) != length)
        {
            Update.printError(Serial);
        }
    }
    else if (command.equals("ota.end"))
    {
        Serial.println("OTA.END via MQTT");
        if (Update.end(true))
        {
            Serial.printf("Update Success \nRebooting...\n");
        }
        else
        {
            Update.printError(Serial);
        }
    }
    else
    {
        Serial.println("Something went worng");
    }
    }
    void callback(char* topic, byte* message, unsigned int length) {
    otaHandler(message,length);
    }

In this code ```callback``` is the method which is called when an MQTT message arrived.This is the relevant code, if required I can share the complete code.

Message send by python application looks like as below:
```
{"command" : "ota.start"}
{"command": "ota.write", "length": length, "data": data})
{"command" : "ota.end"}
```
Below is the snapshot of ```data``` send by Python application in above ota.write message:

[![enter image description here][1]][1]

Below is the snapshot how my firmware file looks like:

[![enter image description here][2]][2]

I am sharing this snapshot to show the data format in which I am publishing firmware file.

Below is the snapshot of serial monitor:
[![enter image description here][3]][3]

Please suggest me if I am missing something on this.

Thanks

  [1]: https://i.stack.imgur.com/hNptB.png
  [2]: https://i.stack.imgur.com/73OBP.png
  [3]: https://i.stack.imgur.com/hrURd.png

body:
You are just throwing an unparseable stream of ASCII decimal representations of the binary data at your code, then writing that ASCII data verbatim to the flash. That can never work.

Instead you need to pick an ASCII representation of your data that is actually parseable (I would suggest sticking to HEX representation and always 2 digits, so represent 0x6 as "06"), then when you receive a packet you must convert the content back into binary before sending it to the Update library.

As it is you take a byte (for example 0xE9) and convert that to ASCII decimal, which is 223. Then you write the 2, 2 and 3 as individual bytes to the flash as ASCII, resulting in 0x32,0x32,0x33 - or printing as decimal in an unparseable stream, 505051.


message:
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?

body:
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.


body:
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](https://www.gammon.com.au/forum/?id=14175).


body:
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.

[![enter image description here][1]][1]

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][2]
_______________________

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.

[![enter image description here][3]][3]

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

  [1]: https://i.stack.imgur.com/sC97W.png
  [2]: https://wokwi.com/arduino/projects/294980637632233994
  [3]: https://i.stack.imgur.com/hMwoh.gif


body:
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.


body:
## 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...


message:
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][1] which uses a [ATSAMD21G18-QFN48][2] chip. Pin D1 on the Seeeduino is pin 9 on the chip; which is labeled as `PA4/EIC/REF/AIN4/SCOM0PAD0/TC0`.

[![screenshot with highlighted pin in question][4]][4]

What would the `REF` pin be used for; and how would the pin be addressed in the code?

Based on [this post][3] 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:
 [![Seeeduino XIAO pin layout][5]][5]

  [1]: https://files.seeedstudio.com/wiki/Seeeduino-XIAO/res/Seeeduino-XIAO-v1.0-SCH-191112.pdf
  [2]: http://ww1.microchip.com/downloads/en/devicedoc/40001884a.pdf
  [3]: https://arduino.stackexchange.com/a/24529/71398
  [4]: https://i.stack.imgur.com/iBtpy.gif
  [5]: https://i.stack.imgur.com/yeuXO.jpg

body:
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.
[![enter image description here][1]][1]
[![enter image description here][2]][2]
[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/RyOkB.png
  [2]: https://i.stack.imgur.com/wuIvg.png
  [3]: https://i.stack.imgur.com/BKDiO.png


message:
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.
1. 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.
2. 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.
3. Subtly solder 2 digital pins and set one to output and other to input. If not connected break loop.
4. 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.

body:
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][1]). 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).

  [1]: https://rweather.github.io/arduinolibs/crypto.html


message:
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?

body:
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.


body:
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
```


message:
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](https://github.com/arduino-libraries/ArduinoBLE/blob/94ffe050629a8af65b6dfcee5ee3679ad5f2fab9/src/utility/HCIUartTransport.cpp). It also messes with NINA_RESETN and SPIWIFI_SS a bit in [ BLELocalDevice.cpp](https://github.com/arduino-libraries/ArduinoBLE/blob/94ffe050629a8af65b6dfcee5ee3679ad5f2fab9/src/local/BLELocalDevice.cpp), but I'm not too worried about those.

The WiFiNINA library uses SerialNina to update the wifi firmware in [SerialNINAPassthrough.ino](https://github.com/arduino-libraries/WiFiNINA/blob/e8f0701d46c874530837bddf3b50ced7da674444/examples/Tools/SerialNINAPassthrough/SerialNINAPassthrough.ino) and [ESP32BootROM.cpp](https://github.com/arduino-libraries/WiFiNINA/blob/5d245e34269afe99216f1aec0f65501f35083dbf/examples/Tools/FirmwareUpdater/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?

body:
> 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][1]. (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.

  [1]: https://forum.arduino.cc/t/can-the-nano-iot-33-run-full-bluetooth-not-ble/626990/22


message:
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](https://arduino.stackexchange.com/questions/21137/arduino-how-to-get-the-board-type-in-code)

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.

body:
According to [documentation][1] 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`.

  [1]: https://arduino.github.io/arduino-cli/latest/platform-specification/#boardstxt


message:
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][1] 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][2].

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()
```

  [1]: https://www.sparkfun.com/products/449
  [2]: https://forum.arduino.cc/t/serial-input-basics-updated/382007

body:
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.


message:
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:

[![f_{scl}=\frac{f_{cpu}}{16+2\timesTWBR\timesPrescaler}][1]][1]

Then solving for `TWBR`:

[![TWBR=\frac{\frac{f_{cpu}}{f_{scl}}-16}{2\timesPrescaler}][2]][2]

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

[![f_{scl}=\frac{f_{cpu}}{2^{CLKPR}\times(16+2\timesTWBR\timesPrescaler)}][3]][3]

And solving for `TWBR`:

[![TWBR=\frac{\frac{f_{cpu}}{2^{CLKPR}\times f_{scl}}-16}{2\timesPrescaler}][4]][4]

Is the following code a correct implementation of the equations?

```cpp
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.

  [1]: https://i.stack.imgur.com/8cgX4.png
  [2]: https://i.stack.imgur.com/jFEId.png
  [3]: https://i.stack.imgur.com/gaX5K.png
  [4]: https://i.stack.imgur.com/9vrzJ.png

body:
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:

[![f_{scl}=\frac{f_{cpu}}{2^{CLKPR}\times(16+2\timesTWBR\timesPrescaler)}][3]][3]

And solving for `TWBR`:

[![TWBR=\frac{\frac{f_{cpu}}{2^{CLKPR}\times f_{scl}}-16}{2\timesPrescaler}][4]][4]

  [3]: https://i.stack.imgur.com/gaX5K.png
  [4]: https://i.stack.imgur.com/9vrzJ.png


message:
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();
    }

body:
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,


message:
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");
  }
}
```

body:
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.


message:
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](https://learn.adafruit.com/adafruit-arduino-lesson-6-digital-inputs/overview).

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:

[![enter image description here][1]][1]

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?

  [1]: https://i.stack.imgur.com/ZgEV2.jpg

body: 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.


body: 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)`.


body:
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][1]. Also the datasheet of the used microcontroller also contains all information about what SFRs exist and how they are used to perform specific actions.

  [1]: https://www.arduino.cc/en/Reference/PortManipulation


body:
I would like to add two more cents. It is a wonderful explanation already from @chrisl
Here is the simulation screenshot for your [example][1]:
[![enter image description here][2]][2]

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)
[![enter image description here][3]][3]

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

 1. The 1st person is looking at the switches. The 2nd person is
    controlling the LED
 2. 1st person is instructed to notify the second person about anybody pressing the switches
 3. whenever the ON switch is pressed, the 1st person will immediately tell the second person to turn on the LED
 4. 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][4]
[![enter image description here][5]][5]

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));
    }

  [1]: https://wokwi.com/arduino/projects/307720303778202178
  [2]: https://i.stack.imgur.com/QvZ36.gif
  [3]: https://i.stack.imgur.com/U9Zkw.png
  [4]: https://wokwi.com/arduino/projects/307720931096134209
  [5]: https://i.stack.imgur.com/HHXDT.gif


message:
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.

body:
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][1]?) 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.

  [1]: https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.h#L72


body:
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.


message:
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

body:
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).


body:
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.


message:
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?

body:
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`](https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFiClientSecure) library instead of `WiFiClient` library. Or even better, you could use an HTTP client that already implements the HTTP protocol, like [`HTTPClient`](https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPClient).


message:
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?

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/qhLvn.png

body:
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.


body:
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.


body: 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.


message:
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

body:
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"}


message:
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;
    }

body:
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:
1. start with an empty (zero) code
2. multiply the code by 10 (or left-shift once for binary)
3. read a switch, add 1 to the code if it is HIGH
4. 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.

<!-- language-all: lang-c++ -->

    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);
    }


body:
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;
    }