# Question
Title: Understanding why should avoid “String” and alternative solutions
1. **Why “Strings” are bad for Arduino?**
2. **Which is the most efficient and fastest solution to read and store the data from Accelerometer and GPS?**

---

## ***Stings are evil for Arduino***

---

An Uno or other ATmega328-based board only has 2048 bytes SRAM.

The SRAM is composed by three parts:

1. The Static
2. The Heap
3. The Stack

**The Heap is where, randomly, a C++ string information is allocated.**

If I add an information to my C++ String the system copies itself and deletes the old copy leaving a hole in the heap, that grows up with the cycles.

When I wrote my first sketch for reading and writing the information from an MPU6050 and stored on a SD (whithout connecting to a GPS) I noticed that the sampling time was not constant.

Thanks to the feedback obtained in this question on StackOverflow, I understood that the problem was my excessive use of strings, and now i understand why.

So I started to dig into this issue.

This was one of the first version of the code:

```
/******************************************************************************
  CSV_Logger_TinyGPSPlus.ino
  Log GPS data to a CSV file on a uSD card
  By Jim Lindblom @ SparkFun Electronics
  February 9, 2016
  https://github.com/sparkfun/GPS_Shield

  This example uses SoftwareSerial to communicate with the GPS module on
  pins 8 and 9, then communicates over SPI to log that data to a uSD card.

  It uses the TinyGPS++ library to parse the NMEA strings sent by the GPS module,
  and prints interesting GPS information - comma separated - to a newly created
  file on the SD card.

  Resources:
  TinyGPS++ Library  - https://github.com/mikalhart/TinyGPSPlus/releases
  SD Library (Built-in)
  SoftwareSerial Library (Built-in)

  Development/hardware environment specifics:
  Arduino IDE 1.6.7
  GPS Logger Shield v2.0 - Make sure the UART switch is set to SW-UART
  Arduino Uno, RedBoard, Pro, Mega, etc.
******************************************************************************/

#include <SPI.h>
#include <SD.h>
#include <TinyGPS++.h>
#include<Wire.h>
#define ARDUINO_USD_CS 10 // uSD card CS pin (pin 10 on SparkFun GPS Logger Shield)

/////////////////////////
// Log File Defintions //
/////////////////////////
// Keep in mind, the SD library has max file name lengths of 8.3 - 8 char prefix,
// and a 3 char suffix.
// Our log files are called "gpslogXX.csv, so "gpslog99.csv" is our max file.
#define LOG_FILE_PREFIX "gpslog" // Name of the log file.
#define MAX_LOG_FILES 100 // Number of log files that can be made
#define LOG_FILE_SUFFIX "csv" // Suffix of the log file
char logFileName[13]; // Char string to store the log file name
// Data to be logged:
#define LOG_COLUMN_COUNT 15
char * log_col_names[LOG_COLUMN_COUNT] = {
  "longitude", "latitude", "altitude", "speed", "course", "date", "time", "satellites","Acc.X","Acc.Y","Acc.Z","Gy.X","Gy.Y","Gy.Z","Temp"
}; // log_col_names is printed at the top of the file.

//////////////////////
// Log Rate Control //
//////////////////////
#define LOG_RATE 1000 // Log every 1 seconds
unsigned long lastLog = 0; // Global var to keep of last time we logged

/////////////////////////
// TinyGPS Definitions //
/////////////////////////
TinyGPSPlus tinyGPS; // tinyGPSPlus object to be used throughout
#define GPS_BAUD 9600 // GPS module's default baud rate

/////////////////////////////////
// GPS Serial Port Definitions //
/////////////////////////////////
// If you're using an Arduino Uno, Mega, RedBoard, or any board that uses the
// 0/1 UART for programming/Serial monitor-ing, use SoftwareSerial:
#include <SoftwareSerial.h>
#define ARDUINO_GPS_RX 9 // GPS TX, Arduino RX pin
#define ARDUINO_GPS_TX 8 // GPS RX, Arduino TX pin
SoftwareSerial ssGPS(ARDUINO_GPS_TX, ARDUINO_GPS_RX); // Create a SoftwareSerial

// Set gpsPort to either ssGPS if using SoftwareSerial or Serial1 if using an
// Arduino with a dedicated hardware serial port
#define gpsPort ssGPS  // Alternatively, use Serial1 on the Leonardo

// Define the serial monitor port. On the Uno, Mega, and Leonardo this is 'Serial'
//  on other boards this may be 'SerialUSB'
#define SerialMonitor Serial
const int MPU=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

void setup()
{
   Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  SerialMonitor.begin(9600);
  gpsPort.begin(GPS_BAUD);

  SerialMonitor.println("Setting up SD card.");
  // see if the card is present and can be initialized:
  if (!SD.begin(ARDUINO_USD_CS))
  {
    SerialMonitor.println("Error initializing SD card.");
  }
  updateFileName(); // Each time we start, create a new file, increment the number
  printHeader(); // Print a header at the top of the new file
}

void loop()
{
 Wire.beginTransmission(MPU);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,14,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
{
  if ((lastLog + LOG_RATE) <= millis())
  { // If it's been LOG_RATE milliseconds since the last log:
    if (tinyGPS.location.isUpdated()) // If the GPS data is vaild
    {
      if (logGPSData()) // Log the GPS data
      {
        SerialMonitor.println("GPS logged."); // Print a debug message
        lastLog = millis(); // Update the lastLog variable
      }
      else // If we failed to log GPS
      { // Print an error, don't update lastLog
        SerialMonitor.println("Failed to log new GPS data.");
      }
    }
    else // If GPS data isn't valid
    {
      // Print a debug message. Maybe we don't have enough satellites yet.
      SerialMonitor.print("No GPS data. Sats: ");
      SerialMonitor.println(tinyGPS.satellites.value());
    }
  }

  // If we're not logging, continue to "feed" the tinyGPS object:
  while (gpsPort.available())
    tinyGPS.encode(gpsPort.read());
}
}

byte logGPSData()
{
  File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file

  if (logFile)
  { // Print longitude, latitude, altitude (in feet), speed (in mph), course
    // in (degrees), date, time, and number of satellites.
    logFile.print(tinyGPS.location.lng(), 6);
    logFile.print(',');
    logFile.print(tinyGPS.location.lat(), 6);
    logFile.print(',');
    logFile.print(tinyGPS.altitude.feet(), 1);
    logFile.print(',');
    logFile.print(tinyGPS.speed.mph(), 1);
    logFile.print(',');
    logFile.print(tinyGPS.course.deg(), 1);
    logFile.print(',');
    logFile.print(tinyGPS.date.value());
    logFile.print(',');
    logFile.print(tinyGPS.time.value());
    logFile.print(',');
    logFile.print(tinyGPS.satellites.value());
    logFile.print(AcX);
    logFile.print(',');
    logFile.print(AcY);
    logFile.print(',');
    logFile.print(AcZ);
    logFile.print(',');
    logFile.print(GyX);
    logFile.print(',');
    logFile.print(GyY);
    logFile.print(',');
    logFile.print(GyZ);
    logFile.print(',');
    logFile.print(Tmp);
    logFile.println();
    logFile.close();

    return 1; // Return success
  }

  return 0; // If we failed to open the file, return fail
}

// printHeader() - prints our eight column names to the top of our log file
void printHeader()
{
  File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file

  if (logFile) // If the log file opened, print our column names to the file
  {
    int i = 0;
    for (; i < LOG_COLUMN_COUNT; i++)
    {
      logFile.print(log_col_names[i]);
      if (i < LOG_COLUMN_COUNT - 1) // If it's anything but the last column
        logFile.print(','); // print a comma
      else // If it's the last column
        logFile.println(); // print a new line
    }
    logFile.close(); // close the file
  }
}

// updateFileName() - Looks through the log files already present on a card,
// and creates a new file with an incremented file index.
void updateFileName()
{
  int i = 0;
  for (; i < MAX_LOG_FILES; i++)
  {
    memset(logFileName, 0, strlen(logFileName)); // Clear logFileName string
    // Set logFileName to "gpslogXX.csv":
    sprintf(logFileName, "%s%d.%s", LOG_FILE_PREFIX, i, LOG_FILE_SUFFIX);
    if (!SD.exists(logFileName)) // If a file doesn't exist
    {
      break; // Break out of this loop. We found our index
    }
    else // Otherwise:
    {
      SerialMonitor.print(logFileName);
      SerialMonitor.println(" exists"); // Print a debug statement
    }
  }
  SerialMonitor.print("File name: ");
  SerialMonitor.println(logFileName); // Debug print the file name
}

```

Then I started:

1. Studying how Arduino Memory works
2. Breaking the problem, focusing only to learn how to read and write on a SD the accelerometer information (the device is not connected to the PC)

The following code is my latest version:

```
 void Read_Write()
 // function that reads the MPU and writes the data to the SD.
  {
   // Local variables:
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; // Variables read from MPU6050

// Read data:
Wire.beginTransmission(MPU);
Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true);  // request a total of 14 registers
AcX = Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY = Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ = Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

GyX = Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY = Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ = Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

// Data preparation for file saving:
String dataString = ""; // string for assembling the data to log:

// Add time tag:
dataString += String(Time0); dataString += ",";

// Append the MPU6050 data to the string:
dataString += String(AcX); dataString += ",";
dataString += String(AcY); dataString += ",";
dataString += String(AcZ); dataString += ",";
dataString += String(GyX); dataString += ",";
dataString += String(GyY); dataString += ",";
dataString += String(GyZ);

// Open the file in append mode:
File dataFile = SD.open("datalog.txt", FILE_WRITE);

// If the file is available, write to it:
if (dataFile)
{
dataFile.println(dataString);
dataFile.close();
if (Serial_plus_SD)
  Serial.println(dataString);
}
// if the file does not open, pop up an error:
else
errorFW();

return;
}

```

I recived other suggestions such as ***"create a Buffer", but without a technical description and motivation I am having difficulties understand how to do it***.

(I don’t want to simply copy&paste the code as i have done intitially with the first version)

I have to use C Strings instead of C++ Strings?

I have a civil engineer background, so is my first time with coding.

***Thank you for your patience.***

# Answer
First, let me point out a problem in your code, completely unrelated to your question:

```
AcX = Wire.read()<<8|Wire.read();

```

The C++ standard does not specify in which order the two reads will be performed. This may work well with the particular version of the particular compiler you are using, but it can break the day you (or an update to the Arduino IDE) changes the compiler version or a compiler flag. You should instead do a single read per statement, e.g.:

```
AcX  = Wire.read() << 8;
AcX |= Wire.read();

```

Next, I would like to say that the simplest Arduino way of doing what you are trying to do is to use neither a `String` nor a character array. Instead, open the file first, then format and send the data on the fly using `print()` or `println()`:

```
dataFile.print(Time0); dataFile.print(",");
dataFile.print(AcX);   dataFile.print(",");
[...]

```

This way you never need to store the whole string in memory. It is then a very memory-friendly solution.

Now, I realize this seems inconvenient if you want to print the data to both the SD file and the serial port. In such a case you could put the printing code inside a function that can print to any `Print` object (for instance the data file and `Serial`), and you can then call the function twice:

