message:
Arduino Nano is performing really slowly, even though the calculations are simple and there are no delays

I'm working on a tiny ping-pong game based on Arduino Nano. Its modes are "person vs person" and "person vs computer" (the computer just tries to keep its racket at the same Y position as the ball). There are 2 "up" buttons, 2 "down" buttons, two 7-segment score indicators and 2 shift registers controlling them. The display is SSD1306 (128x32 pixels).

I'm posting here the entire code because I don't know where the issue lies.

```cpp
#include <Adafruit_SSD1306.h>

// Up/down buttons
#define UP1 2
#define DOWN1 3
#define UP2 4
#define DOWN2 5

// Shift registers that control score indicators
#define DATA1 6
#define CLOCK1 7
#define LATCH1 8
#define DATA2 9
#define CLOCK2 10
#define LATCH2 11

#define RANDOM_NUMBERS A0  // This port isn't connected to anything and is used to get random seed
#define WRAP 118  // Text on display wraps on this position

#define SSD1306_ADDRESS 0x3C  // I2C address of display

Adafruit_SSD1306 ssd1306;

const byte numbers[10] = {  // Arab numbers for score indicators
  0b1111110, 0b0011000, 0b1101101, 0b0111101, 0b0011011, 0b0110111, 0b1110111, 0b0011100, 0b1111111, 0b0111111
};

short currentDirection = -1;
short directionState = -1;  // The sequence number of next move in the period of ball trajectory
short nextMove = -1;
short ballX = 63;
short ballY = 15;
short racket1 = 12;
short racket2 = 12;

short score1 = 0;
short score2 = 0;
bool gameOver = false;

bool playingWithComputer = false;

void setup() {
  pinMode(UP1, INPUT_PULLUP);
  pinMode(DOWN1, INPUT_PULLUP);
  pinMode(UP2, INPUT_PULLUP);
  pinMode(DOWN2, INPUT_PULLUP);
  pinMode(DATA1, OUTPUT);
  pinMode(CLOCK1, OUTPUT);
  pinMode(LATCH1, OUTPUT);
  pinMode(DATA2, OUTPUT);
  pinMode(CLOCK2, OUTPUT);
  pinMode(LATCH2, OUTPUT);

  randomSeed(analogRead(RANDOM_NUMBERS));

  updateScores();

  ssd1306.begin(SSD1306_SWITCHCAPVCC, SSD1306_ADDRESS);
  ssd1306.display();
  delay(2000);  // A delay to show the Adafruit logo
  ssd1306.clearDisplay();

  ssd1306.setTextSize(1);
  ssd1306.setTextColor(WHITE);
  ssd1306.setCursor(0, 0);  // Cursor should be at this position to draw objects correctly

  printLongText(5, 0, "Press \"up\" to play with computer, otherwise press \"down\"");

  while (true) {
    if (!digitalRead(UP1) || !digitalRead(UP2)) {  // Both "up" buttons (as well as both "down" ones) are treated the same unless there's a game "person vs person"
      playingWithComputer = true;
      break;
    }
    if (!digitalRead(DOWN1) || !digitalRead(DOWN2)) break;

    delay(5);  // This delay is here to avoid overloading the processor
  }

  ssd1306.clearDisplay();
  ssd1306.display();

  delay(100);  // This delay is intended to show user that they don't need to hold button any more
}

void loop() {
  if (gameOver) {
    delay(1000);
    return;
  }

  if (nextMove < 0) {
    pickDirection();
    return;
  }

  short oldDirection = currentDirection;
  switch (getBounceType()) {
    case 0:
      verticalFlipDirection();
      ballY++;
      break;
    case 1:
      verticalFlipDirection();
      ballY--;
      break;
    case 2:
      if (ballY < (racket1 - 1) || ballY > (racket1 + 8)) {  // This determines if the ball ran shorto the racket or not (true if it did not)
        score2++;

        // Ball goes to the center of the screen after goal
        ballX = 63;
        ballY = 15;
        pickDirection();

        updateScores();
      }
      else {
        horizontalFlipDirection();
        ballX++;
      }

      break;
    case 3:
      if (ballY < (racket2 - 1) || ballY > (racket2 + 8)) {
        score1++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        horizontalFlipDirection();
        ballX--;
      }

      break;
    case 4:
      if (racket1 > 1) {
        score2++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        reverseDirection();  // This occurs when the ball rans exactly shorto the corner of its zone
        ballX++;
        ballY++;
      }

      break;
    case 5:
      if (racket2 > 1) {
        score1++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        ballX--;
        ballY++;
        reverseDirection();
      }

      break;
    case 6:
      if (racket1 > 1) {
        score2++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        reverseDirection();
        ballX++;
        ballY--;
      }

      break;
    case 7:
      if (racket2 > 1) {
        score1++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        ballX--;
        ballY--;
        reverseDirection();
      }

      break;
  }
  if (oldDirection != currentDirection) directionState = 0;  // Resetting direction state if the ball bounced
  pickMove();  // Next move may have changed if the ball bounced

  switch (nextMove) {
    case 0:
      ballY--;
      break;
    case 1:
      ballX++;
      break;
    case 2:
      ballY++;
      break;
    case 3:
      ballX--;
      break;
  }
  directionState++;
  pickMove();

  ssd1306.clearDisplay();
  ssd1306.drawRect(ballX, ballY, 2, 2, WHITE);

  if (playingWithComputer) {
    if (!digitalRead(UP1) || !digitalRead(UP2)) {
      if (racket1 > 0) racket1--;
    }
    if (!digitalRead(DOWN1) || !digitalRead(DOWN2)) {
      if (racket1 < 24) racket1++;
    }

    // This is the algorithm used by computer — it just tries to keep the computer-controlled racket at the same Y position as the ball
    if ((racket2 + 3) > ballY) {
      if (racket2 > 0) racket2--;
    }
    if ((racket2 + 3) < ballY) {
      if (racket2 < 24) racket2++;
    }
  } else {
    if (!digitalRead(UP1)) {
      if (racket1 > 0) racket1--;
    }
    if (!digitalRead(DOWN1)) {
      if (racket1 < 24) racket1++;
    }
    if (!digitalRead(UP2)) {
      if (racket2 > 0) racket2--;
    }
    if (!digitalRead(DOWN2)) {
      if (racket2 < 24) racket2++;
    }
  }

  ssd1306.drawRect(0, racket1, 2, 8, WHITE);
  ssd1306.drawRect(126, racket2, 2, 8, WHITE);

  ssd1306.display();
}

// This function picks a random direction for the ball
void pickDirection() {
  currentDirection = random(0, 20);
  directionState = 0;
  pickMove();
}

// This function determines the next move of the ball (up/right/down/left) based on its current direction and direction state
void pickMove() {
  short sector = getSector();  // Directions that go to up-right are in sector 0, those going to down-right are in sector 1, etc

  switch (currentDirection) {
    case 0:
    case 5:
    case 10:
    case 15:
      directionState = directionState % 5;  // Resetting direction state when the ball reaches next period of its trajectory

      // At certain direction states the ball goes to its primary direction (e.g. in an almost vertical trajectory the primary direction would be up)
      // At other states it goes to the secondary direction, which when added to the primary one forms the actual trajectory of the ball
      // Sectors divide into 2 parts. The first part includes 3 trajectories which have their primary direction number (up - 0, right - 1, down - 2, left - 3) same as sector number
      // Secondary directions in first part are sector number plus 1
      // In the second part the primary direction is (sector_number + 1) % 4 and the secondary one is the sector number
      // There are 20 supported trajectories (5 in each of 4 sectors). They are presented in Ping-Pong.png
      // First trajectories in each sector (as well as second ones etc) have the same structure, so there's only one code block
      // for handling first trajectories of all sectors. However, their primary and secondary directions differ in each sector
      // The following line determines if the ball should now go to the primary or secondary direction and based on that sets nextMove
      nextMove = (directionState == 0 || directionState == 1 || directionState == 3) ? sector : (sector + 1) % 4;
      return;
    case 1:
    case 6:
    case 11:
    case 16:
      directionState = directionState % 4;
      nextMove = (directionState < 2) ? sector : (sector + 1) % 4;
      return;
    case 2:
    case 7:
    case 12:
    case 17:
      directionState = directionState % 4;
      nextMove = (directionState == 0 || directionState == 2) ? sector : (sector + 1) % 4;
      return;
    case 3:
    case 8:
    case 13:
    case 18:
      directionState = directionState % 4;
      nextMove = (directionState < 2) ? getSecondPartMove(sector) : sector;
      return;
    case 4:
    case 9:
    case 14:
    case 19:
      directionState = directionState % 5;
      nextMove = (directionState == 0 || directionState == 1 || directionState == 3) ? getSecondPartMove(sector) : sector;
      return;
  }
}

// Just a helper for pickMove (determines primary direction of second-part trajectories in a certain sector)
short getSecondPartMove(short sector) {
  return (sector + 1) % 4;
}

// This function determines the current bounce type (-1 - currently no bounce, 0 - bounce from upper wall,
// 1 - bounce from lower wall, 2 - facing the first player's wall, 3 - facing the second player's wall,
// 4 - facing upper-left corner, 5 - upper-right corner, 6 - bottom-left, 7 - bottom right
// On 4-7 the ball reverses its trajectory
short getBounceType() {
  if (ballX <= 2 && ballY <= 0) return 4;  // Made ballX indents so that the ball bounces from rackets and not bounds of screen
  if (ballX >= 124 && ballY <= 0) return 5;
  if (ballX <= 2 && ballY >= 30) return 6;
  if (ballX >= 124 && ballY >= 30) return 7;

  if (ballX <= 2) return 2;
  if (ballX >= 124) return 3;

  if (ballY <= 0) return 0;
  if (ballY >= 30) return 1;

  return -1;
}

// This function flips the current trajectory of the ball vertically to bounce from the upper/lower wall
// (source and flipped trajectories have a relationship that differs in different sectors of the source trajectory, see this function)
void verticalFlipDirection() {
  short sector = getSector();

  switch (sector) {
    case 0:
    case 1:
      currentDirection = 9 - currentDirection;
      return;
    case 2:
    case 3:
      currentDirection = 10 + (9 - (currentDirection - 10));
      return;
  }

  directionState = 0;
}

// Same as previous function but the translation is horizontal here
// (the relationship between source and flipped trajectories is different)
void horizontalFlipDirection() {
  short sector = getSector();

  switch (sector) {
    case 0:
    case 3:
      currentDirection = 19 - currentDirection;
      return;
    case 1:
    case 2:
      currentDirection = 5 + (9 - (currentDirection - 5));
      return;
  }

  directionState = 0;
}

// This function reverses the trajectory of the ball
void reverseDirection() {
  currentDirection = (currentDirection + 10) % 20;
  directionState = 0;
}

// This function determines the sector of the current trajectory
short getSector() {
  if (currentDirection < 5) return 0;
  else if (currentDirection < 10) return 1;
  else if (currentDirection < 15) return 2;
  else return 3;
}

// This function prints text on the display, wrapping it at a certain X position
void printLongText(short cursorX, short cursorY, String text) {
  ssd1306.setCursor(cursorX, cursorY);

  int16_t x, y;
  uint16_t w, h;

  short lastSpace = -1;
  short i;

  // Adding character by character to current line until the wrapping position is reacher
  // In parallel finding the last space before wrap (it will be where the line breaks)
  for (i = 0; i < text.length(); i++) {
    if (text.charAt(i) == ' ') lastSpace = i;

    ssd1306.getTextBounds(text.substring(0, i + 1), 0, 0, &x, &y, &w, &h);

    if (x + w > WRAP && lastSpace >= 0) {
      ssd1306.println(text.substring(0, lastSpace + 1));  // Wrapping position reached; breaking the current line at the index of last space in it and printing it
      text = text.substring(lastSpace + 1);

      i = -1;  // Now the same with next line
      lastSpace = -1;
      ssd1306.setCursor(cursorX, ssd1306.getCursorY());
    }
  }
  ssd1306.println(text);  // printing the rest of text

  ssd1306.display();

  ssd1306.setCursor(0, 0);  // Cursor should be at this position to draw objects correctly
}

// This function displays the scores on corresponding indicators and checks if the game if over
// (i.e. one of the players has a score of 7)
void updateScores() {
  digitalWrite(LATCH1, false);
  shiftOut(DATA1, CLOCK1, MSBFIRST, numbers[score1]);  // Sending the necessary mask to the shift registers
  digitalWrite(LATCH1, true);

  digitalWrite(LATCH2, false);
  shiftOut(DATA2, CLOCK2, MSBFIRST, numbers[score2]);
  digitalWrite(LATCH2, true);

  if (score1 >= 7) {
    ssd1306.clearDisplay();
    printLongText(10, 12, "Player 1 wins!");
    ssd1306.display();

    gameOver = true;
  }
  if (score2 >= 7) {
    ssd1306.clearDisplay();
    printLongText(10, 12, "Player 2 wins!");
    ssd1306.display();

    gameOver = true;
  }
}
```