```
static void printImuData(Print &printer, int16_t Time0,
        int16_t AcX, int16_t AcY, int16_t AcZ,
        int16_t GyX, int16_t GyY, int16_t GyZ)
{
    printer.print(Time0); printer.print(",");
    printer.print(AcX);   printer.print(",");
    [...]
}

[...]

printImuData(dataFile, Time0, AcX, AcY, AcZ, GyX, GyY, GyZ);
if (Serial_plus_SD)
    printImuData(Serial, Time0, AcX, AcY, AcZ, GyX, GyY, GyZ);

```

Alternatively, you could use a kind of tee to duplicate the data to both streams. See for example this implementation.

**Edit**: A more elegant way to achieve the same would be to wrap all the IMU data into a `struct` (or a `class`), and then make the whole thing printable:

```
struct ImuData : public Printable
{
    uint16_t Time0, AcX, AcY, AcZ, GyX, GyY, GyZ;
    size_t printTo(Print& p) const;
};

size_t ImuData::printTo(Print& p) const
{
    size_t bytes = 0;
    bytes += p.print(Time0); bytes += p.write(',');
    [...]
    bytes += p.print(GyZ);
    return bytes;
}

```

The you can print the `struct` like you would print the string:

```
ImuData imu;
imu.Time0 = ...;
imu.AcX   = Wire.read() << 8;
imu.AcX  |= Wire.read();
[...]

dataFile.println(imu);
if (Serial_plus_SD)
    Serial.println(imu);

```
> 4 votes

# Answer
Edgar answers your first question about `String` and printing very nicely. Majenko also has a nice description here of the pitfalls.

Regarding your **second** question about GPS/efficiency/speed:

1. use NeoGPS,
2. use AltSoftSerial,
3. use the MPU FIFO,
4. use the up-to-date SdFat,
5. watch out for SD write delays, and
6. `close` the log file at some point.

---

**1.** NeoGPS is the smallest, fastest and most accurate GPS parser available. The example programs are structured properly, and there is an example for SD logging.

NeoGPS has a FIFO of fixes, unlike other libraries. This avoids "sampling" the GPS at some rate defined by `millis()`. The Arduino crystal is not as accurate as the atomic GPS clock, so your logging rate should be based off a fix becoming available, at exactly one per second. Your sketch will "drift" against the GPS updates, losing a fix periodically (depending on the accuracty of the crystal).

**2.** Perhaps the single greatest improvement you could achieve is **NOT** to use `SoftwareSerial`. It is very inefficient, because it disables interrupts for long periods of time. At 9600, it disables interrupts for 1ms while each character from the GPS device is received. The Arduino could have executed ~10000 instructions during that time, but instead it twiddles its thumbs while *waiting exclusively* for each bit of a byte to arrive... -\_-

Instead, you should use `AltSoftSerial`, as you have connected the GPS device to the required pins, 8 & 9. If you were using two other pins, you could have used my NeoSWSerial. Both of these libraries are *much, much* more efficient than `SoftwareSerial`.

**3.** If you want evenly-spaced MPU samples, put the device in the FIFO mode. It will write the selected registers into a FIFO at a selected sampling time. This also gives you a little flexibility in reading the sample: you just have to read it before the 1024-byte FIFO fills up.

**4.** You are using an old version of the SD library. I strongly suggest that you use the latest SdFat library. It has many improvements and bug fixes.

**5.** Some SD cards will occasionally take a longer time to write. The 47ms write time is not unusual. In fact, 100ms is fairly common. As long as the MPU FIFO does not overflow during this time, you will not lose any MPU samples.

If you find that an SD write occasionally causes the FIFO to overflow, you may have to modify the SDFat library to call a `yield` function while it's waiting for the write to complete. This `yield` function can read from the FIFO during that time, saving the samples into an Arduino RAM area.

**6.** I would recommend that you `close` the logFile when some event occurs. Perhaps a button press? You can use the LED to indicate that logging is active or inactive. You could also watch for inactivity for some period of time (no speed, MPU zero values).

---

With those suggestions, here is a NeoGPS/AltSoftSerial/SdFat version of your original sketch (GPS tested, MPU/SD untested but compiles):
```
#include <SPI.h>
#include <SdFat.h>
#include <NMEAGPS.h>
#include <Wire.h>
#define ARDUINO_USD_CS 10 // uSD card CS pin (pin 10 on SparkFun GPS Logger Shield)

/////////////////////////
// Log File Defintions //
/////////////////////////
// Keep in mind, the SD library has max file name lengths of 8.3 - 8 char prefix,
// and a 3 char suffix.
char logFileName[13] = "gpslogXX.csv";
// Our log files are called "gpslogXX.csv, so "gpslog99.csv" is our max file.
#define MAX_LOG_FILES 100 // Number of log files that can be made

// Data to be logged:
#define LOG_COLUMN_HEADER \
  "longitude," "latitude," "altitude," "speed," "course," "date," "time," \
  "satellites," "Acc.X," "Acc.Y," "Acc.Z," "Gy.X," "Gy.Y," "Gy.Z," "Temp"
  // printed at the top of the file.

SdFat SD;
File  logFile;

/////////////////////////
// NeoGPS Definitions //
/////////////////////////
NMEAGPS gps; // NeoGPS object to be used throughout
gps_fix fix; // The latest GPS information received from the gpsPort
#define GPS_BAUD 9600 // GPS module's default baud rate

/////////////////////////////////
// GPS Serial Port Definitions //
/////////////////////////////////
// If you're using a Mega, Leo or Due, use Serial1 for the GPS:
//#define gpsPort Serial1

// If you're using an Arduino Uno or other ATmega328 board that uses the
// 0/1 UART for programming/Serial monitor-ing, use AltSoftSerial:
#include <AltSoftSerial.h>
AltSoftSerial gpsPort; // Always on pins 8 & 9
//If you can't use pins 8 & 9, use this:
//#include <NeoSWSerial.h>
//NeoSWSerial gpsPort( 2, 3 ).

// Define the serial monitor port. On the Uno, Mega, and Leonardo this is 'Serial'
//  on other boards this may be 'SerialUSB'
#define SerialMonitor Serial

//#define USE_MPU
const int MPU=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

void setup()
{
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  SerialMonitor.begin(9600);
  gpsPort.begin(GPS_BAUD);

  SerialMonitor.println( F("Setting up SD card.") );

  updateFileName(); // Each time we start, create a new file, increment the number
  // see if the card is present and can be initialized:
  if (!SD.begin(ARDUINO_USD_CS))
  {
    SerialMonitor.println( F("Error initializing SD card.") );
  } else {
    logFile = SD.open( logFileName, FILE_WRITE );
    // Print a header at the top of the new file
    logFile.println( F(LOG_COLUMN_HEADER) );
  }

}

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

  while (gps.available( gpsPort )) {
    fix = gps.read();  // get the entire fix structure, once per second

    if (logGPSData()) { // Log the GPS data
      SerialMonitor.println( F("GPS logged.") ); // Print a debug message
    } else {// If we failed to log GPS
      // Print an error, don't update lastLog
      SerialMonitor.println( F("Failed to log new GPS data.") );
    }
  }
}

byte logGPSData()
{
  if (logFile.isOpen())
  { // Print longitude, latitude, altitude (in feet), speed (in mph), course
    // in (degrees), date, time, and number of satellites.

    if (fix.valid.location)
      logFile.print(fix.longitude(), 6);
    logFile.print(',');
    if (fix.valid.location)
      logFile.print(fix.latitude(), 6);
    logFile.print(',');
    if (fix.valid.altitude)
      logFile.print(fix.altitude() * 3.2808, 1);
    logFile.print(',');
    if (fix.valid.speed)
      logFile.print(fix.speed_mph(), 1);
    logFile.print(',');
    if (fix.valid.heading)
      logFile.print(fix.heading(), 1);
    logFile.print(',');

    if (fix.valid.date) {
      logFile.print( fix.dateTime.full_year() );
      if (fix.dateTime.month < 10)
        logFile.print( '0' );
      logFile.print( fix.dateTime.month );
      if (fix.dateTime.date < 10)
        logFile.print( '0' );
      logFile.print( fix.dateTime.date );
    }
    logFile.print(',');

    if (fix.valid.time) {
      if (fix.dateTime.hours < 10)
        logFile.print( '0' );
      logFile.print( fix.dateTime.hours );
      if (fix.dateTime.minutes < 10)
        logFile.print( '0' );
      logFile.print( fix.dateTime.minutes );
      if (fix.dateTime.seconds < 10)
        logFile.print( '0' );
      logFile.print( fix.dateTime.seconds );
    }
    logFile.print(',');

    if (fix.valid.satellites)
      logFile.print(fix.satellites);
    logFile.print(',');
    logFile.print(AcX);
    logFile.print(',');
    logFile.print(AcY);
    logFile.print(',');
    logFile.print(AcZ);
    logFile.print(',');
    logFile.print(GyX);
    logFile.print(',');
    logFile.print(GyY);
    logFile.print(',');
    logFile.print(GyZ);
    logFile.print(',');
    logFile.print(Tmp);
    logFile.println();
    logFile.flush(); // make sure the file contains at least this much

    return 1; // Return success
  }

  return 0; // If we failed to open the file, return fail
}

// updateFileName() - Looks through the log files already present on a card,
// and creates a new file with an incremented file index.
void updateFileName()
{
  for (uint8_t i; i < MAX_LOG_FILES; i++)
  {
    // Set logFileName to "gpslogXX.csv":
    logFileName[6] = (i/10) + '0';
    logFileName[7] = (i%10) + '0';

    if (!SD.exists(logFileName))
      break; // We found our index

    SerialMonitor.print(logFileName);
    SerialMonitor.println( F(" exists") );
  }
  SerialMonitor.print( F("File name: ") );
  SerialMonitor.println(logFileName);
}

```

Your original sketch used 24114 bytes of program space and 1690 bytes of RAM. The NeoGPS version uses 21198 bytes of program space and 1400 bytes of RAM, **a significant savings**.

Minor points:

* It uses the F macro to save RAM
* It opens the log file in `setup` and flushes after every GPS update. You should investigate when to `close` the log file.
* It reads IMU samples as fast as possible, but you should switch this to the FIFO approach
* It doesn't use `sprintf` to compose the log filename (this saves program space)
* The column header does not need to be an array of character strings. It can be one `#define`. The F macro is applied when it is printed.
* It only prints GPS fields if they have a valid value.
* Comments in the GPS port section were wrong about using `SoftwareSerial` on a Mega.
* Obvious comments deleted. The `else` of an `if` statement does not deserve an `// otherwise` comment. -\_-
> 4 votes

# Answer
I would use sprintf, with a statically allocated buffer.

**E.g.**

substitute

```
// Data preparation for file saving:
String dataString = ""; // string for assembling the data to log:

// Add time tag:
dataString += String(Time0); dataString += ",";

// Append the MPU6050 data to the string:
dataString += String(AcX); dataString += ",";
dataString += String(AcY); dataString += ",";
dataString += String(AcZ); dataString += ",";
dataString += String(GyX); dataString += ",";
dataString += String(GyY); dataString += ",";
dataString += String(GyZ);

```

with