**[Look](https://imgur.com/a/4h438v0) how slowly does the ball move, even though a `loop` iteration doesn't include any `delay`s at all, and there are no complex calculations.** Conversion to GIF didn't change the speed.

My circuit looks like this (it's just a test, so no buttons, just pull-ups, and no score indicators).

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](http://i.stack.imgur.com/w2aek.png)

<!-- End schematic -->

Answers [here](https://arduino.stackexchange.com/questions/16103/arduino-code-on-board-runs-really-slow) didn't help. Changing the I2C clock speed to 400 KHz didn't help either.

So — is such slowness caused by the (not very high) complexity of my code? Or is it some kind of glitch? **Please don't suggest using libraries instead of my own moving and bouncing logic.**

body:
I put in some timing into your code. As a tip for you and others who may want to time code, here is a simple way of doing that ...

## Timer class

Define a timer class as follows:

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

    class timer
      {
      unsigned long start;
      const char sReason [50];

      public:

        // constructor remembers time it was constructed
        timer (const char * s)
          {
          strncpy (sReason, s, sizeof (sReason) - 1);
          start = micros ();
          Serial.print (F("Start:  "));
          Serial.println (sReason);
          };

        // destructor gets current time, displays difference
        ~timer ()
          {
          unsigned long t = micros ();
          Serial.print (F("Finish: "));
          Serial.print (sReason);
          Serial.print (F(" = "));
          Serial.print (t - start);
          Serial.println (F(" µs"));
          }
      };    // end of class timer

## How to use the timer class

If you want to time "loop" then just put this at the start of it:

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

    void loop() {
      timer t ("Loop");
      ... other code ...
    }  // end of loop

The constructor starts timing, and the destructor (when `loop` is exited) works out the difference and displays it.

To time some specific code, make a "block" like this:

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

      {    // start of block
      timer t ("Draw ball");
      ssd1306.clearDisplay();
      ssd1306.drawRect(ballX, ballY, 2, 2, WHITE);
      }    // end of block

Inside the block the timer instance is created, it times what is inside the block, and displays the result after the `}` is passed.

Naturally, for all this to work you need to do a `Serial.begin (115200);` in `setup`.

---

## Results of timing

I added the above two timing calls, plus for drawing the rackets and updating the display:

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

      {
      timer t ("Draw rackets");
      ssd1306.drawRect(0, racket1, 2, 8, WHITE);
      ssd1306.drawRect(126, racket2, 2, 8, WHITE);
      }

      {
      timer t ("ssd1306.display");
      ssd1306.display();
      }

The results I got were:

    Start:  Loop
    Start:  Draw ball
    Finish: Draw ball = 1812 µs
    Start:  Draw rackets
    Finish: Draw rackets = 1956 µs
    Start:  ssd1306.display
    Finish: ssd1306.display = 168944 µs
    Finish: Loop = 178516 µs

Clearly, updating the display is taking almost all the time (169 ms each time, which means you will be doing around 5 loops per second).

Following on from a suggestion in [the Adafruit forum](https://forums.adafruit.com/viewtopic.php?t=148978) I changed your constructor for ssd1306 to be:

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

    #define SCREEN_WIDTH 128
    #define SCREEN_HEIGHT 32
    #define OLED_RESET -1
    Adafruit_SSD1306 ssd1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Now the timing is:

    Start:  Loop
    Start:  Draw ball
    Finish: Draw ball = 1780 µs
    Start:  Draw rackets
    Finish: Draw rackets = 1956 µs
    Start:  ssd1306.display
    Finish: ssd1306.display = 21192 µs
    Finish: Loop = 30648 µs

So that is around 33 FPS rather than 5 FPS. A big improvement!

---

## Further speed improvements

Following on from your edit about changing from I2C to SPI "not making much difference", the speed difference would indeed be significant. According to [my page about protocols](http://www.gammon.com.au/forum/?id=10918) SPI can be 30 times as fast as I2C (depending on the I2C clock speed) so I suggest that getting the SPI version of that board would indeed give you a significantly faster refresh rate — at least 10 times as fast.

You may then need to rework how you show scores but [bit banged SPI](http://www.gammon.com.au/forum/?id=10892&reply=6#reply6) could be an option for the them. The scores hardly need to update all that quickly, and in any case there would be a lot less data. (The screen has 4096 pixels, and the scores would only be a handful of digits).

---

From a comment by SNBS:

>  But I noted in my question that changing the I2C clock speed to 400 KHz (which is 4 times as fast as its regular speed) didn't affect the situation at all.

Yes, well the default behaviour for the constructor is to use a 400 kHz clock, see the constructor declaration:

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

    Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi = &Wire,
                       int8_t rst_pin = -1, uint32_t clkDuring = 400000UL,
                       uint32_t clkAfter = 100000UL);

The constructor definition saves `clkDuring` into `wireClk`.

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

    Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi,
                                       int8_t rst_pin, uint32_t clkDuring,
                                       uint32_t clkAfter)
        : Adafruit_GFX(w, h), spi(NULL), wire(twi ? twi : &Wire), buffer(NULL),
          mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1), rstPin(rst_pin)
    #if ARDUINO >= 157
          ,
          wireClk(clkDuring), restoreClk(clkAfter)
    #endif

At the start of the `display` function it calls TRANSACTION_START

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

    void Adafruit_SSD1306::display(void) {
      TRANSACTION_START

This is a define:

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

    #define TRANSACTION_START                                                      \
      if (wire) {                                                                  \
        SETWIRECLOCK;                                                              \
      } else {                                                                     \
        if (spi) {                                                                 \
          SPI_TRANSACTION_START;                                                   \
        }                                                                          \
        SSD1306_SELECT;                                                            \
      } ///< Wire, SPI or bitbang transfer setup

And `SETWIRECLOCK` sets the I2C clock speed for you:

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

    #define SETWIRECLOCK wire->setClock(wireClk)    ///< Set before I2C transfer


sender: user

message:
Micropython installation on Arduino nano

I am currently trying to use micropython on an arduino Nano 33 BLE using MacOS. Following the instructions from arduino website I was able to complete steps 1-3. At step 4, I can find the bossac file but when I try to run the provided command:

`bossac -e -w —offset=0x16000 —port=usbmodem14201 -i -d -U -R file.bin`

the terminal says no device `found on usbmodem14201` which is a port appearing under the nano board in the IDE.

As a sanity check I ran serialportlist in matlab and the same port was returned when the Nano is plugged in.

I even ran ioreg -p IOUSB in terminal and found the nano:
‘’’ Arduino Nano 33 BLE@14200000 <class AppleUSBDevice, id 0x100008674, re$ ‘’’

That 142… number didn’t work either.

What am I doing wrong?

sender: assistant

body:
Welcome to Arduino StackExchange:

1. Firstly your computer translates double dashes into single long dashes. the dashes should be double dashes (`--`) for options such as `--offset`, `--port`, etc. The command should be:
    ```
    bossac -e -w --offset=0x16000 --port=usbmodem14201 -i -d -U -R file.bin
    ```

but I can see that your computer translated these `--` to those `—` ?

2. Before you try to upload code confirm that the board is recognized by the system using the `ls` command:
    ```
    ls /dev/cu.*
    ```
    This should list all serial devices and you should see something like `/dev/cu.usbmodem14201` in the list if your board is connected.

3. Ensure that you have the necessary permissions to access the serial port. You can try running the `bossac` command with `sudo` to run it as the superuser:
    ```
    sudo bossac -e -w --offset=0x16000 --port=usbmodem14201 -i -d -U -R file.bin
    ```

4. Instead of just the port name `usbmodem14201`, you might need to use the full path like `/dev/cu.usbmodem14201`:
    ```
    bossac -e -w --offset=0x16000 --port=/dev/cu.usbmodem14201 -i -d -U -R file.bin
    ```

5. Check that the Arduino Nano 33 BLE is in the bootloader mode. Typically, this can be achieved by double pressing the reset button. When it's in bootloader mode, the board might appear on a different port. Check the ports again with `ls /dev/cu.*` after you double press the reset button.

If you try all those and still it doesn't work maybe you should try installing latest drivers or check compatibility. Anyways, good luck.


message:
Reading a string from the serial port and comparing to another string

I'm using an Arduino Mega 2560 and writing a really simple piece of code that doesn't work.

```c++
String a, letra;
#define led 13

void setup() {
  Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
  pinMode(led, OUTPUT);
}

void loop() {
  while(Serial.available()) {
    letra= Serial.readStringUntil('\n');
    letra.trim();
    Serial.println(letra);

    if(letra.equals("aa\r\n")){
      Serial.println("ABRE 1");
    }
    if(letra == "aa\r\n"){
      Serial.println("ABRE 2");
    }
    if(letra.compareTo("aa\r\n") == 0){
      Serial.println("ABRE 3");
    }
  }
}
```

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

It's returning what I typed, but it's not entering any of the if conditions...
Can someone help me with that ?

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

body:
[Trim](https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/trim/) removes whitespace, and you are comparing for `\r` and `\n` to be there. Since they are whitespace naturally the compare fails.

See [here](https://cplusplus.com/reference/cctype/isspace/) for one definition of whitespace for C.


message:
how to make this code work with spiffs?

So, I have a page to select a txt file from the user's device and save it to SD card:
```html
<!DOCTYPE html>
<html>
<head>
  <title>File Upload </title>
</head>
<body>
  <h1>File Upload </h1>
<form method='POST' action='/upload' enctype='multipart/form-data'>
<input type='file' name='upload'>
<input type='submit' value='Upload'>
</form>
</body>
</html>
```
and here is my esp8266 code for handling the form :
```c++

  controlserver.on("/UPL", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", upl);
  });
 controlserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request) {
        request->send(200); }, handleUpload);

void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
  String logmessage = "Client:" + request->client()->remoteIP().toString() + " " + request->url();

  if (!index) {
    logmessage = "Upload Start: " + String(filename);
    request->_tempFile = SD.open("/" + filename, "w");
  }

  if (len) {
    request->_tempFile.write(data, len);
    logmessage = "Writing file: " + String(filename) + " index=" + String(index) + " len=" + String(len);
  }

  if (final) {
    logmessage = "Upload Complete: " + String(filename) + ",size: " + String(index + len);
    request->_tempFile.close();
    request->redirect("/");
  }
}
```
My project is not big and it doesn't require SD card, and esp8266 has 4mb memory, I have tried to replace SD with spiffs, but I wasn't successful. I don't know that if it's possible to directly write the txt file to spiffs, but it will be ok if I could save it to a string the write it to a file in spiffs.

body:
Thanks to [this][1] post, I did solve the problem.

Here is the full code,
My html code for the upload page, the form is in the <iframe> tag:
```html

<!DOCTYPE html>
<html>
<head>
  <title>File Upload Example</title>
</head>
<body>
  <h1>File Upload Example</h1>
<form method="POST" action="/upload" enctype="multipart/form-data" target="iframe"><input type="file" name="upload"><input type="submit" value="Upload">
</form>
<iframe style="visibility: hidden;" src="http://" )+local_IPstr+"/Usm" name="iframe"></iframe>
</body>
</html>
```
code for ESP:
```c++

void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if (!index) {
    request->_tempFile = SPIFFS.open("/" + filename, "w");
    Serial.println("1");
}
if (len) {
    request->_tempFile.write(data, len);
     Serial.println("2");
}
if (final) {
   Serial.println("3");
    request->_tempFile.close();
    request->redirect("/");
}
}

 controlserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request) {
        request->send(200); }, handleUpload);

  controlserver.on("/UPL", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", upl);
  });

  readFile(SPIFFS, "/11.txt"); // show the content of the uploaded file, obviously you should know the name of the uploaded file!
```

you can write a function like this to make sure the file was delivered:
```c++
  readFile(fs::FS &fs, const char * path){
  Serial.printf("Reading file: %s\r\n", path);
  File file = fs.open(path, "r");
  if(!file || file.isDirectory()){
    Serial.println("- empty file or failed to open file");
    return String();
  }
  Serial.println("- read from file:");
  String fileContent;
  while(file.available()){
    fileContent+=String((char)file.read());
  }
  file.close();
  Serial.println(fileContent);

}
```

  [1]: https://arduino.stackexchange.com/questions/81482/esp-32-upload-files-to-spiffs-via-browser


message:
reading device or board specific properties from the Arduino MKR WiFi 1010 device

How to read programmatically the device specific properties from the Arduino MKR WiFi 1010 chip or board?

For example, following properties of the device:

 - any identification number, that can uniquely identify the physical device, integer or GUID or string or any other, how to read that from the code?
 - SerialNumber of the MRK WiFi 1010 device
 - ModelNumber of the MRK WiFi 1010 device

I have tried to check the documentation and examples, however I couldn't find anything at all.

body:
[MAC address][1] could be of use to you, but remember that it can be [spoofed][2]. Aside from that Serial and Model numbers **are not** accessible from software layer.

Here is a simple implementation for fetching the MAC address

```python
    #include <WiFiNINA.h>

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

      if (WiFi.status() == WL_NO_MODULE) {
        Serial.println("Communication with WiFi module failed!");
        while (true);
      }

      byte mac[6];
      WiFi.macAddress(mac);
      Serial.print("MAC: ");
      for (int i = 5; i >= 0; i--) {
        if (mac[i] < 16) {
          Serial.print("0");
        }
        Serial.print(mac[i], HEX);
        if (i > 0) {
          Serial.print(":");
        }
      }
      Serial.println();
    }

    void loop() {}
```

Another solution that I can think of is writing your own unique identifier such as UUID to EEPROM memory for each board.

If you're generating a UUID in the context of a server or a device with more resources, there are libraries and tools that can create these for you based on various factors to ensure uniqueness (like timestamp, MAC address, etc.). However, with a microcontroller like the one on the Arduino MKR WiFi 1010, you have a more constrained environment, and the process can be more manual.

You can use an [online UUID generator][3] or can generate it using Python:
```python
    import uuid
    print(uuid.uuid4())
```
After generating your UUID's, you can write them on EEPROM but make sure to not over-write EEPROM since it has very limited call boundaries.

## Writing to EEPROM

``` python
#include <EEPROM.h>

const char* MY_UUID = "550e8400-e29b-41d4-a716-446655440000";
const int EEPROM_UUID_ADDRESS = 0;  // starting address in EEPROM

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

  // Write UUID to EEPROM
  for (int i = 0; i < strlen(MY_UUID); i++) {
    EEPROM.write(EEPROM_UUID_ADDRESS + i, MY_UUID[i]);
  }
  Serial.println("UUID written to EEPROM");
}

void loop() {}
```

"starting address in EEPROM" is the address of the first box (or byte) where the program begins storing our UUID. By specifying `const int EEPROM_UUID_ADDRESS = 0;`, we are saying we'll start storing the UUID from the very first byte (box) of the EEPROM. **If you were storing other data in EEPROM, you would need to ensure that the addresses don't overlap**. For example, if you had other data stored in the first 10 bytes, you might set `EEPROM_UUID_ADDRESS` to 10 to start storing the UUID from the 11th byte.

## Reading from the EEPROM:

``` python
#include <EEPROM.h>

const int UUID_LENGTH = 36;  // Length of the UUID string
char readUUID[UUID_LENGTH + 1];  // +1 for the null terminator
const int EEPROM_UUID_ADDRESS = 0;  // starting address in EEPROM

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

  // Read UUID from EEPROM
  for (int i = 0; i < UUID_LENGTH; i++) {
    readUUID[i] = EEPROM.read(EEPROM_UUID_ADDRESS + i);
  }
  readUUID[UUID_LENGTH] = '\0';  // Null terminate the string

  Serial.print("UUID read from EEPROM: ");
  Serial.println(readUUID);
}

void loop() {}
```
**+1 for the null terminator**:

   In the C and C++ programming languages, strings are represented as an array of characters. The end of the string is marked by a special character known as the "null terminator" or "null character", which is represented by the value `'\0'` (a byte with all bits set to 0).

   When we read or write strings to/from memory (like EEPROM), we often need to account for this null terminator to ensure the string is properly terminated and can be safely used with string functions.

   In the code, the UUID is 36 characters long. When we declare an array to hold this UUID with the line:
   ```cpp
   char readUUID[UUID_LENGTH + 1];
   ```
   We're allocating space for the 36 characters of the UUID plus an additional character for the null terminator, hence `UUID_LENGTH + 1`.

   Later, after reading the UUID from EEPROM, we ensure this array is a properly terminated string by adding the null terminator:
   ```cpp
   readUUID[UUID_LENGTH] = '\0';
   ```

   This ensures that when we use `readUUID` in functions that expect a string, they'll recognize where the string ends. Without the null terminator, these functions wouldn't know where the string finishes, leading to unpredictable behavior or errors.

I hope that this is helpful.

  [1]: https://en.wikipedia.org/wiki/MAC_address
  [2]: https://en.wikipedia.org/wiki/MAC_spoofing
  [3]: https://www.uuidgenerator.net/


body:
The IDE shows the serial number so I looked into the SAMD core and found the function which reads the serial number from registers. It is in the CDC.cpp file

```cpp
uint8_t Serial_::getShortName(char* name) {
 // from section 9.3.3 of the datasheet
 #define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C)
 #define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040)
 #define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044)
 #define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048)

 utox8(SERIAL_NUMBER_WORD_0, &name[0]);
 utox8(SERIAL_NUMBER_WORD_1, &name[8]);
 utox8(SERIAL_NUMBER_WORD_2, &name[16]);
 utox8(SERIAL_NUMBER_WORD_3, &name[24]);
 return 32;
}
```

from [the datasheet of SAMD21][1]:
> Each device has a unique 128-bit serial number which is a concatenation of four 32-bit words contained at the
following addresses:

>The uniqueness of the serial number is guaranteed only when using all 128 bits

  [1]: https://ww1.microchip.com/downloads/en/DeviceDoc/SAM_D21_DA1_Family_DataSheet_DS40001882F.pdf


message:
How to control camera lens by Arduino's PWM? What FOCUS A+, FOCUS A- wires means?

I have a camera lens which I want to control by arduino (like this https://vi.aliexpress.com/item/1005004141070063.html)

I have an info about wires description but I can't understand what focus A+, A-, B+, B- means? I guess I need to send PWM pulses to A and B wires to move focus in straigt and opposite direction but I can't understand what + and - means. Is it just signal and ground?

[![Manual][1]][1]

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

body:
It looks like you will be dealing with bipolar stepper motors. Most
likely, A+ and A− are connected to one coil, whereas B+ and B− are
connected to the other coil.

See the Arduino documentation: [Arduino and Stepper Motor
Configurations][docs] for instructions on driving this kind of motor.

[docs]: https://docs.arduino.cc/learn/electronics/stepper-motors


message:
Is it possible to use UART0 freely when connecting ESP32 s3 via USB (D+, D-)?

I've designed a test PCB that utilizes an ESP32 S3 and testing pins. During program uploads, I use the USB interface over GPIO20 and GPIO19 as D+ and D-. Everything works fine in this configuration. However, I've encountered an issue where UART0 becomes inactive after using the USB interface. Now, I want to connect the TX pin of a GPS module (NEO 6m) to UART0's RX pin, but I'm unable to do so. It's impractical to run the code as is because when data is received on RX0, it floods the continuous serial screen. I'm looking for a solution to completely disconnect UART0 from the USB interface so that I can use it independently.

**In Short How I can receive date from UART0 and than Serial.print to Serial monitor over the USB interface?**

    #define RXD2 6
    #define TXD2 7

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      while (!Serial)
        delay(200);
      Serial.println("start GPS...");

      Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
    }

    void loop() {
      while (Serial.available()) {
        Serial.print(char(Serial.read()));
      }
    }

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

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

body:
`Serial` is 'com' port over USB on esp32 with native USB (and "USB CDC On Boot" option selected in Tools menu). **For UART0 the core then creates `Serial0`.**

From [documentation][1]:
> To use the UART as serial output, you can use Serial0.print("Hello World!"); instead of Serial.print("Hello World!"); which will be printed using USB CDC.

  [1]: https://docs.espressif.com/projects/arduino-esp32/en/latest/guides/tools_menu.html?highlight=Serial0#usb-cdc-on-boot


message:
How can I compensate for a joysticks offset value in neutral position?

I have a joystick that outputs the values 0 - 4095. I want to map these values in this fashion (Yes, the reversed mapping is intended):

    outputValue = map(inputValue, 4095, 0, -2048, 2047);

However, the neutral central position of the joystick is offset, outputting 145 instead of 0.

Is there a way to map these values - taking the offset value in account - and still have the output values ranging from -2048 to 2047? I fail to do this with the map() function alone, and could need some help with the specific math involved.

body:
You can only approximate it, you have to sacrifice something.

The basic problem is that your input range is asymmetric in respect to the mid point. Let's visualize it this way (with a bit of visual exaggeration):

```
min                     mid      max
0----------------------2193-----4095
```

Another problem is that the whole range 0..4095 may not be physically reachable by the joystick, so your usable range may actually look like this:

```
min                mid        max
433---------------2193-------3722
```

So, to calibrate your joystick, you need to measure the min, mid and max points that you can physically reach with exactly that joystick on the input scale (joysticks are analog devices, so their actual ranges can differ from joystick to joystick and even from axis to axis in the same physical joystick).

Now, if you have these numbers (I call those calibration values `joy_min`, `joy_mid` and `joy_max`), you need to `map` both parts of your range separately:

```
if( joy_input < joy_mid ) {
  output = map(joy_input, joy_min, joy_mid, -2048, 0);
} else {
  output = map(joy_input, joy_mid, joy_max, 0, 2047);
}
```

The downside is that any step in the output may represent a slightly different distance in the movement, depending on whether you are currently lower or higher than the measured midpoint. But I expect that to be negligible.

Also, keep in mind that this is only for one axis of the joystick. You may need completely different calibration values for the other axis. In addition, you may want to implement a "dead zone" around the midpoint, i.e. always returning `output = 0` for `joy_mid-10 < joy_input < joy_mid+10` or something like that.

And as the joystick range may drift (with temperature, age, etc...) and `map` does not constrain the output range, it might be a good idea to apply a `output = constrain(output, -2048, 2047)` afterwards.

(In my code, I assume that you want to map 0..4095 to -2048..2047 as you say in the text; but in your code, you map 4095..0 to -2048..2047, basically flipping the direction. If that part of your code is correct and the text is not, just swap -2048 with 2047 in my code.)


message:
Confusing stepper reaction to increase in delayMicroseconds()

I have been following [this tutorial](https://youtu.be/idVcItHfGS4?si=7FADgMjTdCiBJcJJ) using the same hardware, TB6600 driver, 42HS48-1704A (yes I think its supposed to be 42hs40 but thats not what it says the sticker) stepper but am controlling via a Nano.

The code,

    const int stepPin = 5;
    const int dirPin = 2;
    const int enPin = 8;

    int num_steps = 200;
    int dt = 1000;

    void setup() {

      pinMode(stepPin, OUTPUT);
      pinMode(dirPin, OUTPUT);
      pinMode(enPin, OUTPUT);
      digitalWrite(enPin, LOW);

    }

    void loop() {

      digitalWrite(dirPin, HIGH); // Enables the motor to move in a particular direction

      for(int x = 0; x < num_steps; x++) {

        digitalWrite(stepPin, HIGH);
        delayMicroseconds(dt);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(dt);

      }

      delay(1000); // One second delay
      digitalWrite(dirPin, LOW); //Changes the direction of rotation

      for(int x = 0; x < num_steps; x++) {

        digitalWrite(stepPin, HIGH);
        delayMicroseconds(dt);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(dt);

      }

      delay(1000);
    }

I added `dt` so I could control the step speed but its not behaving as I thought it would.

The original code has `dt = 500` which needed 15V to run & runs not quite chunky movement but bordering on it & just over 1 revolution when `num_steps = 2000`

I changed to `dt = 1000` & now its got really smooth faster motion & doing quite a few revolutions (too fast for me to count with my eyes) but if reduce `num_steps = 200` that results in 1 revolution & now only needs 9V to run.

So, how come when I increase the delay it runs faster? Is this some kind of clocking/synching issue?

body:
With `dt = 500` you get one step per millisecond. This is probably too fast for the motor/driver combination. When the driver tries to execute another step, while the previous is not fully executed by the motor shaft (which needs some time due to the shafts inertia), the magnets will misalign and the coil current of the current step will not result in a proper rotation of the shaft. Some of the pulses are aligned enough to the motor shaft position just by chance and can result in a correct step. So the motor skips some of the pulses due to its inertia. Increasing the voltage will increase the force of the motor coils, which drive the shaft. Thus it can overcome the described problems easier (the shaft moving faster by the force of one pulse than before)

Increasing to `dt = 1000` gives the motor enough time to follow each step. You aren't loosing steps because the magnets and coils in the motor always align correctly.


message:
How can I host a WiFi network from an Arduino getting a connection from a SIM card?

My friend and I are doing a project and we're stuck on a problem. We tried looking stuff up but it looks like no one documented something similar before.

Basically, what we want to do is have one Arduino (we thought a MKR NB 1500) in a remote location without any available WiFi (or Ethernet) connection be able to host its own Wifi Network. We thought that giving it a SIM card would allow it to communicate to our webserver (API) and to our surprise, it does (yay)! However, we also want **people near the Arduino to be able to access the internet**. However, that's where we're stuck...

I know that hosting an access point on an Arduino with WiFi is possible. But **is it possible for that access point to link the user to the real internet, itself provided by the SIM card**?

*P.S. : We are open to having two different Arduinos linked together (or more) in order to make this work. We just need to be able to transfer the SIM network to an access point (hotspot basically).*

*P.P.S : We are also open to using different technologies like ESP controllers... We're just not using a cellular hotspot because of the cost of these things and we want to make it with Arduino or different controllers.*

body:
Bridging of two networks at TCP/IP level is done in the TCP/IP stack. It translates addresses from one *network interface* to other *network interface*, but both interfaces are handled by the same *TCP/IP stack*.

An example on an MCU would be translating between esp8266 SoftAP and STA network interface. They are two network interfaces handled by the same TCP/IP stack. And now esp8266 Arduino can handle some Ethernet modules as additional network interfaces of that TCP/IP stack too.

With MKR NB 1500 or any other (mobile) network module attached to Arduino you can't do bridging because the TCP/IP stack is in the firmware of the module and the WiFi or Ethernet shield you would attach to the MKR would have its own TCP/IP stack in the firmware too.

If you are on esp8266, esp32 or other MCU where the TCP/IP stack runs in the MCU, you still can't make it work together with the TCP/IP stack in the external module. Those Ethernet modules esp8266 can use as netwok interaces with its TCP/IP stack are interfaced on the software layer closer to hardware, but the mobile network modules use AT commands without exposing access to lower layers.

What you can do is to proxy some network services as I write in [this answer][1].

  [1]: https://arduino.stackexchange.com/questions/57178/bridging-the-wifi-networks-on-nodemcu-how-to-set-the-esp8266-as-wifi-extender/57199#57199


message:
Ubuntu - TinyISP is not recognized

I got a Pocket AVR Programmer.

https://learn.sparkfun.com/tutorials/pocket-avr-programmer-hookup-guide

I hooked it up on Ubuntu Linux, opened up a sketch in the Arduino IDE, selected `Programmer: USBTinyISP` and then `Upload Using Programmer`.

However, I am getting this error:

    An error occured while uploading the sketch
    avrdude: Warning: cannot open USB device: Permission denied
    avrdude: Error: Could not find USBtiny device (0x1781/0xc9f)

I even followed this blog post:
https://www.krekr.nl/content/using-usbtinyisp-with-ubuntu/
and issued these commands:

In a terminal, type:

    sudo nano /etc/udev/rules.d/99-USBtiny

Then paste

    SUBSYSTEM=="usb", ATTR{idVendor}=="1781", ATTR{idProduct}=="0c9f", GROUP="adm", MODE="0666"

into the new file. Write it out by pressing Ctrl-O.

    sudo usermod -a -G plugdev YOURUSERNAME
    sudo service udev restart
    sudo udevadm control --reload-rules

However, the problem still remains.

body:
Have you installed the libusb?

> sudo apt-get install libusb-1.0-0-dev


message:
With TIMER1 in CTC mode can't get above ~200khz in arduino UNO runnning @ 16MHZ with no prescaller?

I got the following code, and based on the datasheet the Freq should be `clk / 2 * Prescaller * (1 + OCR1A)` making it that if I set the OCR1A to 0, I should get something close to **8Mhz**, but the maximum I can get is **~200kHZ**.  Can anyone help me understand why?

In FAST PWM MODE I can reach those speeds, just wanted to know why i can't in CTC MODE.
```c++
    void setup() {

        DDRB |= (1 << PINB1) ;
        TCCR1A = 0;
        TCCR1B = 0;
        OCR1A = 0;
        TCCR1B |= (1<<CS10) | (1<<WGM12);

        TIMSK1 |= (1<<OCIE1A);
        sei();
    }

    void loop() {

    }

    ISR (TIMER1_COMPA_vect){
     PORTB ^= 1 << PINB1;
    }
```

body:
I disassembled your program. Below is the code for the ISR. Next to each
instruction, I wrote the number of CPU cycles it takes, as a comment:

```lisp
; Prologue: save some registers to the stack.
push r1         ; 2
push r0         ; 2
in   r0, 0x3f   ; 1
push r0         ; 2
clr  r1         ; 1
push r24        ; 2
push r25        ; 2

; ISR body: PORTB ^= 0x02;
in   r24, 0x05  ; 1
ldi  r25, 0x02  ; 1
eor  r24, r25   ; 1
out  0x05, r24  ; 1

; Epilogue: restore registers and return.
pop  r25        ; 2
pop  r24        ; 2
pop  r0         ; 2
out  0x3f, r0   ; 1
pop  r0         ; 2
pop  r1         ; 2
reti            ; 4
```

I count a total of 31 CPU cycles, most of them spent in the
prologue and epilogue. Then, there is some overhead:

* The CPU always executes at least one instruction of the main program
  between two interrupts. Given that the main program is in a tight loop
  containing only two double-cycle instructions, that will take two CPU
  cycles.

* The CPU takes four cycles to enter interrupt mode: prevent nested
  interrupts, save the program counter and load the address of the
  interrupt vector.

* The interrupt vector is a `jmp` instruction that jumps to the ISR.
  This takes three cycles.

The minimal interrupt period is then given by this sum:

     2  one loop instruction
     4  enter interrupt mode
     3  jump to ISR
    31  execute ISR
    ────────────────────────
    40  total cycles

This takes 2.5 µs, giving an interrupt frequency of 400 kHz.
Given that you need two interrupts for a full cycle of the output
signal, the maximum you can see on the output is then 200 kHz.

You can save 10 CPU cycles by toggling the pin with:

```c++
    PINB |= 1 << PINB1;
```

This line compiles to a single double-cycle `sbi` machine instruction.
As this instruction doesn't access any CPU registers, you don't need to
save and restore `r24` and `r25`. Actually, you don't need to save and
restore any register, so you could just remove the prologue, and replace
the epilogue by a single `reti` instruction:

```c++
ISR (TIMER1_COMPA_vect, ISR_NAKED) {
    PINB |= 1 << PINB1;
    asm("reti");  // return from interrupt
}
```

This gives an ISR that executes in six cycles, and the total interrupt
period can then be as small as 15 cycles. Beware though, that you
should not write a naked ISR unless you are absolutely sure that the
code within it will not clobber any CPU register, nor the status
register.

--------------------------------------------------------------------

**Clarification**: On the face of it, the instruction

```c++
PINB |= 1 << PINB1;
```

seems to mean: “Load `PINB`, do a bitwise OR with `0x02`, then write the
result back to `PINB`”. This is, however, not how the compiler
interprets it. Instead, it takes it to mean “set bit 1 of register
`PINB` to one”. This happens to be a single machine instruction, as
`PINB` is a bit-addressable I/O registers.

Yes, the avr-gcc compiler may be a bit peculiar in this respect.


message:
Arduino pin erratic behavior?

I've built a switch key matrix (thus the diode, contextually useful schematics below) and me being me, I realised after that I misunderstood a few things about how button really works, to say the least...  So anyway, I want to save it so I plan on a solution which, to my surprise, is half-working: When I remake the entier circuit on a breadboard (mistake & solution), it's working but when I do it with my PCB, it doesn't...

The 5V+ is from a digital pin set to HIGH and I've mesured w/ an oscilloscope the tension between the ground and a digital pin ("Arduino INPUT") on the breadboard and on the PCB, with the input pin connected and not connected:

|             |Connected | Not Connected  |
| --------    | -------- | -------------- |
|  BreadBoard | 2.5V+    | 5V+            |
|  PCB        | 0V+      | 5V+            |

So it's seems like the pin is becoming one with the ground but I can't find anything that could explain this.
I've been testing and trying to understand what the hell was going on for multiple hours now and I runned out of ideas... Does anyone here have an idea of whats might happening ?

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

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

body:
Are you supplying the breadboard from a 5v power source, other than the one that is supplying the Arduino?

Is there any reason why you are using a diode between the button and the arduino pin?

Arduino can sink and source current and with the 10k resistor that diode is just "dropping" some voltage, i would remove it if you really don't have any other use for it.

If you are supplying the PCB with a different power source than the arduino, you have to "join" the 2 grounds, connect the groud from the power source of the PCB to any ground pin of the arduino. if you could take a photo that could help.

Something like this :

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

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


message:
ATTINY 85 - use host laptop's internet

Suppose I enable USB tethering (internet) on my laptop. Will it be possible to use that internet on an ATTINY 85 connected to USB.

body:
No, the attiny85 is simply too slow and not powerful enough to process your laptop's internet connection and begin something with it. If you only have to make API Request, you can hard code them into the firmware, and send the api-request-string to your computer, make your computer execute the API-request and then send the API response from the computer to the attiny to process the response there.

Regards

Dario


message:
Read byte and time into EEPROM, then display with a comma between the time and the value?

I have bytes of natural numbers 1-60 coming in at random times:

Example of send data

```c++
// Uno send

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

  int integersToSend[] = {1, 22, 30, 4, 50};
  for (int i = 0; i < 5; i++)
  {
    Serial.print(integersToSend[i]);  // send as characters
    delay(1000);
  }
}

void loop() {}
```

I want to log the time (any time format) and what value was received into EEPROM:
```c++
#include <EEPROM.h>

const int timeRefreshDisplay = 30000;
const int EEPROM_SIZE = 100; // Define size of EEPROM available
int addr = 0; // EEPROM address pointer

unsigned long programStartTime;

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600); // Initialize Serial1 for data input
  programStartTime = millis(); // Record program start time
}

void loop()
{
  if (Serial1.available())
  {
    int receivedData = Serial1.read();

    if (receivedData != 0 && receivedData <= 60)
    {
      byte receivedValue = receivedData; // Convert?

      // Calculate the timestamp based on program start time
      unsigned long currentTime = programStartTime + millis();

      // Store the received timestamp and value in EEPROM
      EEPROM.put(addr, currentTime);
      addr += sizeof(unsigned long);
      EEPROM.put(addr, receivedValue);
      addr += sizeof(int);
    }
  }

  if (millis() - programStartTime >= timeRefreshDisplay)
  {
    programStartTime = millis();
    displayEEPROMData();
  }
}

void displayEEPROMData() {
  // Display all positions stored in EEPROM
  Serial.println("EEPROM:");

  for (int i = 0; i < EEPROM_SIZE; i += sizeof(unsigned long) + sizeof(int)) {
    if (i >= EEPROM_SIZE) {
      i = 0; // Start reading from the beginning when reaching the end of EEPROM
    }

    unsigned long timestamp;
    int value;
    EEPROM.get(i, timestamp);
    EEPROM.get(i + sizeof(unsigned long), value);

    // Display position data with timestamp in HH:MM:SS format
    Serial.print(String(i / (sizeof(unsigned long) + sizeof(int)) + 1) + ": ");
    Serial.println(String(timestamp) + ", " + String(value));
  }
}
```
Serial monitor

    EEPROM:
    1: 17330, 22272
    2: 101, 27943
    3: 4143972352, 116
    4: 0, 0
    5: 0, 0
    6: 0, 0
    7: 0, 0
    8: 0, 0
    9: 0, 0
    10: 0, 0
    11: 0, 0
    12: 0, 0
    13: 0, 0
    14: 0, 0
    15: 0, 0
    16: 0, 0
    17: 0, 0

I'm not quite sure how it is reading data into EEPROM. That has to be where the issue is. I just don't know how to fix it. I tried clearing out the memory:
```c++
    #include <EEPROM.h>

    void setup() {
       // initialize the LED pin as an output.
       pinMode(13, OUTPUT);

       for (int i = 0 ; i < 22; i++) /*EEPROM.length()*/
          EEPROM.write(i, 0);

       // turn the LED on when we're done
       digitalWrite(13, HIGH);
    }

    void loop() {}
```
Serial monitor again

    EEPROM:
    1: 0, 0
    2: 0, 0
    3: 0, 0
    4: 0, 4
    5: 70, 1
    6: 22, 3
    7: 230, 2
    8: 182, 4
    9: 134, 50
    10: 234, 49
    11: 209, 50
    12: 213, 50
    13: 185, 51
    14: 189, 48
    15: 161, 52
    16: 137, 53
    17: 140, 48

I'm using a Leonardo to receive.

body:
This works.

    #include <EEPROM.h>

    const int EEPROM_SIZE = 100; // Define size of EEPROM available
    int addr = 0; // EEPROM address pointer

    unsigned long programStartTime;

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

      programStartTime = millis(); // Record program start time

      // Initialize EEPROM data
      //  for (int i = 0; i < EEPROM_SIZE; i++) {
      //    EEPROM.write(i, 0);
      //  }
      displayEEPROMData();
    }

    void loop()
    {
      if (Serial1.available())
      {
        int receivedData = Serial1.read();

        if (receivedData >= 1 && receivedData <= 60)
        {
          byte receivedValue = static_cast<byte>(receivedData); // Convert to byte

          // Calculate the timestamp based on program start time
          unsigned long currentTime = millis() - programStartTime;

          // Store the received timestamp and value in EEPROM
          EEPROM.put(addr, currentTime);
          addr += sizeof(currentTime);
          EEPROM.put(addr, receivedValue);
          addr += sizeof(receivedValue);

          displayEEPROMData();
        }
      }

      if (addr >= EEPROM_SIZE) {
        addr = 0; // Wrap around if the EEPROM is full
      }

    }

    void displayEEPROMData() {
      // Display all positions stored in EEPROM
      Serial.println("EEPROM:");

      for (int i = 0; i < EEPROM_SIZE; i += sizeof(unsigned long) + sizeof(byte)) {
        unsigned long timestamp;
        byte value;
        EEPROM.get(i, timestamp);
        EEPROM.get(i + sizeof(timestamp), value);

        // Display position data with timestamp in HH:MM:SS format
        Serial.print(String(i / (sizeof(unsigned long) + sizeof(byte)) + 1) + ": ");
        Serial.println(String(timestamp) + ", " + String(value));
      }
    }


message:
Why am I getting wrong compass heading using magnetometer readings?

I have been trying to calculate the compass heading using the magnetometer in an MPU9250 sensor. But the result is not making sense to me. I am completely new in this and do not have much understanding in how magnetometers work and just trying to find resources in the internet to make it work. I am calculating the `atan2` of the y and x axis readings of the sensor to find out the angle:

```
float mx = imu.mag_x_ut();
float my = imu.mag_y_ut();
float mz = imu.mag_z_ut();

float heading = atan2(my, mx) * 180 / PI;

Serial.print(mx);
Serial.print(",");
Serial.print(my);
Serial.print(",");
Serial.print(mz);
Serial.print(",");
Serial.println(heading);
```

My understanding is that when the `x` axis of my magnetometer faces the north direction the value of `heading` should be 0, for east 90, south 180 and then for west 270. But my calculations are nowhere near the expected results. I am not even getting a zero reading in any directon. I am attaching the screenshots of the direction reading :

This is when x axis points to north.
[![x pointed to north][1]][1]

Rotated x axis towards east.
[![x pointed to east][2]][2]

x towards south.
[![x pointed to south][3]][3]

x towards west.
[![x pointed to west][4]][4]

I have also added the raw readings from the magnetometer represnted by `mx`, `my` and `mz`. Is something wrong with my sensor or there is some misunderstanding from my part.

EDIT: Readings after hard iron offset compensation.

[![after hard iron offset][5]][5]

  [1]: https://i.stack.imgur.com/BWiup.png
  [2]: https://i.stack.imgur.com/YybqS.png
  [3]: https://i.stack.imgur.com/98QSn.png
  [4]: https://i.stack.imgur.com/72d62.png
  [5]: https://i.stack.imgur.com/W8jot.png

body:
Consider calibrating your magnetometer.  Off the shelf, almost all magnetometers require calibration before making use of their data.  The offset (commonly referred to as Hard Iron) and the magnitude (commonly referred to as Soft Iron) need to be found for each of the 3 sensors (X, Y & Z) for individual magnetometers.

As there is no accelerometer in this design let us simplify the problem and assume the magnetometer will always be used on a flat surface with its Z axis normal to the surface of the Earth.  Let us also assume the X and Y sensors in the magnetometer are perfectly orthogonal to one another.

To calibrate the magnetometer remove metal objects from the local vicinity and avoid large metal object such as cars by 10s of meters.  Sample the X and Y sensors many times as these sensors point toward and away from north.  Find the maximum and minimum X and Y values.

Find the offset calibration value by adding the minimum and maximum values then divining by 2.  Find the magnitude calibration value by arbitrarily picking one axis and adjusting the magnitude of the other to match.  Picking X, we subtract the X minimum from the X maximum to find the X range.  We do the same for Y to find the Y range.  Then we assume the X magnitude calibration value to be 1 and the Y magnitude calibration value to be x-range divided by y-range.

Once calibration is done, to get calibrated X and Y values we subtract the X and Y offset respectively.  Then we multiply the offset adjusted Y value by the Y magnitude calibration value.

Note, this type of calibrated compass is difficult to carry around by hand because it may not be held level with the surface of the earth.  Also, because the inclination of the magnetic field points deeper into the earth the more one travels away from the equator, it will require re-calibration when traveling to a different latitude.

Calibration calculations based on data in question:

    X max to min is 42 to -22 so offset is 10 and range is 64
    Y max to min is 120 to 48 so offset is 84 and range is 72
    So Y magnitude calibration is 64/72 or 0.889

Data when sensors are pointed East:

    Y ~48 & X ~11
    bearing = atan2(((48 - Y_offset) * Y_magnitude), ((11 - X_offset) * X_magnitude))
    bearing = atan2(((48 - 84) * 0.889), ((11 - 10) * 1))
    bearing = atan2(((-36) * 0.889), (1 * 1))
    bearing = atan2(-32.004, 1)
    bearing = -1.540 rad = -88.236 degrees

If instead of -88.236 degrees the value of approximately 90 degrees is desired, change the sign of the Y sensor as part of the calibration process.

The C programming function atan2 is an enhanced form of the math arc tan operation.  The C programming function atan2 will calculate to a full 2-Pi circle.  To verify how this works [use this online atan2 calculator][1].

  [1]: https://www.medcalc.org/manual/atan2-function.php


message:
Why is my LED strip value always equal to 255 on my potentiometer?

I'm pretty new to Arduino and this is my first project I'm working on and I'm really struggling with why my code isn't working properly.

The LED strip should be able to adjust the colour with one potentiometer that I can take out to so I don't use 3 potentiometers and just use that can adjust all colours. Then once it's on mode 4 it should keep the colour and blink repeatedly.

I'm using an Arduino Uno but once my project if finished I'll use the Arduino Nano. I don't know if I'll need to change the code but if I do I think I could do that on my own.

I just don't know why my LED strip is always stuck on off (255).

```c++
// set pin numbers:
int ledPinR = 11; // the number of the LED R pin
int ledPinG = 10; // the number of the LED G pin
int ledPinB = 9; // the number of the LED B pin
int buttonPin = 7; // the number of the push button pin
int mode = 0; //to change the mode
int bluelev = 0; //save the blue led value
int greenlev = 0; //save thegreen led value
int redlev = 0; // save the red led value

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPinR, OUTPUT);
  pinMode(ledPinG, OUTPUT);
  pinMode(ledPinB, OUTPUT);

  //make the led strip white at boot
  digitalWrite(ledPinR, 0);
  digitalWrite(ledPinG, 0);
  digitalWrite(ledPinB, 0);
}

void loop() {
  // when the button is pressed changes the mode value by one
  if (digitalRead(buttonPin) == LOW) {
    ++mode;
    delay(500);
  }

  if (mode == 1) { //red config
    int adcValue; // Define a variable to save the ADC value
    // Convert analog of A0 port into digital, and work as PWM duty cycle of ledPinR port
    adcValue = analogRead(A0);
    analogWrite(ledPinR, map(adcValue, 0, 1023, 0, 255));
    (redlev = ledPinR); // saves the red led level
  }

  if (mode == 2) { //green config
    int adcValue; // Define a variable to save the ADC value
    // Convert analog of A1 port into digital, and work as PWM duty cycle of ledPinG port
    adcValue = analogRead(A1);
    analogWrite(ledPinG, map(adcValue, 0, 1023, 0, 255));
    (greenlev = ledPinG); // saves the green led level
  }

  if (mode == 3) { //Blue config
    int adcValue; // Define a variable to save the ADC value
    // Convert analog of A2 port into digital, and work as PWM duty cycle of ledPinB port
    adcValue = analogRead(A2);
    analogWrite(ledPinB, map(adcValue, 0, 1023, 0, 255));
    (bluelev = ledPinB); // saves the blue led level
  }

  if (mode == 4) {
    digitalWrite(ledPinR, 255); // switch off LED
    digitalWrite(ledPinG, 255); // switch off LED
    digitalWrite(ledPinB, 255); // switch off LED
    digitalWrite(8, 0); // switch on LED
    delay(1000); //wait 1 second
    digitalWrite(ledPinR, redlev); // switch on LED
    digitalWrite(ledPinG, greenlev); // switch on LED
    digitalWrite(ledPinB, bluelev); // switch on LED
    digitalWrite(8, 225); // switch on LED
    delay(1000); //wait 1 second
  }

  if (mode == 5) {
    mode -= 5; //sets the mode value back to 0
  }
}
```

[![my circuit][1]][1]

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

Here is the setup.

Pretend the RGB LED is a LED strip and the potentiometers are just slots for one to be put in to change the colour when I want to. So when I'm not changing the colours I can use the potentiometer for other projects and not waste 3.

body:
There are at least these errors in your code:

**1. You cannot read back the analog value set to a pin.**

You try this:
```c++
    analogWrite(ledPinR, map(adcValue, 0, 1023, 0, 255));
    (redlev = ledPinR); // saves the red led level
```

You correctly set the analog value at the pin for the red LED. But then you try to read it back. Look at the definition of `ledPinR`: It is an `int` with the fixed value of 11. So `redlev` is always 11.

_Note 1: The output is not really analog, but pulse width modulated._

_Note 2: You don't need the parentheses in the second statement._

Instead, store the mapped value in `redlev`:

```c++
    redlev = map(adcValue, 0, 1023, 0, 255);
    analogWrite(ledPinR, redlev);
```

_Note 3: Use good variable names, like `redLevel`. Some time or later you will confuse things because of abbreviated names._

**2. You are not repeating the analog write in mode4.**

You wrote this, which is apparently wrong:

```c++
  if (mode == 4) {
    digitalWrite(ledPinR, 255); // switch off LED
    // other statements...
    delay(1000); //wait 1 second
    digitalWrite(ledPinR, redlev); // switch on LED
    // other statements...
    delay(1000); //wait 1 second
  }
```

Instead you want this (if 255 is really "off"):

```c++
  if (mode == 4) {
    analogWrite(ledPinR, 255); // switch off LED
    // other statements...
    delay(1000); //wait 1 second
    analogWrite(ledPinR, redlev); // switch on LED
    // other statements...
    delay(1000); //wait 1 second
  }
```

There are more issues, but this will take you a step forward. Most important, keep an indentation style, I cleaned up your source in the question to make it readable.


message:
How to create minimal web server example with a dropdown menu?

I want to create a three-item menu: Verizon, T-Mobile, AT&T. Since the example uses LEDs, I'll do the same--except with a dropdown menu to select among the three.

I'm trying to combine these two examples:

 1. https://randomnerdtutorials.com/esp8266-web-server
 2. https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select

Except with phone carriers instead of cars:

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

I'm struggling on the polyglot part of the programming, combining the HTML and Arduino program in the middle:

```lang-cpp
        // Web Page Heading
        client.println("<form action='/action_page.php'>");
        client.println("  <select id='providor' name='providor'>");
        client.println("    <option value='verizon'>Verizon</option>");
        client.println("    <option value='tmobile'>T-Mobile</option>");
        client.println("    <option value='atnt'>AT&T</option>");
        client.println("  </select>");
        client.println("  <input type='submit'>");
        client.println("</form>");

        if (providor==verizon)
          client.println("<p>Provider Selected: Verizon</p>");
        else if (providor==tmobile)
          client.println("<p>Provider Selected: T-Mobile</p>");
        else if (providor==atnt)
          client.println("<p>Provider Selected: AT&T</p>");
```

Here is the rest of the program:

```lang-cpp
/*

Based from
https://randomnerdtutorials.com/esp8266-web-server

HTML tool
https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select
*/

#include <ESP8266WiFi.h>

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
//String output5State = "off";
//String output4State = "off";

// Assign output variables to GPIO pins
const int output5 = 14;    // D5 verizon
const int output6 = 12;    // D6 tmobile
const int output7 = 13;    // D7 atnt

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output5, OUTPUT);
  pinMode(output6, OUTPUT);
  pinMode(output7, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output5, LOW);
  digitalWrite(output6, LOW);
  digitalWrite(output7, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop()
{
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    currentTime = millis();
    previousTime = currentTime;
    while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
      currentTime = millis();
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            if (header.indexOf("GET /5/on") >= 0)
            {
              Serial.println("D5 on");
              output5State = "on";
              digitalWrite(output5, HIGH);
            }
            else if (header.indexOf("GET /5/off") >= 0)
            {
              Serial.println("D5 off");
              output5State = "off";
              digitalWrite(output5, LOW);
            }
            else if (header.indexOf("GET /6/on") >= 0)
            {
              Serial.println("D6 on");
              output4State = "on";
              digitalWrite(output6, HIGH);
            }
            else if (header.indexOf("GET /6/off") >= 0)
            {
              Serial.println("D6 off");
              output4State = "off";
              digitalWrite(output6, LOW);
            }
            else if (header.indexOf("GET /7/on") >= 0)
            {
              Serial.println("D7 on");
              output4State = "on";
              digitalWrite(output7, HIGH);
            }
            else if (header.indexOf("GET /7/off") >= 0)
            {
              Serial.println("D7 off");
              output4State = "off";
              digitalWrite(output7, LOW);
            }
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");

            // HERE
            // ↓
            // ↓
            // ↓
            // ↓

            // Web Page Heading
            client.println("<form action='/action_page.php'>");
            client.println("  <select id='provider' name='providor'>");
            client.println("    <option value='verizon'>Verizon</option>");
            client.println("    <option value='tmobile'>T-Mobile</option>");
            client.println("    <option value='atnt'>AT&T</option>");
            client.println("  </select>");
            client.println("  <input type='submit'>");
            client.println("</form>");

            if (providor==verizon)
              client.println("<p>Provider Selected: Verizon</p>");
            else if (providor==tmobile)
              client.println("<p>Provider Selected: T-Mobile</p>");
            else if (providor==atnt)
              client.println("<p>Provider Selected: AT&T</p>");

            // ↑
            // ↑
            // ↑
            // ↑

            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}
```

Any suggestions or solutions on how to change or the correct code?

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

body:
First thing: be careful with matching your quotes. Every string literal
should be written as `"bla, bla, bla"`, with no unescaped double-quotes
in between. Do use the syntax highlighting: it is here precisely for
helping you spot this kind of trivial programming mistakes. Also, for
writing very long constant strings, use the C++ “raw string literal”
feature: it just makes this easier.

Second thing, you should understand how a form submission works at the
HTTP level. You should be able to find the info on the Web but, to make
it short, when the user clicks on your form, the browser will send a
request looking like

    GET /action_page.php?providor=verizon HTTP/1.1
    Some-Header-Name: some header value
    Other-Header-Name: other header value
    ...

You should parse this to find the actual provider between the `'='`
character and the following space. Also, get rid of `action_page.php`,
it is useless here.

Then a few random remarks:

* Do not write “providor”: the correct spelling is “provider” (although
  you may prefer “carrier” in this context).

* Within an HTML document, the ampersand should be written `&`.

* The HTML page needs a `<title>` element to be valid.

* Remove the whole section of the code titled “turns the GPIOs on and
  off”: it does not make sense in your context.

Now, to illustrate these points, here is how I would code parsing the
request:

```c++
// Find the provider in the URL.
String provider;
const String provider_before = "GET /?provider=";
int request_begin = header.indexOf(provider_before);
if (request_begin < 0) {
    provider = "unknown";
} else {
    int provider_begin = request_begin + provider_before.length();
    int provider_end = header.indexOf(' ', provider_begin);
    provider = header.substring(provider_begin, provider_end);
}
```

And here is how I would send the page to the client:

```c++
// At the beginning of the sketch (in global context).
const char page_before_provider[] = R"rawstr(<!DOCTYPE html>
<html>
<head>
<title>Phone carrier selection</title>
[...]
<p>Provider Selected: )rawstr";
const char page_after_provider[] = "</p>\n</body>\n</html>\n";

// At the place where the page has to be sent.
client.print(page_before_provider);
if (provider == "verizon")
    client.print("Verizon");
else if (provider == "tmobile")
    client.print("T-Mobile");
else if (provider == "atnt")
    client.print("AT&T");
else
    client.print(provider);
client.print(page_after_provider);
```


body:
Apart from the syntax errors (you aren't matching double quotes in multiple places) web pages don't work like that.

To do something like your form you:

1) Send the form, more-or-less like you have.
2)    >        if (providor==verizon)
      >            client.println("
Providor Selected: Verizon
");

      You can't test the providor (provider?) right there. Do you mean `if (providor=="verizon")`?

3) The form has to be sent to the client, the user has to fill it in, and send it back. Thus you can't test for what they filled in a line or so under sending the form.

So, testing for what they entered is a subsequent step. It's a little hard to explain without taking dozens of paragraphs. I suggest reading up on how web forms work.

---

Here's an analogy:

Say you want to write to a company and apply for a job. You fill in a form and send it off. You do not, a moment later, check to see if you got the job. The form has to go to the company. Someone has to process it. Then they make a reply. The reply might say "in reference to your job application of 11 September 2023 you were/were not successful."

It's like that with HTML. The form, which the user fills in, is the initial step. Then the user fills it in. That might be an hour later. Then they press Send and the reply comes back to you. *That's* when you process the reply.


message:
Arduino Servo with temperature sensor (TMP36)

The essence of the program is to measure the temperature, and if the temperature is higher than 26 degrees, the servo rotates by 45 degrees, and if it's lower, it rotates by 179 degrees. However, a short circuit is occurring. At the moment of the first servo rotation, the temperature jumps to 40 degrees (the temperature is calculated from voltage), and after that, the servo continuously rotates back and forth because the temperature is fluctuating between 40 and 20 degrees. What could be the cause of this issue?

My code:

    #include <Servo.h>
    Servo myServo;
    const int sensorPin = A0;
    const float baselineTemp = 20.0;
    int angle;
    void setup() {
      myServo.attach(9);
      Serial.begin(9600);
    }

    void loop() {
      int sensorVal = analogRead(sensorPin);
      Serial.println("Sensor Value: ");
      Serial.print(sensorVal);
      float voltage = (sensorVal/1024.0) * 5.0;
      Serial.println("Volts:");
      Serial.print(voltage);
      Serial.println("Celcius:");
      float temperature = (voltage - .5) * 100;
      Serial.print(temperature);
      if (temperature < baselineTemp) {
        myServo.write(179);
      } else {
        myServo.write(45);
      }
      delay(800);
    }

Output in terminal:

    sensorVal: 149
     Volts:0.73
     Celcius:22.75
     sensorVal: 192
     Volts:0.94
     Celcius:43.75
     sensorVal: 154
     Volts:0.75
     Celcius:25.20
     sensorVal: 188
     Volts:0.92
     Celcius:41.80
     sensorVal: 150
     Volts:0.73
     Celcius:23.24
     sensorVal: 184
     Volts:0.90
     Celcius:39.84
     sensorVal: 151

[![Servo from right, tmp from left][1]][1]

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

body:
You need to power the servo through a separate power supply. High power devices such as motors etc. should not be powered via the Arduino's regulator.  That is surely affecting the analogRead() and therefore also the temperature reading as already noted by @jsotola.

Secondly, you need to add some hysteresis here to prevent continuous thrashing when the temperature is around the baseline:

```
if (temperature < baselineTemp) { myServo.write(179); }
else { myServo.write(45); }
```

Maybe try something like :

 ```
if (temperature < baselineTemp - 1.0 ) { myServo.write(179); }
elseif (temperature > baselineTemp + 1.0 ) { myServo.write(45); }
 ```

You could also try adding a capacitor across the power rails of the temperature sensor say 10uF very close to the sensor itself.


message:
Is there a way to increase the number of output pins in Arduino Uno?

I am an amateur. I know about Arduino, but I am still learning.

And I was making this Bluetooth rover with a camera, ultrasonic sensor, mecanum wheels, air-soft shooter, and sand sample collector. I am using two L298 motor drivers, because [L23D][1] requires soldering and is a bit less compatible with me. So, when creating this amazing robot I realised that I ran out of pinmode spaces for the air-cannon and some other features.

So, is there a way to increase the number of output pins in an Arduino Uno or can I connect the Rx and Tx pins of the Bluetooth module and the trig and echo pin and use them both as one for two more spaces?

  [1]: https://www.ti.com/product/L293D

body:
It sounds like you are using some GPIOs ;) If you need more digital pins, you can use the analog pins as digital pins (if you didn't already).

[![Arduino Uno analog pins as digital pins][1]][1]

If you already occupied these pins, then I would think about getting an I/O expander. It's a chip/IC that can be mostly controlled via [I²C][2], offering you a way to scale your project's GPIO capabilities.

  [1]: https://i.stack.imgur.com/a7Thn.png
  [2]: https://en.wikipedia.org/wiki/I²C


body:
As an extension to [Dario.Casciato’s response][1], there are not only I²C I/O expanders, but also the simple [74HC595][2] IC, which can be cascaded and used via Arduino's [shiftOut][3] function. It needs three signal pins for 8 / 16 / 24 ...  outputs.

The link is not a purchase recommendation, but rather a technical hint.

  [1]: https://arduino.stackexchange.com/questions/94341/is-there-a-way-to-increase-the-number-of-output-pins-in-arduino-uno/94342#94342
  [2]: https://www.sparkfun.com/datasheets/IC/SN74HC595.pdf
  [3]: https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/


body:
What you probably want is called an ‘I/O Expander’. They come in many different varieties based both on exact means you use to communicate with them, how many I/O pins they give you, and what you can do with those pins.

The usual recommendation for use with an Arduino is an I²C based I/O expander, such a Microchip MCP23017 (available readily online from many sources and available in a DIP format so that you can use it with solderless breadboards), because this provides a reasonably fast interface that is very well supported on the Arduino and uses relatively few pins (only 2 pins are required, not counting Vcc and ground).

I’ve also personally used a Analog Devices DS2408 for this purpose before. It uses a 1-Wire interface, cutting the required pins down to only 1 not counting Vcc and ground, and also not actually requiring the use of a specific I/O pin like a proper I²C device would, but it’s also slower and not as nice to work with (you need a separate library to work with 1-Wire on most Arduino chips), and also only comes in SOIC packages (so requires some precise, but not necessarily difficult, soldering).

In theory you could also use an SPI I/O expander, but they are often a bit more of a pain to work with, and eat at last three pins (possibly four) other than Vcc and ground.

---

In theory, there are two other options in specific circumstances.

The first is a multiplexer chip, which is essentially a fancy solid-state switch with multiple outputs. These are only really practical if you just need to trigger external devices individually, though that may be viable for your use case (it could easily drive a simple level trigger for the airsoft gun and a simple edge trigger for the sand sample collector).

The second is to use a shift register. These are only viable if you have some way to latch outputs (for example, putting a gated D-latch on each output) or only need the outputs to be valid at specific points in time, because updating the outputs cycles each pin through the output values of each other pin. They’re great if you are doing something like implementing a parallel bus, but not as good if you need fast outputs that retain state.


message:
convert string representing a binary number to binary

I have a serial input "1111111" and I would like to convert this to a binary B1111111 that I can send to a led matrix.

I tried to search, but, all the results were misleading, led to full text to binary conversion. Please advise.

edit:
This is my sample code where I am missing a step in the conversion part

    LedControl mat = LedControl(DIN_PIN, CLK_PIN, CS_PIN, MAX_SEG); // MAX7219
    void OneLine() {

    //input
    char text[] = "11111110";
    //convert to binary number somehow

    //show one line
          mat.setRow(0, 0, convertednr);
    }

body:
As pointed out by @EdgarBonet, I can convert the string to binary number with `strtoul()` and pass this to my led control.
Adding this as an answer for future readers:

     LedControl mat = LedControl(DIN_PIN, CLK_PIN, CS_PIN, MAX_SEG); // MAX7219
    void OneLine() {

    //input
    char text[] = "11111110";
    //convert to number
    uint32_t convertednr = strtoul(text, NULL, 2);
    //print out
    mySerial.println(convertednr);

    //show one line
          mat.setRow(0, 0, convertednr);


message:
blink a Grove - RGB LED Stick

I am trying to blink a Grove - RGB LED Stick (10 - WS2813 Mini 3535) with this code:

    #include "FastLED.h"

    int ledState = LOW;       // ledState used to set the LED
    long previousMillis = 0;  // will store last time LED was updated
    long interval = 1000;     // interval at which to blink (milliseconds)

    #define NUM_LEDS 10
    CRGB myLeds[NUM_LEDS];

    void setup() {
      FastLED.addLeds<NEOPIXEL, 4>(myLeds, NUM_LEDS);
    }

    void loop() {
      unsigned long currentMillis = millis();
      FastLED.setBrightness(25);

      if (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;

        // if the LED is off turn it on and vice-versa:
        if (ledState == LOW) {
          for (int i = 0; i < NUM_LEDS; i++) {
            myLeds[i] = CRGB::White;
            FastLED.show();
          }
        } else {
          for (int i = 0; i < NUM_LEDS; i++) {
            myLeds[i] = CRGB::Black;
            FastLED.show();
          }
        }
      }
    }

Any idea why it does not blink?

Thanks

body:
In your code, you define the global variable `ledState` and initialize it to the value "LOW".

In the `loop()` function, the `ledState` variable is used to determine the (next) state of the LED once every 1000 milliseconds, like this:

    ...
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      for (int i = 0; i < NUM_LEDS; i++) {
        myLeds[i] = CRGB::White;
        FastLED.show();
      }
    } else {
      for (int i = 0; i < NUM_LEDS; i++) {
        myLeds[i] = CRGB::Black;
        FastLED.show();
      }
    }
    ...

However, since your code does not change value of `ledState` to reflect the new state of the LED array, the next time the above `if (...)` comparison is run, the outcome is the same and the color of the LEDs not be changed.

The simplest change to make your LEDs blink as you intended, would be to change the above piece of code to the following:

    ...
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      for (int i = 0; i < NUM_LEDS; i++) {
        myLeds[i] = CRGB::White;
        FastLED.show();
        ledState = HIGH;
      }
    } else {
      for (int i = 0; i < NUM_LEDS; i++) {
        myLeds[i] = CRGB::Black;
        FastLED.show();
      }
      ledState = LOW;
    }
    ...

An alternative (arguably more elegant) solution would be to declare `ledState` as a boolean (true/false) variable so that you can further simplify your code:

    #include "FastLED.h"

    bool ledState = false;    // ledState used to set the LED
    long previousMillis = 0;  // will store last time LED was updated
    long interval = 1000;     // interval at which to blink (milliseconds)

    #define NUM_LEDS 10
    CRGB myLeds[NUM_LEDS];

    void setup() {
      FastLED.addLeds<NEOPIXEL, 4>(myLeds, NUM_LEDS);
    }

    void loop() {
      unsigned long currentMillis = millis();
      FastLED.setBrightness(25);

      if (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;

        // if the LED is off turn it on and vice-versa:
        if (!ledState) {
          for (int i = 0; i < NUM_LEDS; i++) {
            myLeds[i] = CRGB::White;
            FastLED.show();
          }
        } else {
          for (int i = 0; i < NUM_LEDS; i++) {
            myLeds[i] = CRGB::Black;
            FastLED.show();
          }
        }
        ledState = !ledState;    // make ledState reflect the new LED state

      }
    }


message:
Is the EEPROM the best alternative for store non-volatile values with Arduino?

SD-cards are capable of store values even if it is turned off.

I don't know what is the time that a EEPROM can keep a value in it's memory, but of course are better than the volatile memory.

There are some others ways of store non-volatile values for arduino?

Which of these need hardware built-in and which doesn't?

Are the EEPROM the best alternative (in terms of facility, durability, and cost) for store non-volatile values when we talk about Arduinos (or even microcontrollers in general)?

body:
EEPROM on the Atmega328P (such as on the Arduino Uno) holds 1KB (1024 bytes) and has a documented write/erase cycle of 100,000 writes.

So, if your application only needs to store 1024 bytes in a non-volatile way, and you do not plan to write more than 100,000 times then that is suitable.

The sort of things I would use EEPROM for are remembering settings (eg. fan speed, oven temperature, a password for accessing WiFi, that sort of thing).

I also personally use it for "remembering" RFID card codes for access to my house. In my experience, using it for that purpose, it has never "forgotten" a code. According to the datasheet it will retain data for 100 years at 25°C.

It is convenient because you don't need any extra hardware.

---

Other alternatives are SPI or I2C based external EEPROM, such as NVRAM (non-volatile RAM) which would have larger capacity, but you would need to connect it. That would likely be about 5 wires and somewhere to put the chip. An example of that is [Adafruit I2C FRAM Breakout](https://learn.adafruit.com/adafruit-i2c-fram-breakout/wiring-and-test).

[![FRAM breakout board][1]][1]

---

You could use a micro-SD card, which I have used on [another project](https://www.gammon.com.au/forum/?id=12106) to record temperature readings every 15 minutes. This has a lot more capacity than EEPROM, and then you can just take the SD card out and read it in an ordinary PC. This needs extra hardware (eg. a holder for the SD card and possibly voltage-level shifters). However you can buy that for around $20, and it is easy enough to hook up.

[![Micro SD card breakout board][2]][2]

---

I don't know how SQL got into the discussion under the question, but that is a language (Structured Query Language) and not a piece of hardware.

---

Another alternative, if you don't particularly want portability, is to send your data along a connection to your PC, and record the data there. Conceivably WiFi could be used for that.

---

## Speed

Speed-wise, I would say EEPROM is the fastest because it is natively inside the chip. Other alternatives required sending messages along wires (I2C, SPI, or maybe USB) to somewhere else and that takes time.

Writing is slower than reading, because writing involves using electricity to make a chemical change in the chip (turning a 1-bit into a 0-bit) but it is still quite fast.

  [1]: https://i.stack.imgur.com/ohktH.jpg
  [2]: https://i.stack.imgur.com/5M901.png


message:
Can Arduino UNO/MEGA master assert SPI SS LOW on multiple slaves at once if Full Duplex is unnecessary?

I have a computer talking serially to an UNO SPI Master and, beyond it, multiple MEGA Slaves.  The slaves never talk back to the master.

I understand it is normal and correct to assert **SS LOW** to select one slave at a time, such that the master clocks bits via **MOSI** to the selected slave on the same clock edges the slave sends bits to the master via **MISO**.

Multiple slaves clocking on MISO would garble the communication back to the master.  But what if I don't care?  Instead, on a system with a pulled-up MISO pin that does not even have MISO wires attached, what if the master selects all the slaves at once, then clocks a byte out on MOSI with a bit set calling for one specific slave (of 8 possible) to respond to subsequent bytes?  That is way faster than the master sorting out with code which slave should get the message originating in the computer.  ALL the slaves can check the bit they expect and ignore the subsequent bytes of the SPI message if the bit is CLEAR-- they are not doing anything else at the moment anyway, say.

What is wrong with this idea?  Are there electronic issues in the UNO or MEGAs I am not thinking of?  Is this done?  Why not?

body:
> What is wrong with this idea?

Nothing, this is perfectly possible. The main advantage is the avoidance of multiple SS lines, reducing pin count and/or decoding hardware.

The SPI main device does not know the number of SPI sub devices, and it will happily sample the level at the MISO pin, whatever you give it.

Each SPI sub device does not know that the other SPI sub devices receive the very same bytes. As you write, if the first byte (or any other protocol detail) tells it to ignore the rest of the transmission, it will.

> Are there electronic issues in the UNO or MEGAs I am not thinking of?

You need to read the data sheet to learn about the load of each input of the SPI sub devices, and the guaranteed provided drive capability of each output of the SPI main device, that means SS, SCLK, MOSI. Then make sure the driver can drive all receivers.

Commonly you can connect a two-digit number without any concern.You write that you have eight, so just go ahead.

You can leave the MISO outputs of the SPI sub devices simply unconnected. At the SPI main device make sure you have a pull-up or pull-down resistor on its MISO input.

> Is this done?

I have no personal experience or example, but I'm sure it is done.

> Why not?

When you actually need responses from the SPI sub devices, you need to do it differently. However, even then you can combine all the MISO outputs of the SPI sub devices with some clever digital logic.

---

Note: I prefer "main" and "sub", which still match the abbreviations, instead of the old terms of the former century.


body:
The electronic circuit of an SPI work this way,  when a slave device is not been selected (i.e. its CS pin is not asserted), its MISO line will be in tri-state output, i.e. it is in a high impedance floating state, electrically disconnect, this allows multiple devices sharing the same MISO bus. For this reason, you can't tie all the slave devices with a single CS pin as all the MISO outputs from the devices will be activated.

If you don't care about the MISO data clocking in from the slave devices, you simple don't connect the MISO pin to the bus.


message:
How to get recover numeric data sent by an Arduino in binary

I am a C# dev and these C++ data conversions are killing me.

I have an Arduino sending binary data through LoRaWAN to AzureIOT. I am trying to decode my Temp/Humid/Bat payload that I am pulling out of AzureIOT Hub.

Here is a sample method I am using in C# to parse the byte array. Once I have parsed it, how do I convert those numbers back to their actual values?

Here is the input data on the sensor side:

>T=74.48
>
>RH=45.20
>
>BatteryVoltage:3332

Thanks.
Here is how the data was input:

```
float temperature = readDHTTemperature(); //this method prints T to Serial
float humidity = readDHTHumidity(); //this method prints H to Serial
uint16_t batteryVoltage = readBattery(true);
delay(100);

unsigned char *puc;

puc = (unsigned char *)(&temperature);
appDataSize = 10;
appData[0] = puc[0];
appData[1] = puc[1];
appData[2] = puc[2];
appData[3] = puc[3];

puc = (unsigned char *)(&humidity);
appData[4] = puc[0];
appData[5] = puc[1];
appData[6] = puc[2];
appData[7] = puc[3];

appData[8] = (uint8_t)(batteryVoltage>>8);
appData[9] = (uint8_t)batteryVoltage;

```

Here is the output:

```
private static void BytesToString()
{
 var hexStringFromPayLoad = "MzOYQgAAHEINBA==";
 var bytes = Base64Decode(hexStringFromPayLoad);

 Console.WriteLine($"Temp: {bytes[0]}, {bytes[1]}, {bytes[2]}, {bytes[3]}");
 Console.WriteLine($"Humid: {bytes[4]}, {bytes[5]}, {bytes[6]}, {bytes[7]}");
 Console.WriteLine($"Bat: {bytes[8]}, {bytes[9]}");

 /*
 Temp: 51, 51, 152, 66
 Humid: 0, 0, 28, 66
 Bat: 13, 4
 */
}
```

body:
Arduinos use very standard formats for their internal binary
representations of data:

* integers are in [two's complement][]
* floats follow the [IEEE 754 standard][ieee754]
* both are little-endian.

This is the same as your typical x86\_64. The implication is that, once
the bytes are in your PC, you do not need to perform any conversion at
all. All you need to do is either alias or copy the bytes to the memory
locations of the variables that are meant to get the values.

Example in plain C:

```c
uint8_t temperature_bytes[] = { 51, 51, 152, 66 };
float temperature;
memcpy(&temperature, temperature_bytes, sizeof temperature);
// now `temperature` holds the value 76.1.
```

How you would do this in C# is a question that is out of topic in this
site.

[ieee754]: https://en.wikipedia.org/wiki/IEEE_754-1985
[two's complement]: https://en.wikipedia.org/wiki/Two's_complement