```
static char pippo[PIPPO_SIZE];
int ret = sprintf(pippo, "%lu,%d,%d,%d,%d,%d,%d",
                         (uint32_t) Time0, AcX, AcY, AcZ, GyX, GyY, GyZ);

// This is just for debugging purposes to test the code
if (ret < 0) {
    // failure: no byte written
} else if (ret >= PIPPO_SIZE) {
    // failure: too many bytes written, I did some mistake :(
} else {
    // ok
}

```

---

The size of the buffer `pippo` is computed as follows:

* `1 byte` for each comma, you have 6
* `6 bytes` for each `int16_t` variable (`5 bytes` for the digits plus `1 byte` for the sign, which however you might not need)
* `10 bytes` for `Time0`, which I assume is of type `unsigned long` which in *Arduino* is 32 bits.
* `1 byte` for closing `\0`

So it should be `1 * 6 + 6 * 6 + 10 + 1 = 53` unless I did some mistake. Add the following at the top of your program:

```
#define PIPPO_SIZE 53

```

---

The motivation for using statically allocated memory is simple, and is already stated in your question: the concatenation of `String` objects results in repeated calls to `new` and `delete` with subsequent *allocation* and *de-allocation* of *dynamic memory*, which gets fragmented. More over, the `String`-based approach is intuitively *slower* because it requires many more steps to accomplish basically the same simple task.

`String` aren't bad *per se*, but in your application you want to squeeze every last fragment of performance that you can, so there's that.
> 3 votes

# Answer
There is now as SafeString library available for Arduino, via the Library Manager (mine :-) )
**SafeStrings are GOOD for Arduino**
They are only ever placed in Static or Stack memory and so completely avoid heap fragementation and small transient object construction and unnecessary data coping, NEVER causes your sketch to reboot and has extensive debugging and error messages.

SafeStrings are designed to be uses by Beginners and includes extensive error checking and detailed error messages to help you find the errors and correct your code. SafeStrings also corrects a number of errors that are in the String code.

There is a detailed tutorial at
https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
and extensive examples include in the library, including parsing/tokenizing

In this case because SafeString implement almost all of String functionallity it is easy to replace EVIL Strings with GOOD SafeStrings

```
    #include "SafeString.h"
    createSafeString(dataString,60); // allocate global 60 byte safestring, just once,
//  for assembling the data to log
// You could also use createSafeString within the method if you want a local SafeString
    .. .. ..
    void setup() {
    Serial.begin(9600);
    // ....
    SafeString::setOutput(Serial); // enable sending debug/error msgs to Serial
    // So you will get a message if dataString runs out of space (but no reboots)
    // ....
    }

    // Data preparation for file saving:

    // Add time tag:
    dataString = Time0; dataString += ","; // or ',';

    // Append the MPU6050 data to the string:
    // no new strings created here!!!
    dataString += AcX; dataString += ",";
    dataString += AcY; dataString += ",";
    dataString += AcZ; dataString += ",";
    dataString += GyX; dataString += ",";
    dataString += GyY; dataString += ",";
    dataString += GyZ;

    // etc ....

    // SafeStrings are printable so can use println(dataString)
    // you can also print TO a SafeString so you could use, for example
    // dataString.print(AcX);
    // to access all the formatting print provides

```
> 3 votes

# Answer
For fixed strings (which do not change), use e.g. F("Text") ... this will place the string in flash instead of heap space. Note that the Uno has 32 KB of flash and 2 KB of SRAM (which is used for heap space among others).

If you need variable sized strings but one or few at a time, make a dedicated buffer (of e.g. 64 bytes) and use that buffer for all string operations. It will take up 64 bytes all time, but will leave no heap gaps. You can create it as a global variable (simple):

```
char string_buffer[64];

```

and use that string\_buffer for string operations.

Note that heap gaps are bad for all devices/operating systems, however since the Arduino has very little builtin SRAM, it is filledup quickly when using strings without thinking about memory management.
> 2 votes

# Answer
A chat system I used to use "back in the day" used a fixed "stack" based string buffer.

Basically a single `char *` buffer of a fixed size was created at the beginning of the program and initialised to 0.

Then strings were appended to that buffer using whatever functions were appropriate at that time. A pointer was kept pointing to the start of the "free" space in the buffer. This is the pointer which was used for placing new text into that buffer.

The entire buffer was then printed to the output stream in one block, the first byte cleared, and the pointer reset to the start of the buffer.

This made a very efficient and simple string buffer which didn't fragment memory in any way and still allowed the use of standard C string functions such as `sprintf()`, `strcpy()`, etc.

For example:

```
char strbuf[128] = { 0 };
char *strptr = strbuf;

strcpy_P(strptr, (PGM_P)F("Temp = "));
strptr += strlen(strptr);
itoa(temperature, strptr, 10);
strptr += strlen(strptr);

Serial.println(strbuf);
strbuf[0] = 0;
strptr = strbuf;

```
> 2 votes

# Answer
***Which is the most efficient and fastest solution to read and store the data from Accelerometer and GPS?***

You don't state how fast is fast enough nore how long you want to record the data for. Particularly for the Accelerometer data.

This suggested solution will log ~800 Accelerometer samples/sec (7 x 16bit ints) continually for 30 days.

There are two problems i) reading and parsing the GPS and reading the Accelerometer ii) storing the data on the SD card.

Reading/parsing the GPS data takes time. This tutorial, Arduino Serial I/O for the Real World covers buffering serial input, parsing GPS data and buffering serial (text/debug) output. Reading the accelerometer data is much faster, leave it in binary form.

Storing data on the SD card can be very slow. Bill Greiman's AnalogBinLogger example in an earlier version of his SdFat Arduino library, uses a pre-allocated and erased SD file and special block writes to minimize the SD latency. https://github.com/greiman/SdFat (code for the earlier version with AnalogBinLogger)

This project, High Frequency, Long Duration Datalogging, uses an Uno/Mega to store 512byte blocks of data to an SD card in less then 1mS each block, continually for 30days. It uses an interrupt to collect the ADC data and two 512byte buffers it for collecting the incoming data and writing to the SD card.

Applying these two projects to your situation you could

1. use on Mega2560 to read/buffer/filter/parse the GPS data and interleave it with the Accelerometer data and buffer it for binary transfer to the second Mega2650 via Serial (115200baud) i.e. ~11.5Kbytes/sec. For 7 x int16\_t accelerometer variables that would be about 800 samples/sec over the serial connection in binary format. The standard Mega2560 64byte TX Serial buffer should be sufficient.
2. In the second Mega265 you need to modify the UART interrupt handler for one of the UARTs to fill the current SD buffer instead of the normal receive buffer. When the buffer is full the interrupt swaps it for a second buffer as in the high speed logger project above.

The second Mega would also have a command and control Serial input to prepare the SD card and start/stop the storage.

**A single board apporach**

Since the SD write of the 512 block takes \<1mS you could also look a combining these two processes into on board.

Read/buffer/parse fill the 512 block. When it is full, block for 1ms while the SD writes that buffer. This approach will reduce accelerometer sampling frequency. See Simple Multitasking Arduino for how to interleave the tasks for reading/parsing the GPS with sampling the accelerometer and writing the SD card
> 1 votes

---
Tags: arduino-uno, sd-card, string, mpu6050
---


# Question
Title: Does an 5V 2.1 A will fit for this Led Schema?
Hello I would like to create an Arduino protoype with Led WS2182B. I currently have Arduino NANO (not UNO, like in this schema) 65 Led WS2182B = Which gives me 3.9 Amp of suply for full brighness (65\*60mAmp) Power supply of a movil charge wich have 5V 2.1 A

I am currently working with this schema from this website

I have a few questions

1. Does this battery will work for this schema replacing the usb conector?
2. Can I use the 68 leds at a medium energy, to make it suitable wih the power supply? Can this damage any device (Because in theory I believe it needs more than 2.1 Amps) 3)If this battery will not be appropiate to this schema. What could I do?

Thank you very much!

# Answer
> 0 votes
You are using a standard USB power bank. It should be possible to power your project as long as you stay below the current limit (2.1A). Probably you should keep the intensity small enough to not exceed 1.9A in normal operation. That should be enough for about half intensity. You really don't want to exceed the current limit. And you should measure the actual current draw and then approach your own current limit (like 1.9A) from below. Calculations are good, but when operating like this you should look at the real values.

If you exceed the current limit of the power bank it depends on the implementation of the power bank what will happen. Most likely the power bank will cut the power but still work. Though it is also possible, that you fry some electronics inside the power bank and kill it this way.

Note:

* While you experiment with your code you can use fewer LEDs, so that they would be able to light up at full intensity. That makes sure, that you don't damage anything from a small programming error. If you write your code in the correct way (for example defining the number of LEDs at exactly one code line and reusing that name everywhere), then it will be easy to increase the number of LEDs to the target and also be sure, that you are staying within your limits.
* You already have it in your wiring diagram, but nonetheless I want to emphasize, that you must not power the LEDs through the Arduino. You need to connect them directly to the USB cable to the power bank. The Arduino cannot withstand such currents.
* USB power banks often cut power, when not enough current is being drawn from them (and for mine the current of an Arduino Nano wasn't enough to hold it active). If in your project the LEDs get turned of at some time, while the Arduino should keep running, the power bank might cut the power, thus turning off the Arduino. In my experience the bigger, more expensive power banks will do that, while small, cheap ones will just keep outputting the power. If this scenario is relevant for you, you need to test this yourself with your specific power bank.

> If this battery will not be appropiate to this schema. What could I do?

You could use multiple of these power banks, each of them powering its own part of the LED strip. One of them can also power the Arduino. Just make sure to connect all grounds together.

---
Tags: arduino-nano, power, led
---


title: How to clear SoftwareSerial values?

text:
# Question
Title: How to clear SoftwareSerial values?
I'm using software serial on my weather station. The way it's supposed to work is that you send an SMS to the device and it replies with the wind speed, etc.

At the moment, The wind speed is detected, waiting for an incoming SMS. The SMS arrives and it sends a response but the response SMS is sent over and over infinitely. I'm guessing the problem is due to the:

```
 if (mySerial.available()>0){

```

As this is what I'm using to test whether the SMS has arrived and presumably, it's then always set to available.

Does anyone know how to basically reset the software serial after the message has been sent?

```
 #include <SoftwareSerial.h>
 #include <ADSWeather.h>

SoftwareSerial mySerial(9, 10);

#define ANEMOMETER_PIN 2
#define VANE_PIN 0
#define RAIN_PIN 3

#define CALC_INTERVAL 1000

unsigned long nextCalc;
unsigned long timer;

int windDir;
int windSpeed;
int rainAmmount;

ADSWeather ws1(RAIN_PIN, VANE_PIN, ANEMOMETER_PIN); //This should configure all pins correctly

void setup()
{
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(RAIN_PIN), ws1.countRain, FALLING); //ws1.countRain is the ISR for the rain gauge.
  attachInterrupt(digitalPinToInterrupt(ANEMOMETER_PIN), ws1.countAnemometer, FALLING); //ws1.countAnemometer is the ISR for the anemometer.
  nextCalc = millis() + CALC_INTERVAL;

  mySerial.begin(9600);   // Setting the baud rate of GSM Module
  delay(100);
}

void loop()
{
  timer = millis();

  int rainAmmount;
  long windSpeed;
  long windDirection;
  int windGust;
  int sent;

  ws1.update(); //Call this every cycle in your main loop to update all the sensor values

  if(timer > nextCalc)
  {

    nextCalc = timer + CALC_INTERVAL;
    rainAmmount = ws1.getRain();
    windSpeed = ws1.getWindSpeed();
    windDirection = ws1.getWindDirection();
    windGust = ws1.getWindGust();

//     windSpeed / 10 will give the interger component of the wind speed
//     windSpeed % 10 will give the fractional component of the wind speed
    Serial.print("Wind speed: ");
    Serial.print(windSpeed / 10);
    Serial.print('.');
    Serial.print(windSpeed % 10);
    Serial.print(" ");

    Serial.print("Gusting at: ");
    Serial.print(windGust / 10);
    Serial.print('.');
    Serial.print(windGust % 10);
    Serial.println("");

  }

  if (Serial.available()>0)
  {
      RecieveMessage();
  }

  //If an message comes in
 if (mySerial.available()>0){
  // Serial.write(mySerial.read());
  Serial.write("Message received");

  //Send the wind speed response.
  SendMessage();

  //At this point the SendMessage() repeats and the message is sent over and over.
}
}

 void SendMessage()
{
  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"NUMRemoved\"\r"); // Replace x with mobile number
  delay(1000);
  mySerial.println("I am SMS from GSM Module");// The SMS text you want to send
  delay(100);
   mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);
}

 void RecieveMessage()
{
  mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
  delay(1000);
 }

 void serialFlush(){
  while(mySerial.available() > 0) {
    char t = mySerial.read();
  }
}

```

# Answer
> 2 votes
For the hardware serial port, the buffer is 64 and I was reading at least 100 times. Every read will clear one byte of data from the serial buffer at a time.

For the software serial port, you do a dummy read and then check whether the buffer is empty or not using

```
    while(mySerial.available()>0)  {
       dummy = mySerial.read();
    }

```

So, in summary, you have to read the buffer until it is empty.

**Useful notes:**

1. You should be knowing when to expect actual data and when not to
2. have a way to identify the valid messages (some fixed header bytes)
3. have a way to validate the contents (checksum)

Leave a comment if you have any questions

# Answer
> 0 votes
```
 if (mySerial.available()>0){

```

You are checking if any serial data has arrived. Then you **never** read it. So naturally it is always available. You have a serialFlush function which does read it, however that function is never called.

You need, however, to read more than one byte. Otherwise you will send an SMS for every byte in the input message.

# Answer
> 0 votes
```
if (mySerial.available() > 0) {
  // Serial.write(mySerial.read());
  Serial.write("Message received");

  //Send the wind speed response.
  SendMessage();

  mySerial.begin(9600);   // Reset myserial buffer

  //At this point the SendMessage() repeats and the message is sent over and over.
}

```

---
Tags: arduino-uno, softwareserial, sim808
---


# Question
Title: Mildly accurate oscilloscope using Arduino Uno R3
I'm trying to make a mildly accurate oscilloscope using Arduino Uno R3 and I've done some research on the best method to do so. First of all I need to measure the voltage with a rather high sampling rate and then I'm going to transfer my data through the serial port and plot the data using Python or Matlab.

According to what I have read the `analogread()` function will cause some delay and therefore some inaccuracies and thus it is not suitable for my purpose.

I found on **this** website some good info about how I should write my code, but I have some questions:

1. I want my reference voltage to be 1.1 V so that by dividing it to 1023 parts I will have an accuracy of about 1 mV. How should I edit the mentioned code in order to do so?
2. The code in the `void loop()` setup is of no use to me (I prefer not to save the measured data on the Arduino and then send to my PC because of memory limitations). After deleting it will the data still be sent to the serial port?
3. Will sending the data through the serial port affect my sample rate/accuracy? I mean how does it effect my accuracy?

P.S: by mildly accurate this is what I mean: I want to measure voltage accurately with 1 mV precision for frequencies of max. 500 kHz (a bit less or more won't hurt).

# Answer
> I want my reference voltatge to be 1.1v so that by dividing it to 1023 parts I will have the accuracy of about 1mv.

You will have a *resolution* of about 1 mV. The accuracy will be significantly worse than that due to the imperfections of the ADC (offset error, gain error, non-linearity) and noise.

> how should I edit the mentioned code in order to do so?

The reference is configured by the bits `REFS0` and `REFS1` of the `ADMUX` register. The internal 1.1 V reference is selected by setting both bits, as shown in table 24-3 of the datasheet. You can then patch the original code like this:

```
@@ -8,7 +8,7 @@
   ADCSRA = 0;             // clear ADCSRA register
   ADCSRB = 0;             // clear ADCSRB register
   ADMUX |= (0 & 0x07);    // set A0 analog input pin
-  ADMUX |= (1 << REFS0);  // set reference voltage
+  ADMUX |= (1 << REFS0) | (1 << REFS1);  // set reference voltage
   ADMUX |= (1 << ADLAR);  // left align ADC value to 8 bits from ADCH register

   // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]

```

> the code in the `void loop()` setup is of no use for me (I prefer not to save the measured data on the arduino and then send to my pc because of memory limitations). after deleting it will the data still be sent to the serial port?

In the linked code, `loop()` is the only function sending anything to the serial port. If you remove it, nothing will be sent. You could `Serial.write()` in the ISR though, in which case an empty `loop()` would be fine.

Note that writing to `Serial` from within an ISR is generally discouraged. Your situation though (an oscilloscope code) is one of the very few cases where it does make sense to do so.

> will sending the data through the serial port affect my sample rate/accuracy?

It can certainly affect your sampling rate. `Serial.write()` is usually non-blocking, as all it does is write the data to the RAM-based transmit buffer. If the buffer fills up, however, `Serial.write()` will block waiting for the serial port to actually send the data, and make enough room in the buffer.

This means that, in order for the oscilloscope to not miss samples, you have to make sure that the serial port can send the data at least as fast as the ADC is acquiring it.

**Example calculation**: If you clock the ADC at 1 MHz, you get one sample every 13 µs. You can follow the example given in the code you linked to, and discard the last two bits in order to transmit only 8 bits of the sample. Transmitting those in plain binary will take 10 “bits” worth of the serial port bandwidth (one start bit, 8 data bits and one stop bit). Each bit should then take less than 1.3 µs, which translates to a baud rate of 769,231 bits per second. You will probably have no other choice than configuring the serial port for 1 Mb/s.

If you want to transmit the whole 10 bits of the ADC readings, you will have to lower the sampling rate by a factor two.

At this point you may notice that the serial port, rather than the ADC, is the bottleneck for the performance of your oscilloscope. If this is too limiting, you may consider building a scope that works by bursts: it stores a burst of samples in memory, then sends it at a leisurely rate through the serial port.
> 2 votes

---
Tags: arduino-uno, serial, adc, isr, digital-analog-conversion
---


# Question
Title: Can I make an Arduino Uno Rev3 pretend to be a joystick?
I want to create a joystick for my flight simulator and I need to make an Arduino Uno Rev3 pretend to be a joystick when I plug it to my computer.

# Answer
The Uno doesn't have native USB capabilities. It uses an additional microcontroller (the Atmega16u2) as an USB to Serial adapter. In the default configuration this microcontroller is only programmed for providing a serial interface over USB, not a joystick interface. You can hack your Uno and reprogram the Atmega16u2 for providing a joystick interface (and there are tutorials for how to reprogram the Atmega16u2 online). (Note, that you need a genuine Arduino for this to work, since the cheap clones often only have CH430 chips as USB to Serial adapter)

But I would suggest going the easier way and buying an Arduino board, which itself has USB capabilities without the need of hacking the board, like the Arduino Micro. Then you can simply use one of the joystick libraries on it. This way will be a lot easier for a beginner than doing it with an Uno.
> 2 votes

---
Tags: arduino-uno, usb, joystick, simulator
---


title: No text in the IDE menu items

text:
# Question
Title: No text in the IDE menu items
I installed arduino 1.8.19 (64-bit) on a Fedora Linux 35 Workstation Edition system. When I started the IDE, and selected the "Open" menu icon, the menu item list appeared, but there was no text displayed with the items. I could open sub-menu items, but there was still no text. It looked like:

I tried several other 1.8.x versions, but with the same result. I haven't found any discussion about this on the Web. so I suspect that it is problem with my configuration. Nevertheless, any suggestions will be most welcome. I have not tried to install the IDE on Windows 10, but that is an option.

# Answer
There is a incompatibility between Arduino 1.8.19 and Fedora 35. On another PC, where I was running an older version of Arduino, I upgraded to Fedora 36 and the upgrade warned me of the incompatibility with the older Arduino and Fedora 36 and said it was deleting Arduino. After the Fedora upgrade completed, I installed Arduino 1.8.19 and it worked as expected. When I upgraded the original PC, the one with the no text in the menus, to Fedora 36, the menus also worked as expected. Hallelujah!! So, all is well and I have my answer. Thanks for your replies.
> 2 votes

---
Tags: arduino-ide
---


# Question
Title: Arduino I2C maximum number of writes per transmisson
Is there any limit on the number of `Wire.write()` commands consecutively in between the `Wire.beginTransmission()` command and the `Wire.endTransmission()` command for the Arduino Wire library?

# Answer
There are **five** buffers used by the TWI and Wire library. They are defined as 32 bytes.

In wire.h:

```
#define BUFFER_LENGTH 32

```

In Wire.cpp:

```
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
...
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];

```

In twi.h:

```
  #define TWI_BUFFER_LENGTH 32

```

In twi.c:

```
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
...
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
...
static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];

```

So immediately you are using 5 x 32 bytes (160 bytes).

---

You could increase that to (say) 64 bytes, bearing in mind your 160 byte overhead is now 320 bytes, and you don't have a lot of RAM.

The comments about `endTransmission()` are correct. After a `Wire.beginTransmission()` nothing is actually transmitted until the `endTransmission()` call. This lets you fill up the buffer at your leisure, and then let the library do the writes in a fairly timing-specific way.

---

### Reference
> 6 votes

# Answer
A quick look at the source code implies that there is a fixed length buffer of 32 bytes:

From the header file `wire.h`:

```
#define BUFFER_LENGTH 32

```

And from the implementation of the `write` function:

```
size_t TwoWire::write(uint8_t data)
{
  if(transmitting){
  // in master transmitter mode
    // don't bother if buffer is full
    if(txBufferLength >= BUFFER_LENGTH){
      setWriteError();
      return 0;
    }
    // put byte in tx buffer
    txBuffer[txBufferIndex] = data;
    ++txBufferIndex;
    // update amount in buffer
    txBufferLength = txBufferIndex;
  }else{
  // in slave send mode
    // reply to master
    twi_transmit(&data, 1);
  }
  return 1;
}

```
> 1 votes

# Answer
The buffer size can be increased.

Should go to the twi.h fil, Wire.h file and set the desired length of the variable: BUFFER\_LENGTH
> -1 votes

---
Tags: i2c
---


# Question
Title: Change the fuses of an Arduino Uno (can an Arduino Uno change its own fuses?)
For now, I'm using an Arduino Uno alone including its 328p (no other external chip to program).

I would like to **change its fuses to internal 8 Mhz clock** (because then I'll move the 328p out of the Arduino Uno), and for simplicity I'd like to do it from Arduino IDE.

Here is what I tried:

* I created a new entry in boards.txt copy-pasted from Uno, fuses modified, like this:

```
atmega328p.name=Atmega328p
atmega328p.upload.tool=avrdude
atmega328p.upload.protocol=arduino
atmega328p.upload.maximum_size=32256
atmega328p.upload.maximum_data_size=2048
atmega328p.upload.speed=115200

atmega328p.bootloader.tool=avrdude
atmega328p.bootloader.low_fuses=0x62
atmega328p.bootloader.high_fuses=0xD9
atmega328p.bootloader.extended_fuses=0xFF
atmega328p.bootloader.unlock_bits=0x3F
atmega328p.bootloader.lock_bits=0x0F
atmega328p.bootloader.file=optiboot/optiboot_atmega328.hex

atmega328p.build.mcu=atmega328p
atmega328p.build.f_cpu=8000000L
atmega328p.build.board=AVR_UNO
atmega328p.build.core=arduino
atmega328p.build.variant=standard

```
* I selected this board in *Tools \> Board: Atmega328p*
* I tried to *Upload* any sketch (and not *Upload with programmer* since I have no other chip connected to the Arduino Uno), hoping it would modify the fuses during the (successful) *Upload* process.

**I think it didn't work (when I move the 328p outside of the Uno it doesn't work).**

**How can I change the fuses for an Arduino Uno directly from Arduino IDE, to enable internal 8 Mhz clock?**

---

PS: "Tools \> Burn Bootloader" does not succeed, but I think this is normal, since there is just the Arduino Uno, and no other chip / nothing to use as a "Programmer":

> avrdude: stk500\_recv(): programmer is not responding
> avrdude: stk500\_getsync() attempt 1 of 10: not in sync: resp=0x03

# Answer
You need a programmer to burn fuses. If you have another arduino then you can use the Arduino as ISP example sketch in the IDE. You can't burn fuses just using the USB cable like you upload code with. The only reason that can talk to the chip at all is because there is another chip to convert it to serial and a bootloader on the 328P to allow it to upload code via serial.
> 2 votes

# Answer
As mentioned in the other answer, it seems that it's not possible for an Arduino Uno to change *its own fuses*.

So here is how I did:

* I used a Nano (loaded with "Arduino as ISP") as programmer for the Uno with this classical wiring (except that in my case, the left board, the programmer, is a Nano):

* I added this to `boards.txt` (source here):

```
##############################################################
atmega328bb.name=ATmega328 on a breadboard (8 MHz internal clock)
atmega328bb.upload.protocol=arduino
atmega328bb.upload.maximum_size=30720
atmega328bb.upload.maximum_data_size=2048
atmega328bb.upload.speed=57600
atmega328bb.upload.tool=avrdude
atmega328bb.bootloader.tool=arduino:avrdude
atmega328bb.bootloader.low_fuses=0xE2
atmega328bb.bootloader.high_fuses=0xDA
atmega328bb.bootloader.extended_fuses=0x05
atmega328bb.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
atmega328bb.bootloader.unlock_bits=0x3F
atmega328bb.bootloader.lock_bits=0x0F
atmega328bb.build.mcu=atmega328p
atmega328bb.build.f_cpu=8000000L
atmega328bb.build.core=arduino
atmega328bb.build.variant=standard
atmega328bb.build.board=AVR_BARE

```
* I used *"Programmer: Arduino as ISP"*, then *"Burn bootloader"* then *"Upload with programmer"* with any sketch.
* Then the fuses are programmed to Internal 8 Mhz, and we can take the ATmega328p out of the Uno and move it on a breadboard! Working now :)
> 1 votes

# Answer
This is technically possible, but tricky.

First you'd have to wire up the Arduino with some jumpers in such a way that the 328P can use its ICSP header to reprogram the 16U2/8U2 via that chips own header. With the right custom firmware in place you could then re-wire the board so that the 16U2 changes the fuses of the 328P upon boot and reuploads the firmware before switching into its usual function. Then it's just a matter of having the 328P reprogram the 16U2 with the original DFU firmware, and presto! An Arduino that changed its own fuses!

If you just need to change the fuses without a ICSP programmer then that can be done by just programming the 16U2 chip directly through its USB port (although technically that doesn't qualify as the Uno "programming itself").
> 0 votes

---
Tags: arduino-uno, atmega328, avr, oscillator-clock, fuses
---


title: Using an I2C barometer

text:
# Question
Title: Using an I2C barometer
When buying a barometer for my current project at work, I chose the MikroElektronika click 3 barometer. However, as it turns out, the library for it doesn't exist for Arduino. I know it uses I2C communication, so I tried connecting the board to my Arduino UNO R3 as follows:

simulate this circuit – Schematic created using CircuitLab

However, I do not know how to use the output of the sensor. Is there a way to access the raw data measured by the sensor and post-process it myself, or is a library needed?

Thanks for your help

# Answer
I have found MikroElektronika library for the barometer 3. You can get basic idea how to communicate with the sensor. MikroElektronika c libraray

You can develop your own library based on that one for Arduino or you can read the data sheet of the sensor for more details.
> 1 votes

---
Tags: sensors, i2c
---


# Question
Title: Suggested pullup resistor values for 1-wire network
I'm attempting to connect 6 DS18B20 temperature sensors to an Arduino GPIO pin in a topology that looks something like this:

Conceptually, it's a star network with two star subnets.

The GPIO pin on the Arduino is connected to point "E" through a 4-inch wire, a JST connector, and another 4-inch wire.

The 3 wires (shown in green) connecting sensors "A", "B", and "C" to point "D" are approximately 3 feet long (and are, in fact, the original ~1-meter wires that came pre-attached to the sensors when I bought them). Segment ED is ~4 feet long.

The 3 wires (shown in blue) connecting sensors "G", "H", and "I" to point "F" are approximately 20-30 feet long (including the original 3-foot wires attached to the sensors when I bought them). Segment EF is ~8 feet long.

No parasitic power is involved. Every DS18b20 has 3 wires... +5v (probably closer to 4.5v by the time it gets to G/H/I), ground, and 1-wire data.

#### So... where would YOU recommend putting resistors (feel free to describe points besides the ones I labeled with letters), and what values would you use?

And... would it actually be any *better* to take advantage of the fourth (presently unused) wire in the cables I have connecting G, H, and I to F as a 'return wire' to turn it into a much longer daisy chain (E to F, F to G, G back to F, F to H, H back to F, F to I), or something even more radical (say, ED, DA, AD, DB, BD, DC, CD, DE, then continuing the daisy chain with EF as described previously)?

For what it's worth, I presently have a single 4.7k pullup resistor sitting at point "E", and it seems to work... but after reading Maxim's AppNote about "Building reliable long 1-wire networks" (Appnote 148), I'm feeling like it *shouldn't* work, and that I really *ought* to do something more sophisticated for the sake of long-term reliability.

# Answer
I have a linear network with three thermos at roughly 5', 20', and 40-50' from the micro (a 5v '328p), as well as being parasitically powered. The physical bus is a twisted pair from a Cat-5 cable. The pullup is 4.7KOhm on the processor board.

I've tested this network using a 3.3v '328p and it wasn't as reliable, but reducing the pullup to 2.2K (IIRC) fixed it.

I find Maxim's App Note 148, "Guidelines for Reliable 1-Wire Networks" to be very helpful and is my go-to for 1-wire network questions.
> 1 votes

---
Tags: 1-wire
---


# Question
Title: How to display only specific data in the serial monitoring?
I got the following data as shown in the figure from imu razor which is connected to Arduino Mega 2560 in the serial monitoring and I want to get only the data that starts with "#A-R= "

Can any one provide me with code to do this?

This is my code:

```
#define BUFF_SIZE 40
char buffer[BUFF_SIZE];
String header ;
char Bufferheader[4] ;

void setup(){
Serial.begin(57600);
Serial2.begin(57600);
Serial2.write("#osct");
}

void loop() {

int i = 0;
while(Serial2.available()) {
buffer[i++] = Serial2.read();
if(i == BUFF_SIZE) break;
}

for(int j = 0; j < i; j++) {
Serial.print(buffer[j]);

}
}

```

# Answer
The method outlined by Majenko is the general way of dealing with this kind of requirement, and also probably the “cleanest” way. If, however, you are confident that the incoming data always follows the pattern you are showing, then you can “cheat” and cut some corners.

Consider this: in the sample you show, the character `'A'` only ever appears as the second character in a line, and always as part of the sequence `"#A-R="`. If you are confident that this is always the case, then you can apply the following algorithm:

* the program processes one input character at a time, and decides whether to print it to its output or not
* it has two possible states: either it is printing every character it reads (because it believes the character belongs to a “#A-R” line), or it is not
* if it is printing and it reads an end of line, it prints that end of line, and then stops printing
* if it is not printing and it reads an `'A'`, it outputs `"#A"`, then starts printing all its input.

In code:

```
void loop() {
    static bool printing = false;  // are we printing what we read?
    if (Serial2.available()) {
        char c = Serial2.read();
        if (printing) {
            Serial.write(c);
            if (c == '\n')  // on end of line, stop printing
                printing = false;
        } else if (c == 'A') {  // on 'A', start printing
            Serial.print("#A");
            printing = true;
        }
    }
}

```

This code assumes your device uses ASCII LF (`'\n'`) as end-of-line indicator. You will have to replace `'\n'` by `'\r'` if it uses ASCII CR instead.
> 2 votes

# Answer
Your code is doing literally nothing except reading from one serial port and passing it to another.

You need to throw away pretty much all that code and do some actual processing of the data.

You need to:

1. Read the incoming data a line at a time (that is, read everything up to the line ending into a buffer)
2. Examine the start of that buffer
3. Output whatever data from the buffer your examinations deem appropriate.

I can't go into detail here about how to do it, but there are tutorials covering all those topics available on the web. For the serial reading I have a tutorial that you may find helpful.
> 1 votes

---
Tags: serial, arduino-mega
---


# Question
Title: Uploading sketch to multiple Arduinos connected in series
I'm currently working on a project where you essentially will have multiple Arduinos (1 Uno, multiple Nanos) daisy-chained, only connected through 2 digital pins and one wire for Serial communication (RX Pin -\> TX Pin). (The first one is connected via USB to the PC.)

I figured the serial communication between the first Arduino and PC would also be forwarded through the RX and TX pins, but that doesn't seem to be the case.

As it's fairly tedious to update one at a time, is there a way of updating all of them at once, using only the one-way serial communication wire?

EDIT: Yeh so like imma just add a USB Port to every single component to the chain to update separately, and update every single one of them separately.

# Answer
> 5 votes
Try connecting only the RX and reset pins. Serial programming is done by the bootloader, but it needs to be switched into programming mode first, which is done by resetting the chip and then sending a special code to the RX pin within a certain time period. When you program through the serial port (as you are doing with the Uno) the FTDI chip drives this pin for you, but you'll need to cascade that reset signal through to the other chips as well. This still isn't guarenteed to work 100%, because it depends on a number of other factors as well, but at least you'll have a chance.

When I've done stuff like this commercially I've programmed via the ICSP connector instead and made programming rigs out of spring-loaded pin connectors that the target boards simply clip onto. If you're planning on doing this with any degree of frequency then I'd recommend investing a bit of time into doing this yourself.

UPDATE: ok, I can see now why this isn't working. The Nano's CH340 usb-to-serial chip is pulling RX low, preventing the data stream from being read. Would work fine with standalone chips, obviously doesn't on the Nano.

I think your best option is to use ICSP. It's an extra pin, but if you breadboard then it shouldn't make any difference. Plus there are a number of advantages to doing so, including faster programming, the ability to upload/replace the bootloader and the ability to change fuses (e.g. to protect your firmware or disable the bootloader altogether to give you app more Flash space etc).

If you don't already know how to do this then the layout is:

* Connect Uno SCLK(D13)/MOSI(D11)/GND pins to all the corresponding Nano pins.
* Connect Uno D10 to all the Nano's RESET pins.
* Connect Uno MISO(D12) to only the first Nano's MISO pin.
* Connect Uno VIN to all the Nano VINs (you don't want all the Nanos being driven from the Uno's regulator)

Should wind up looking something like this:

Prepare the Uno for programming:

* Set your IDE board type to Uno
* Set IDE programmer type to "AVR ISP"
* Upload IDE ArduinoISP sketch to the Uno

And now you're ready to program the Nanos:

* Set your IDE board type to Nano
* Set IDE programmer type to "Arduino as ISP"
* Upload your Nano sketch using "Upload Using Programmer"

Just tried it now with the two Nanos in the photo, worked fine.

# Answer
> 0 votes
There is a two-way protocol used by the bootloader which I describe here.

You could conceivably connect all the Rx wires together, and use the Tx wire from the first one (so it responds appropriately), and discard the responses from the other units. If they program at exactly the same rate, and reset at exactly the same moment, that might work.

You might be better off just uploading using a device designed to do that, as I describe on my forum. The Atmega328P programmed using that method can be reprogrammed in about one second (so the time to hook up the wires is the long part). Using the ICSP interface on the chips, and a suitable plug, could make that very quick, and easy.

There are also stand-alone devices, for example the Crossroads standalone programmer which uses the techniques described in my forum post. You can use that in the field because it doesn't require a monitor or PC. You just hook it up via the ICSP port, select what file you want to upload, and hit the "program" button.

---
Tags: serial, uploading
---


# Question
Title: `noInterrupts()` causes the arduino to no longer appear in ports
Minimal working example:

```
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  noInterrupts();
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

```

When uploaded to my Arduino Nano 3.3v BLE from my M1 Mac, this causes the Nano to no longer appear in the ports menu. In order to get it to appear again, I have to double press the reset button on the Nano so that it resets to a default script. After doing this, the Nano is available in the ports menu again.

I also cannot see the Nano via `cat /dev/cu.<TAB>` when this script is uploaded to it.

Does anyone know why this happens? Or alternatively (if this is intended behaviour) why it is not documented in `interrupts()` or `noInterrupts`?

I've looked through some other posts, but I don't think they're duplicates of this one:

#### Edits in response to answers

So the MWE wasn't quite descriptive enough of my problem and some of the answers got caught up on that (which is my fault). I've included a more detailed description of what I'm doing below to describe what I'm actually doing, but I've also accepted the answer which I think answers the heart of the question "why do interrupts cause the Nano to not appear in port?".

What I'm actually doing is I've got two Arduino Nanos (call them primary and secondary) connected via I2C and `Wire.h`. Each Arduino nano is reading 15 analog inputs (via a multiplexer). The secondary Nano is then sending its 15 analog readings to the primary over I2C. But I'm getting a lot of noise in the analog readings of the primary Nano, but no noise in the secondary. This noise disappears when I disconnect I2C. So my theory was that digital SCL and SDA wires were causing noise in the analog sensor wires, but I observed the noise would only occur for ~2ms every ~10ms. I thought I'd disable interrupts (and therefor disable `Wire.h` from pulsing SCL/SDA) while I was reading the primary's analog sensors, and enable interrupts afterwards. This caused the Nano to not appear in the Ports tab, and the rest is the result of this post.

I now think I didn't include the 4.7Ohm pull-up resistor on SDA and SCL which seems to only be included on the official Arduino examples, and never on any random internet examples.

# Answer
I'm not really an expert on the Nano 3.3v BLE, however it appears that it is directly connected to the USB port and thus disabling interrupts will also disable its ability to respond to USB handshakes, thus it will appear to the host that it has been unplugged.

The original Nano had a separate chip (FT232RL) which handled the USB interface, and thus disabling interrupts on that Arduino would not drop the USB connection.

> Or alternatively (if this is intended behaviour) why it is not documented in interrupts() or noInterrupts?

Probably the documentation has not kept up-to-date with later product releases. It is not uncommon for documentation to lag behind what the released products actually do.

As timemage points out in another answer, your attempts to blink LEDs with interrupts turned off will not succeed. In fact, turning interrupts off should only be done for milliseconds, not permanently. I assume that is a demonstration sketch, but still ... if you turn interrupts off only briefly the problem should go away.
> 2 votes

---
Tags: interrupt
---


# Question
Title: How do I build and upload a C++ program without the Arduino Library or IDE?
*Note: This is a reference question (but feel free to write answers of your own!)*

---

I want to use the AVR tools directly -- no arduino-builder or arduino-cli. I would also like compilation and uploading to be as fast as reasonably possible

# Answer
> 2 votes
1. Create a new file called `Makefile` in your project directory. Populate it with the following contents:

```
TEMPDIR := $(shell mktemp -d)

all:
    avr-g++ -DF_CPU=<CLK> -mmcu=<PARTNO> -fno-threadsafe-statics -O3 -flto -std=c++23 -isystem/usr/avr/include -lm -fuse-linker-plugin -Wl,--gc-sections *.cpp -o ${TEMPDIR}/a.elf

    avr-objcopy -O ihex -R .eeprom ${TEMPDIR}/a.elf ${TEMPDIR}/a.hex
    avrdude -V -p<PARTNO> -carduino -P/dev/tty<SERIAL_PORT> -b<BAUD> -D -Uflash:w:${TEMPDIR}/a.hex

    rm ${TEMPDIR}/a.elf ${TEMPDIR}/a.hex
    rm -d ${TEMPDIR}

```
2. In the Arduino IDE, press `Ctrl`+`,` and enable verbose output during compilation and uploading.
3. Start uploading with `Ctrl`+`U`. Replace the groups of angled brackets in Makefile (e.g. `<CLK>`) with the values in the Arduino IDE's build output.
4. Run `make`.

`-lm` links in the AVR math library. `*.cpp` refers to your c++ source files. `-V` prevents avrdude from reading back the flash contents and verifying it, which saves time, but you may want to disable it while diagnosing problems.

---
Tags: avr, avrdude, avr-gcc, avr-toolchain
---


title: How do I escape a boot loop?

text:
# Question
Title: How do I escape a boot loop?
*Note: This is a reference question (but feel free to write answers of your own!)*

---

I uploaded code that contains a bug that causes my Arduino to immediately reset itself when starting using this code from the AVR libc FAQ. The built-in LED keeps flashing. Because it's in this state of constantly resetting, I'm unable to upload my sketch to it.

I tried holding the reset button while uploading and burning a new bootloader, but neither of those worked.

How do I get my Arduino out of this boot loop so I can upload sketches again?

# Answer
> 4 votes
1. Start holding the reset button. This is to prevent the Arduino from entering the boot loop.
2. Unplug the Arduino and plug it back in.
3. Open a new sketch. Remove all of the code and replace it with `int main(){}`. This is to create a small program that will upload quickly.
4. Start uploading the sketch. Avrdude will attempt to upload the sketch ten times -- each time it tries, the RX LED on the Arduino will flash briefly.
5. Notice how often the LED flashes (0.2 Hz for me). Right before it flashes again, release the reset button. There's a small window of oppurtunity for avrdude to upload the sketch before the arduino starts up. If the TX and RX LEDs flash, success!

---
Tags: bootloader, reset, watchdog
---


# Question
Title: MKR1010 disconnects and reconnects normally until it reaches a point where it never reconnects again
The board does reconnect from time to time, but there are times where it just disconnects and never reconnects again and I can't replicate the error because while I run it with Serial open and turn ON and OFF my WiFis it always reconnects as it should.

```
#include <ArduinoHttpClient.h>
#include <WiFiNINA.h>
#include <EmonLib.h>

EnergyMonitor emon1;
EnergyMonitor emon2;
EnergyMonitor emon3;
int INTERVAL = 60;
int last_code = 0;

char ssid[] = "MySSID";
char pass[] = "MyPW";

String ID = "Garden_Pump_Sensor";

int sequence = 0;
double kWh = 0.0;

char serverAddress[] = "192.168.1.108";  // server address
int port = 5005;

WiFiClient wifi;
HttpClient client = HttpClient(wifi, serverAddress, port);

int status = WL_IDLE_STATUS;

void setup() {
  Serial.begin(9600);
  analogReadResolution(9);
  emon1.current(0, 100);
  emon2.current(5, 100);
  emon3.current(6, 100);
  Connecting();
}

void Connecting() {
  int tries = 4;
  while ( (WiFi.status() != WL_CONNECTED && tries > 0) || last_code != 200) {
    Serial.print("Status #1: ");
    Serial.println(WiFi.status());
    WiFi.begin(ssid, pass);
    Serial.print("Status #2: ");
    Serial.println(WiFi.status());
    tries--;
    last_code = 200;
  }

  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

void reconnecting() {
  if (WiFi.status() != 3  || (WiFi.RSSI() <= -90) || (WiFi.RSSI() == 0) || last_code != 200) {
    WiFi.end();
    Connecting();
  }
}

void loop() {
  unsigned long delayTime = INTERVAL * 1000;
  unsigned long time_start = millis();

  DataMonitorAndSend();

  unsigned long time_final = millis() - time_start;
  unsigned long delay_value = delayTime - time_final;
  Serial.println(delay_value);
  if (delay_value < 1  || delay_value > delayTime) {
    return;
  } else {
    delay(delay_value);
  }

}

void DataMonitorAndSend() {
  reconnecting();

  Serial.println("making POST request");
  String contentType = "application/json";
  kWh = kWh + getKWH();
  String postData = "{\"ID\": \""+ID+"\",\"seq\": " + String(sequence) + ",\"kWh\": " + String(kWh, 6) + "}";
  Serial.print("data: ");
  Serial.println(postData);

  client.setHttpResponseTimeout(5 * 1000);
  client.post("/receivedata/", contentType, postData);

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

  Serial.print("Status code: ");
  Serial.println(statusCode);
  if (statusCode == 200) {
    kWh = 0;
    sequence++;
  }
  last_code = statusCode;
  Serial.print("Response: ");
  Serial.println(response);

}

double getKWH() {
  int LOOPS = 15;
  double kWh_Total = 0.0;
  unsigned long delayTime_kwh = 2 * 1000;
  for (int i = 0; i < LOOPS; i++) {
    unsigned long time_start_kwh = millis();

    double Irms1 = emon1.calcIrms(600);
    if (Irms1 < 0.3) Irms1 = 0;
    double Watt1 = (Irms1 * 230) / 1000;

    double Irms2 = emon2.calcIrms(600);
    if (Irms2 < 0.3) Irms2 = 0;
    double Watt2 = (Irms2 * 230) / 1000;

    double Irms3 = emon3.calcIrms(600);
    if (Irms3 < 0.3) Irms3 = 0;
    double Watt3 = (Irms3 * 230) / 1000;

    kWh_Total = kWh_Total + ((Watt1 + Watt2 + Watt3) / 60);

    unsigned long time_final_kwh = millis() - time_start_kwh;
    unsigned long delay_value_kwh = delayTime_kwh - time_final_kwh;
    if (delay_value_kwh < 0  || delay_value_kwh > delayTime_kwh) {
      delay(0);
    } else {
      delay(delay_value_kwh);
    }

  }

  return kWh_Total / LOOPS;
}

```

Feel free to ignore the `getkWH()`, it's code related to power consumption. Also the firmware is up to date and the server is using a static IP.

# Answer
Since you only send a data every 60s, it is better to only establish a WiFi when you need it, AND only create an instance of HttpClient after that. That's means that it only creating the `wifi` and `client` instances when you need it instead of using a global instances. Here is a way I usually do for such an application that I modified based on your sketch, you could give it a try. Please noted that only the changes that I made are highlighted in my code snippet, please fill-in the rest of your code:

```
unsigned long INTERVAL = 60000;  // in milliseconds
unsigned long time_start = millis() + INTERVAL;    // noted that I changed this to a global variable and to unsigned long

// WiFiClient wifi;
// HttpClient client = HttpClient(wifi, serverAddress, port);

void Connecting() {
  WiFi.disconnect();
  WiFi.begin(ssid, pass);
  Serial.print("Connecting to ");
  Serial.print(ssid);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" Connected");

  // your code for printing localIP
}

void loop() {

  if (WiFi.status() != WL_CONNECTED)
    connecting();

  // send data when INTERVAL is reached
  if (millis() - time_start > INTERVAL) {
    DataMonitorAndSend();
    time_start = millis();
  }

  yield();

}

void DataMonitorAndSend() {
  // reconnecting();

  WiFiClient wifi;
  HttpClient client = HttpClient(wifi, serverAddress, port);

  // rest of your DataMinitorAndSend() code

  client.end();

}

```
> 1 votes

# Answer
I found that before using WiFi.begin() to re-connect, one needs to use WiFi.disconnect() first. At least that keeps my set-up reliably re-connecting, when its battery is empty or my router is out for a moment. Also, testing for WL\_CONNECTED or 3 only means that one's set-up is connected to the router, but the router not necessarily yet to the internet; in case of a restart of the router after a power outage. On one of my routers, one has to wait 10 seconds, on another 18 seconds.

```
void connectToWLAN()
{
  // Check if the AirLift FeatherWing's WLAN module works
  if (WiFi.status() == WL_NO_MODULE)
  {
    Serial.println("Connection to AirLift FeatherWing WLAN module failed");

    // If not, indicate there is a WLAN module malfunction
    WiFi.setLEDs(0, 255, 0); // Red

    // And stop forever
    while (true);
  }

  // Return to loop() if already connected to the WLAN router
  if (WiFi.status() == WL_CONNECTED)
  {
    return;
  }

  Serial.println("Trying to connect to WLAN router");

  // Indicate there is no WLAN router connection just yet
  WiFi.setLEDs(192, 255, 0); // Yellow

  do
  {
    // Start connection to WLAN router and print a status value
    WiFi.disconnect();
    delay(1000);

    status = WiFi.begin(WLAN_SSID, WLAN_PASS);
    // WL_IDLE_STATUS     = 0
    // WL_NO_SSID_AVAIL   = 1
    // WL_SCAN_COMPLETED  = 2
    // WL_CONNECTED       = 3
    // WL_CONNECT_FAILED  = 4
    // WL_CONNECTION_LOST = 5
    // WL_DISCONNECTED    = 6
    Serial.println(WiFi.status());
    delay(10000);
  }
  while (status != WL_CONNECTED);

  Serial.println("Connection to WLAN router successful");

  // Indicate that the WLAN router connection was established
  WiFi.setLEDs(255, 0, 0); // Green

  // To better see the status indicating RGB LED's state
  delay(2000);
}

```
> 0 votes

---
Tags: wifi, http, mkr1010
---


# Question
Title: How do I upload a sketch without a bootloader, using another Arduino as a programmer?
*Note: This is a reference question (but feel free to write answers of your own!)*

---

My Arduino takes too long to start up, I need to use the space taken up by the bootloader and I don't want a brown-out to be able to move the program counter to bootloader code, which could lead to my code being corrupted.

I considered buying an Arduino programmer, but since I already have an Uno lying around doing nothing, I would rather use that as a programmer.

I found a few guides on the internet, but most of them leave important details out and aren't specific enough.

So, how can I upload a sketch without a bootloader, using another Arduino as a programmer?

# Answer
There are a few guides on the internet that explain how to do this, but I've found that most of them contain too much ambiguity or leave important details out. This is my attempt at writing a short but complete guide that's easy to follow.

## Prerequisites

* The board that will run your sketch
* A board that will act as a programmer (a.k.a. "ISP")
* 7 wires
* Any small capacitor

## Steps

### Programming the programmer

First, you'll need to upload the ArduinoISP sketch to the programmer. Here's how:

1. In the Arduino IDE, press `Alt`+`F` and open Examples -\> 11.ArduinoISP -\> ArduinoISP.
2. Plug in the programmer board (USB).
3. Press `Alt`+`T` and set "Board" to your *programmer* board's type and "Port" to your *programmer* board's serial port.
4. Press `Ctrl`+`U` to upload the sketch to your programmer.

### Connecting the boards

Then you need to connect the programmer to the board that will run your sketch.

1. Unplug the programmer board. This is to prevent accidental short-circuits.
2. Connect pins **GND, 10, MOSI, MISO, SCK and 5V** of the programmer to pins **GND, RESET, MOSI, MISO, SCK and 5V** of the board that will run your sketch, respectively. Pins MOSI, MISO and SCK correspond to pins 11, 12 and 13, respectively, on the Uno and the Nano. Consult your board's datasheet if you're uncertain.
3. Connect the capacitor between pins 5V and RESET of the programmer board. This is to prevent it from auto-resetting while programming.
4. Plug in the programmer board. You will never need to plug in the board that will run your sketch.

### Uploading your sketch

The order of these steps is important due to a bug in the Arduino IDE.

1. Press `Alt`+`T` and set "Board" to *the board that will run your sketch*'s type, "Port" to your *programmer* board's serial port and "Programmer" to "Arduino as ISP".
2. Open the sketch you would like to upload.
3. Press `Ctrl`+**`Shift`**+`U` to upload the sketch using the programmer.

## Troubleshooting

If something went wrong, press `Ctrl`+`,` and enable verbose "compilation" and "upload" and repeat the step that went wrong. Look out for these error messages:

### `avrdude: stk500_recv(): programmer is not responding`

Followed by something similar to:

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

```

Remove the capacitor before uploading a sketch to your *programmer* board.

### `avrdude: Yikes! Invalid device signature.`

Scroll up and copy the line that looks similar to the following:

```
...avrdude -C...avrdude.conf -v -V -p... -c... -P... -b... -Uflash:w:....hex:i

```

Paste it into a terminal and add  `-F` to the end. You can reuse this command every time you upload the same sketch.

### The upload seems to succeed but my sketch is still running the same code!

If the board that runs your sketch's CPU clock is slower than 1MHz (e.g. your sketch modifies the CPU prescaler), you need to change `(1000000/6)` in the ArduinoISP sketch to something slower and re-upload the sketch to your programmer.
> 3 votes

---
Tags: bootloader, arduino-as-isp
---


# Question
Title: How can I clear two FastLEDs strip ws2812b separately? One strip is connected to pin 7 of UNO and other strip to pin 6 of UNO
The power supply is external. I want to clear one strip say pin 7, and meanwhile i dont want other strip say pin 6 to switch off...I use FastLED.clear(); FastLED.show(); But it clears all the led strips connected to pin6 and pin7. What is the code to switch off only one strip?

# Answer
You can use two `CLEDController` instances, which you can control separately, and by using the `clearLedData` you can clear either one or the other LED strip (depending on the `CLEDController` instance).

Below is the code I copied from https://forum.arduino.cc/t/xrads-fastled-fastled-clear-question/693569/8 which contains more info:

```
#include <FastLED.h>

#define COLOR_ORDER GRB
#define LED_TYPE WS2812B

#define DATA_PIN 9
#define NUM_LEDS 26
CRGB leds[NUM_LEDS];

#define HEADLIGHTS 10   //headlight led pin
#define NUM_HEADLIGHTS 2
CRGB leds2[NUM_HEADLIGHTS];

CLEDController &ledController = FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
CLEDController &headlightController =   FastLED.addLeds<LED_TYPE, HEADLIGHTS, COLOR_ORDER>(leds2, NUM_HEADLIGHTS);

void setup() {
  ledController.setCorrection(TypicalLEDStrip);
  headlightController.setCorrection(TypicalLEDStrip);

  ledController.clearLedData();
  headlightController.clearLedData();
  FastLED.show();
}

void loop() {
}

```
> 1 votes

---
Tags: arduino-mega, ws2812
---


title: Arduino Nano IOT33 - Using flash

text:
# Question
Title: Arduino Nano IOT33 - Using flash
I'm looking for a way to store data on flash as on ESP8266 or ESP32 using `FS.h`, `LITTLEFS.h` but it fails.

Is is possible on Nano IOT33 ?

# Answer
It seems this library can be used:

https://github.com/cmaglie/FlashStorage

Library: FlashStorage library for Arduino

About info: A convenient way to store data into Flash memory on the ATSAMD21 and ATSAMD51 processor family

Mentioned in external related article (thanks to Juraj): https://forum.arduino.cc/t/persistent-storage-for-arduino-nano-33-iot-no-eeprom/623137

**UPDATE**

(See remark of Juraj below: this is NOT for a Nano IOT33)

See Library: https://github.com/khoih-prog/FS\_Nano33BLE

About info: Wrapper of FS (LittleFS or not-advisable FATFS) for Arduino MBED nRF52840-based boards, such as Nano\_33\_BLE boards. This library facilitates your usage of FS (LittleFS or FATFS) for the onboard flash. FS supports power fail safety and high performance

Mentioned in: https://forum.arduino.cc/t/fs-nano33ble-library-for-nano-33-ble-using-littlefs-fatfs/900463
> 1 votes

---
Tags: flash, arduino-nano-33-iot
---


title: How can I log data to a thumb drive?

text:
# Question
Title: How can I log data to a thumb drive?
I am working on a project where I need to log data, but I was wondering if it is possible to log that data to a thumb drive? I know that I can log data to an SD card, but I thought a thumb drive would be more accessible to users who wish to obtain the data. And if it is possible to log to a thumb drive, could it be done in CSV format? The data is just sensor data.

# Answer
In principle you can log to a thumb drive any data you want, binary and text (thus also CSV).

However, the Arduino Uno does not support connecting a USB stick directly. If you want to connect a USB stick, you need a so called USB Host shield (for Arduino).

More information can be read on the Arduino site at this page:

https://docs.arduino.cc/retired/shields/arduino-usb-host-shield
> 2 votes

# Answer
\[Updated\]

As an alternative to a Uno host shield, changing to a different Arduino MCU may also assist. USB host capabilty is needed for communicating with thumb drives.

Some Arduino models have a native USB port (e.g., Arduino Due, Arduino Leonardo, Arduino Micro, Arduino Nano 33 IOT, Arduino Zero, Arduino MKR Zero, Arduino MKR1000 ... ) which will work as a USB client device role.

A smaller set of MCU can act as either a USB client or host (e.g., Arduino Due, Arduino Portenta, ...). There is a USBHost library for Arduino Due listed in the Arduino Reference. Documentation for Arduino Portenta in USB host mode is here.

Here is a discussion (and reference to an alternative library) regarding using a Due to write files to a thumb drive.

Of course an adapter cable or a thumb drive with a physical connector matching the native USB port on the selected MCU is required. Both are commonly available.

See also Can the Arduino interface with USB devices without the USB host shield?
> 2 votes

---
Tags: arduino-uno, usb, data, logging
---


# Question
Title: Why doesn't serial communication work on Arduino Uno r3 and ESP8266 WiFi module?
I have a simple problem here. I use an ESP8266 WiFi module and an Arduino Uno r3.

What I want is to receive a serial message from the ESP8266 on the Arduino Uno.

Note: I set the upload speed of the ESP8266 to 9600.

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

void loop() {
  Serial.write("hello friend");
  delay(2000);
}

```

Arduino Uno:

```
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); //rx, tx

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

String message = "";
boolean check = false;

void loop() {
  Serial.println(mySerial.available());
  mySerial.println("hindi nagagana");
  while (mySerial.available() > 0) {
    Serial.println(mySerial.readString());
    check = true;
  }

  if (check == true) {
    Serial.println(message);
  }

  delay(200);
}

```

Or any idea on how to control the Arduino Uno via the internet, such as a simple LED blink?

I used Firebase for databases an I plan to use ReactJs for webApp/Native App (nodeJs).

# Answer
i think you should change `Serial.write()` to `Serial.print()` because `Serial.write()` is for send data as bytes or series of bytes and `Serial.print()` send as human-readable text.
Reference:
Serial.write()
https://www.arduino.cc/reference/en/language/functions/communication/serial/write/
Serial.print()
https://www.arduino.cc/reference/en/language/functions/communication/serial/print/
esp 8266 code:

```
void setup()
{
 Serial.begin(9600);
}
void loop(){
    Serial.print("hello friend");
    delay(2000);

 }

```
> -1 votes

---
Tags: arduino-uno, esp8266
---


# Question
Title: How to cut down size of imported DigiKeyboard library
I'm working on a project with a Digispark ATTiny85, that performs keystrokes using the DigisparkKeyboard library (https://github.com/digistump/DigisparkArduinoIntegration/tree/master/libraries/DigisparkKeyboard). Besides the DigiKeyboard, I also import EEPROM.h.

My own code is only about 150 lines, I've cut down the size following a number of online guides, trying to avoid larger data types and so on. The Digispark is limited to ~6kB and the imported DigiKeyboard library takes up a little more that 5.4kB. In total the compiled project takes up about 7kB, which exceeds the boards capacity.

From the DigiKeyboard library I only use `DigiKeyboard.sendKeyStroke()` and `DigiKeyboard.print()` (with about only ten different characters). So I assume there is a lot of unused code I could remove, but I don't know how to approach this. I use Visual Studio Code and PlatformIO.

How could I reduce the size of the used DigisparkKeyboard library?

# Answer
With input from @EdgarBonet, I looked into the functions used and it turned out that the `String()` function, I used once in my code, takes up about 3kB of space in the compiled program.

I ended up removing the line with `String()` and kept the imported DigiKeyboard library as it is.
> 4 votes

# Answer
The compiler/linker will remove unused functions/methods automatically, so I doubt you can save memory by removing unused functions/methods yourself.

However, you could possibly gain by:

* Removing the calls of check functions/methods when you know the result will be always `false`, `true`, or always the same number, string or data type in general.
* Removing (parts of) functions/methods which are related to physical or logical functionality you never use. Like e.g. `if`, `case` statements that will never apply).
* Prevent using an entire class (e.g. `String`) (see second comment of Emma Makes below).
> 1 votes

---
Tags: compile, code-optimization, keyboard, digispark
---


# Question
Title: LED blink patterns with multiple LEDs with millis() not using Delay()
I want to make LED blink patterns with multiple LEDs with the `millis()` function. I researched about it but did not find a perfect solution.

I found one blog, but it is using a LED pin number array; I need a solution without an array. Any help will be appreciated.

This is my code which I have written:

```
const int Button_code_1 = 2;
const int Button_code_2 = 3;
const int Button_code_stop = 4;

const int LED_one = 6;
const int LED_two = 8;
const int LED_three = 10;
const int LED_four = 12;

int buttonState_code_1 = 0;
int buttonState_code_2 = 0;
int buttonState_code_stop = 0;

void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);

  pinMode(Button_code_1,INPUT);
  pinMode(Button_code_2,INPUT);
  pinMode(Button_code_stop,INPUT);

  pinMode(LED_Button_one,INPUT);
  pinMode(LED_Button_two,INPUT);
  pinMode(LED_Button_three,INPUT);
  pinMode(LED_Button_four,INPUT);

  pinMode(LED_one, OUTPUT);
  pinMode(LED_two, OUTPUT);
  pinMode(LED_three, OUTPUT);
  pinMode(LED_four, OUTPUT);
}

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

  buttonState_code_1 = digitalRead(Button_code_1);
  Serial.println(buttonState_code_1);
  buttonState_code_2 = digitalRead(Button_code_2);
  Serial.println(buttonState_code_2);
  delay(1000);
  buttonState_code_stop = digitalRead(Button_code_stop);

  if(buttonState_code_1==1)
  {
    pattern_one();
  }
  if(buttonState_code_2==1)
  {
    pattern_two();
  }

}

void pattern_one()
{
  digitalWrite(LED_one, LOW);
  digitalWrite(LED_two, HIGH);
  digitalWrite(LED_three, LOW);
  digitalWrite(LED_four, LOW);
  delay(3000);
  digitalWrite(LED_one, LOW);
  digitalWrite(LED_two, LOW);
  digitalWrite(LED_three, LOW);
  digitalWrite(LED_four, HIGH);
  delay(3000);
  digitalWrite(LED_one, HIGH);
  digitalWrite(LED_two, LOW);
  digitalWrite(LED_three, LOW);
  digitalWrite(LED_four, LOW);
  delay(3000);
  digitalWrite(LED_one, LOW);
  digitalWrite(LED_two, LOW);
  digitalWrite(LED_three, HIGH);
  digitalWrite(LED_four, LOW);
  delay(3000);
}

void pattern_two()
{
  digitalWrite(LED_one, HIGH);
  digitalWrite(LED_two, LOW);
  digitalWrite(LED_three, LOW);
  digitalWrite(LED_four, LOW);
  delay(3000);
  digitalWrite(LED_one, LOW);
  digitalWrite(LED_two, LOW);
  digitalWrite(LED_three, HIGH);
  digitalWrite(LED_four, LOW);
  delay(3000);
  digitalWrite(LED_one, LOW);
  digitalWrite(LED_two, HIGH);
  digitalWrite(LED_three, LOW);
  digitalWrite(LED_four, LOW);
  delay(3000);
  digitalWrite(LED_one, LOW);
  digitalWrite(LED_two, LOW);
  digitalWrite(LED_three, LOW);
  digitalWrite(LED_four, HIGH);
  delay(3000);
}

```

This is my sample code with four LEDs. I have written this code with `delay()`, so when I want to change the pattern I can't because `delay()` is blocking the code.

I researched this and found the `millis()` function as the solution. How can I implement this code using the `millis()` function?

# Answer
> 1 votes
This is one of the effects for 3 (sets) of LEDs from my light alarm clock sketch:

```
void cycleEffect() {

  static unsigned long previousMillis;
  static uint8_t cycleCounter;

  if (millis() - previousMillis > 100) {
    previousMillis = millis();
    digitalWrite(LEDS_CENTRAL_PIN, cycleCounter == 0);
    digitalWrite(LEDS_LEFT_PIN, cycleCounter == 1);
    digitalWrite(LEDS_RIGHT_PIN, cycleCounter == 2);
    cycleCounter++;
    if (cycleCounter == 3) {
      cycleCounter = 0;
    }
  }
}

```

---
Tags: arduino-uno, led, millis
---


# Question
Title: Detect where touch happened on a big capacitive electrode
I have a big-ish electrode (10cm x 10cm) that works fine for detecting touch over the whole electrode (as a boolean - simple touch vs. release) but I was wondering if there was a way to detect where on the electrode there was a touch, using filtered data or something? I saw this link where the person made a capacitive touch grid. All their copper tape rows/columns are touching. When I try to connect multiple clips to a single electrode though (more-or-less what they did) my MPR121 becomes unresponsive.

I'm using an Arduino Uno, a Sparkfun MPR121 capsense breakout, and this library for interacting with the MPR121.

Here's a basic program I have running at the moment just to check out an average of filtered data readings to see if there's a pattern. There isn't. The readings are anywhere between 250 and 580 no matter where the electrode is touched.

```
#include <MPR121.h>
#include "Wire.h"

int readingSum = 0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  MPR121.begin(0x5A);
  MPR121.setInterruptPin(2);

  MPR121.setTouchThreshold(50);
  MPR121.setReleaseThreshold(40);

  delay(1000);
}

void loop() {
  if (MPR121.touchStatusChanged()) {
    MPR121.updateAll();
    if (MPR121.isNewTouch(0)) {
      for (uint8_t i = 0; i < 8; i++) {
          readingSum += MPR121.getFilteredData(0);
      }
      Serial.println(readingSum / 8);
    }
    readingSum = 0;
  }
}

```

# Answer
As @jsotola mentioned in the comments, no I don’t think there is a way to take a single electrode and turn it into a touchpad. Touchpads rely on a grid of addressable capacitance points to resolve a location.

I didn’t spend a lot of time investigating the link you referenced. However I wonder if you allowed for the adhesive backing on the copper tape when you attempted to replicate the example. It looks to me to be rows and columns of copper conductor separated by a thin layer of adhesive. Not the same thing as one big conductor.
> -1 votes

---
Tags: arduino-uno, capacitors
---


# Question
Title: Using pyFirmata with a 360° servo; how do I stop it?
I am testing out pyFirmata. I have a 360° servo, and know how to change its direction, but I dont't know how to stop it.

What command, like `servo.write()`, would work to make it stop moving until prompted to move again?

# Answer
> 1 votes
You'll need to check datasheets for your servos but a PWM value of 1500 microseconds would generally be near neutral / no rotation. Decreasing values less than this should generate increasing speed clockwise. Increasing values greater than neutral should generate increasing speed counter clockwise.

See https://arduino.stackexchange.com/a/88650/71575

---
Tags: programming, python, continuous-servo
---