title: Run function when triggered

text:
# Question
Title: Run function when triggered
I'm trying to create a motion/fall sensing device. I have a sensor that continuously checks if motion and fall is detected in `void loop()`. If both motion and fall are detected, then I'd like to send an image to my computer. My image capture function is `camCapture()`. The problem is that once the motion and fall detected, it continuously calls `camCapture()` and repeatedly sends images to the computer given that `camCapture()` is called in `void loop()`. I'd like to only send a single image when it is triggered, and a single image every time it is triggered thereafter. For example, if the motion and fall is triggered, then send an image once. If it detects motion and fall again after it has already gone back to LOW, then send an image again once.

I can't use `setup()` since I can only run a function once, and it defeats the purpose of what I'm trying to do. My `void loop()` code is below.

```
void loop()
{
  // Read data from accelerometer
  mma.read();
  sensors_event_t event;
  mma.getEvent(&event);

  // Store magnitude of all axis
  magnitude = calculateMagnitude(event.acceleration.x, event.acceleration.y, event.acceleration.z);

  // Motion is detected! 20 seconds will be given to detect a fall from the accelerometer
  if(digitalRead(pirSensor) == HIGH)
  {
    num_timeAtPIR = millis(); // Time that PIR sensor was activated with respect to the system time
    bool_waitForAccel = 1; // Set flag to true to wait for accelerometer
    Serial.println("Motion detected!");
    digitalWrite(buzzer, LOW);
    //delay(1000);

  }
  else if(magnitude > sensitivity)
  {
    num_timeAtAccel = millis();
    Serial.println("Fall detected!");
    Serial.print("Magnitude is: ");
    Serial.println(magnitude);
    bool_waitForPIR = 1; // Waiting for PIR
    Serial.println();

    digitalWrite(buzzer, HIGH);
    delay(4000);

  }
  else // No motion is detected
  {
    Serial.println("No motion detected! :(");
    bool_waitForPIR = 0;
    bool_waitForAccel = 0;
    Firebase.setInt(firebaseData, pirPath, 0);
    Firebase.setInt(firebaseData, accelPath, 0);
    digitalWrite(buzzer, LOW);
  }

  // Motion then Fall are detected. Alarm is activated and picture is captured and save onto server.
  if(bool_waitForAccel == 1 && (magnitude > sensitivity))
  {

    Serial.println("Motion and Fall detected!");
    Serial.print("Magnitude is: ");
    Serial.println(magnitude);
    bool_waitForAccel = 0; // No longer waiting for accelerometer
    Serial.println();

    digitalWrite(buzzer, HIGH);
    delay(4000);

    camCapture(); // Take picture!

  }

  // Fall then motion are detected. Alarm is activated and picture/video is captured to save onto website.
  else if(bool_waitForPIR == 1 && (magnitude > sensitivity))
  {
    Serial.println("Fall detected");
    Serial.print("Magnitude is: ");
    Serial.println(magnitude);
    Serial.println();

    bool_waitForPIR = 0; // No longer waiting for PIR

    digitalWrite(buzzer, HIGH);

    delay(4000);

    camCapture(); // Take picture!

  }

  // 20 second timer to check if a Fall is detected after Motion is detected.
  if(millis() > (num_timeAtPIR + period))
  {
    bool_waitForAccel = 0; // Set flag to false
  }
  else if(millis() > (num_timeAtAccel + period)) // 20 second timer to check if Motion is detected after a fall is detected
  {
    bool_waitForPIR = 0;
  }

}

```

UPDATE 1: Posting the rest of the code.

```
// Program header files
#include <Wire.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ArduCAM.h>
#include <SPI.h>
#include "FS.h"
#include "FirebaseESP32.h"
#include "memorysaver.h"
#include <Adafruit_MMA8451.h>
#include <Adafruit_Sensor.h>

//Time and Date NTP Server Header
#include <NTPClient.h>
#include <WiFiUdp.h>

//Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

//Variables to save date and time
String formattedDate = "";
String dayStamp = "";
String timeStamp = "";

String logPath = "/Log";
String tempPath = "/Log/Temperature";
String pirPath = "/Log/PIR_Sensor";
String accelPath = "/Log/Accelerometer";
String pirDatePath = "/Log/pir_Date";
String pirTimePath = "/Log/pir_Time";
String accelDatePath = "/Log/accel_Date";
String accelTimePath = "/Log/accel_Time";

// Database/Wi-Fi configuration
#define FIREBASE_HOST "host"
#define FIREBASE_AUTH "auth"
#define AP_SSID "apssid"
#define AP_PASSWORD "password"

#define WIFI_SSID "ssid"
#define WIFI_PASSWORD "passsword"

// Variables to keep track of previous and current time to create a delay
unsigned long currentTime = 0;
unsigned long prevTime = 0;

unsigned long bool_waitForAccel = 0; // Used to flag the accelerometer
unsigned long bool_waitForPIR = 0; // Used to flag the PIR
unsigned long num_timeAtPIR = 0; // Used to keep track of the time the PIR sensor detected motion
unsigned long num_timeAtAccel = 0; // Used to keep track of the time the accelerometer detected a fall
unsigned long period = 20000; // Amount of time given to check after motion is detected

int statusLED = 26; // Choose the pin for status LED
int buzzer = 12; // Choose the pin for Piezzo Buzzer. Connected from MOSFET gate.
int tempSensor = 2; // Choose pin for Temperature Sensor
int pirSensor = 27; // Choose pin for controller PIR Sensor

int PIR_Power = 25; // Controls Power gate for PIR Sensor
int ArduCAM_Power = 32; // Controls Power gate for ArduCAM

const int CS = 5; // GPIO5 as Slave Select for ArduCAM

int wifiType = 0; // 0: Station    1: AP (Access Point)

// Set up requests to send captured image to external server
bool onlineMode = true;
String start_request = "";
String boundary = "_cam_";
String end_request = "\n--" + boundary + "--\n";

// Set buffer size for camera data
static const size_t bufferSize = 2048;
static uint8_t buffer[bufferSize] = {0xFF};
byte buf[256];
static int iPic = 0;
static int kPic = 0;
uint8_t temp = 0, temp_last = 0;
uint32_t len = 0;
bool is_header = false;

// Threshhold for declaring a fall on the accelerometer
float sensitivity = 11.0;

float magnitude = 0.0; // Stores the calculated magnitude

// Accelerometer, Semaphore, and Firebase instances
Adafruit_MMA8451 mma = Adafruit_MMA8451();
FirebaseData firebaseData;

#if defined (OV2640_MINI_2MP) || defined (OV2640_CAM)
ArduCAM myCAM(OV2640, CS);
#endif

WiFiClient client;

void start_capture()
{
  myCAM.clear_fifo_flag();
  myCAM.start_capture();
}

void camCapture()
{
  digitalWrite(ArduCAM_Power, HIGH);

  // Flush the FIFO
  myCAM.flush_fifo();
  // Clear capture done flag
  myCAM.clear_fifo_flag();
  // Start capture
  myCAM.start_capture();

  Serial.println("Start capture!");
  while(!myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK));

  len = myCAM.read_fifo_length();
  Serial.print("The FIFO length is: ");
  Serial.println(len);

  if(len >= MAX_FIFO_SIZE) // 8M
  {
    Serial.println("Over size!");
  }
  if(len == 0) // 0KB
  {
    Serial.println("Size is 0KB");
    return;
  }

  long full_length;
  if(client.connect("xx.xx.xx.xx", 80) || onlineMode)
  {
    if(onlineMode)
    {
      while(client.available())
      {
        String line = client.readStringUntil('\r');
      }
    }

  start_request = start_request +
  "\n--" + boundary + "\n" +
  "Content-Disposition: form-data; name=\"data\"; filename=\"CAM.jpg\"\n" +
  "Content-Transfer-Encoding: binary\n\n";

  full_length = start_request.length() + len + end_request.length();
  client.println("POST /uploads.php HTTP/1.1");
  client.println("Host: xx.xx.xx.x");
  client.println("Content-Type: multipart/form-data; boundary =" + boundary);
  client.print("Content-Length: "); client.println(full_length);
  client.println();
  client.print(start_request);

  iPic = 0;

  static uint8_t buffer[bufferSize] = {0xFF};

  while (len--)
  {
    temp_last = temp;
    temp =  SPI.transfer(0x00);
    //Read JPEG data from FIFO
    if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while,
    {
      buf[iPic++] = temp;  //save the last  0XD9
      //Write the remain bytes in the buffer
      myCAM.CS_HIGH();
      client.write(buf, iPic);
      //Close the file
      //file.close();
      Serial.println(F("Image save OK."));
      is_header = false;
      iPic = 0;
    }
    if (is_header == true)
    {
      //Write image data to buffer if not full
      if (iPic < 256)
        buf[iPic++] = temp;
      else
      {
        //Write 256 bytes image data to file
        myCAM.CS_HIGH();
        client.write(buf, 256);
        iPic = 0;
        buf[iPic++] = temp;
        myCAM.CS_LOW();
        myCAM.set_fifo_burst();
      }
    }
    else if ((temp == 0xD8) & (temp_last == 0xFF))
    {
      is_header = true;
      buf[iPic++] = temp_last;
      buf[iPic++] = temp;
    }
  }

  // End the POST request to the server
  client.println(end_request);

  myCAM.CS_HIGH();

  // Stop the client
  client.stop();
  digitalWrite(ArduCAM_Power, LOW);
  }
  else // No connection to the server.
  {
    Serial.println("Could not connect to external server!");
    Serial.println("Please check the IP address or Port");
    return;
  }
}

// Calculate the magnitude with the x, y, and z axis of the accelerometer.
// Gives an overall value that is better than just using the z-axis
float calculateMagnitude(float x, float y, float z)
{
  float magnitude = sqrt(sq(x) + sq(y) + sq(z));

  return magnitude;
}

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  SPI.begin();
  SPI.setFrequency(4000000);

  pinMode(CS, OUTPUT);
  pinMode(PIR_Power, OUTPUT); // Set mosfet gate to output for PIR Sensor
  pinMode(ArduCAM_Power, OUTPUT); // Set mosfet gate to output for ArduCAM

  pinMode(statusLED, OUTPUT);      // Declare LED as output
  pinMode(buzzer, OUTPUT);         // Declare Piezo Buzzer as output
  pinMode(pirSensor, INPUT);        // Declare PIR Sensor as input

  Serial.println();

  // Check if accelerometer is properly connected/found
  if(!mma.begin())
  {
    Serial.println("Couldn't start MMA8451 Accelerometer.");
    Serial.println("Check your connections.");
    while(1);
  }
  Serial.println("MMA8451 Accelerometer found!");

  // Set the g-range for the accelerometer. Can be adjusted to 2g, 4g, or 8g.
  mma.setRange(MMA8451_RANGE_2_G);

  // Check if camera is found
  digitalWrite(ArduCAM_Power, HIGH);
  uint8_t vid, pid;
  uint8_t temp;
  while(1)
  {
    //Check if the ArduCAM SPI bus is OK
    myCAM.write_reg(ARDUCHIP_TEST1, 0x55);
    temp = myCAM.read_reg(ARDUCHIP_TEST1);
    if (temp != 0x55) {
      Serial.println(F("SPI interface Error!"));
      delay(2);
      continue;
    }
    else
      break;
  }

  #if defined (OV2640_MINI_2MP) || defined (OV2640_CAM)
  //Check if the camera module type is OV2640
  myCAM.wrSensorReg8_8(0xff, 0x01);
  myCAM.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
  myCAM.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
  if ((vid != 0x26 ) && (( pid != 0x41 ) || ( pid != 0x42 )))
    Serial.println(F("Can't find OV2640 module!"));
  else
    Serial.println(F("OV2640 detected."));
  #endif

  //Change to JPEG capture mode and initialize the OV2640 module
  myCAM.set_format(JPEG);
  myCAM.InitCAM();

  myCAM.OV2640_set_JPEG_size(OV2640_640x480);
  myCAM.clear_fifo_flag();
  // Turn off Camera
  digitalWrite(ArduCAM_Power, LOW);

  // Connect to WiFi
  if (wifiType == 0)
  {
    if(!strcmp(WIFI_SSID,"SSID"))
    {
      Serial.println(F("Please set your SSID"));
      while(1);
    }
    if(!strcmp(WIFI_PASSWORD,"PASSWORD"))
    {
      Serial.println(F("Please set your PASSWORD"));
      while(1);
    }
    // Connect to WiFi network
    Serial.println();
    Serial.print(F("Connecting to: "));
    Serial.println(WIFI_SSID);

    WiFi.mode(WIFI_STA);

    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

    while (WiFi.status() != WL_CONNECTED)
    {
      delay(500);
      Serial.print(F("."));
    }

    Serial.println();
    Serial.println(F("WiFi connected"));
    Serial.println();
    Serial.println(WiFi.localIP());
  }
  else if (wifiType == 1)
  {
    Serial.println();
    Serial.println();
    Serial.print(F("Shared AP: "));
    Serial.println(AP_SSID);
    Serial.print(F("The password is: "));
    Serial.println(AP_PASSWORD);

    WiFi.mode(WIFI_AP);

    WiFi.softAP(AP_SSID, AP_PASSWORD);

    Serial.println();
    Serial.print("AP IP Address is: ");
    Serial.println(WiFi.softAPIP());
  }

  // Initialize a NTPClient to get time
  timeClient.begin();
  timeClient.setTimeOffset(-14400);

  //If Firebase is connected, turn on the LED
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.reconnectWiFi(true);
  digitalWrite(statusLED,HIGH);

  Serial.println("------------------------------------");
  Serial.println("Path exist test...");
  if (Firebase.pathExist(firebaseData, logPath))
  {
    Serial.println("Path " + logPath + " exists");
  }
  else
  {
    Serial.println("Path " + logPath + " does not exist");
    Serial.println("Adding all necessary paths to /Log");
    Serial.println("Will have to reinitialize later once everything is set up.");

     // Initialize All  variables to 0;
    Firebase.setFloat(firebaseData, tempPath, 0.0);
    Firebase.setInt(firebaseData, pirPath, 0);
    Firebase.setInt(firebaseData, accelPath, 0);
    //Firebase.setString(firebaseData, pirDatePath, ???);
    //Firebase.setString(firebaseData, pirTimePath, ???);
    //Firebase.setString(firebaseData, accelDatePath, ???);
    //Firebase.setString(firebaseData, accelTimePath, ???);

  }
  Serial.println("------------------------------------");
  Serial.println();

  digitalWrite(PIR_Power, HIGH);

  digitalWrite(pirSensor, LOW);
  digitalWrite(statusLED, LOW);

  Serial.println("Sensors booting up...");
  delay(10000); // Let sensors boot up, 10s
  Serial.println("Sensors ready!");
}

```

# Answer
You need to add a state variable to your `loop()` function.

At the start of `loop()` add a variable declaration like:

```
void loop()
{
  static bool capture_sent = false;

```

Then change your line

```
  if(bool_waitForAccel == 1 && (magnitude > sensitivity))
  {

```

to

```
  if(!capture_sent && bool_waitForAccel == 1 && (magnitude > sensitivity))
  {
    capture_sent = true;

```

or, if you want to perform some of the logic in that stanza and just not call `camCapture()` then leave the `if` line alone and make the call to `camCapture()` conditional upon `!capture_sent`.

Then in any place in your code where you see the condition which tells you you'd want to call `camCapture()` again when triggered, reset `capture_sent` to \`false. I'm leaving it up to you to decide where that goes because you understand what conditions determine that.
> 1 votes

---
Tags: esp8266, programming, arduino-ide, esp32, loop
---


# Question
Title: ESP8266 HTTPS post body request with WifiClientSecure
Is there a way to post HTTPS body request in Arduino esp8266. I am able to HTTPS parameter request with WifiClientSecure library,but is not safe compared to Request Body send in POST.

# Answer
> 1 votes
You do it like any other POST. It's just you happen to be using a secure client to make the connection.

1. Open the connection
2. Send the right headers, including a `Content-Type` and `Content-Length` and maybe a `Content-Encoding` if you encode it.
3. Send the body

It's not any different to an unencrypted POST request.

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


# Question
Title: Osepp DS1307 RTC program error (tmElements_t tm; does not name a type)
Using a basic 1307 SetTime program, and ran into a problem (first time programming a module).

```
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>

const char *monthName[12] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

tmElements_t tm;

void setup() {
  bool parse=false;
  bool config=false;

  // get the date and time the compiler was run
  if (getDate(__DATE__) && getTime(__TIME__)) {
    parse = true;
    // and configure the RTC with this info
    if (RTC.write(tm)) {
      config = true;
    }
  }

  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
  delay(200);
  if (parse && config) {
    Serial.print("DS1307 configured Time=");
    Serial.print(__TIME__);
    Serial.print(", Date=");
    Serial.println(__DATE__);
  } else if (parse) {
    Serial.println("DS1307 Communication Error :-{");
    Serial.println("Please check your circuitry");
  } else {
    Serial.print("Could not parse info from the compiler, Time=\"");
    Serial.print(__TIME__);
    Serial.print("\", Date=\"");
    Serial.print(__DATE__);
    Serial.println("\"");
  }
}

void loop() {
}

bool getTime(const char *str)
{
  int Hour, Min, Sec;

  if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
  tm.Hour = Hour;
  tm.Minute = Min;
  tm.Second = Sec;
  return true;
}

bool getDate(const char *str)
{
  char Month[12];
  int Day, Year;
  uint8_t monthIndex;

  if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
  for (monthIndex = 0; monthIndex < 12; monthIndex++) {
    if (strcmp(Month, monthName[monthIndex]) == 0) break;
  }
  if (monthIndex >= 12) return false;
  tm.Day = Day;
  tm.Month = monthIndex + 1;
  tm.Year = CalendarYrToTm(Year);
  return true;
}

```

And I got the following

```
"tmElements_t tm;" does not name a type.

```

# Answer
> 1 votes
According to example ReadTest/ReadTest.ino, you have to include

```
#include <TimeLib.h>

```

See also comment from Alexander below (unchecked by me) that Time.h needs to be referenced.

---
Tags: programming, rtc
---


# Question
Title: SIM800l doesn't respond on arduino micro
I want my Arduino Micro to interact with my SIM 800 L module. But unfortunately nothing happens, may you can help me figure out where I made a mistake. Here's my wiring:

Summary of my wiring:

* *External Battery ---\> 800L*
* plus ---\> 5VIN
* minus ---\> GND (both in POWER and UART TTL-Section)

---

* *Arduino ---\> 800L*
* RX ---\> RXD
* TX ---\> TXD

With that setup I'm using the following code:

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

//Arduino Micro
//SIM 800l

SoftwareSerial mySerial(1, 0); // RX, TX

void setup()
{
  // Open serial communication
  Serial.begin(9600);

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);

  Serial.println("Setup finished");

}

void loop() // run over and over
{
  Serial.println("Sending AT command");
  mySerial.write("AT"); //OK should be returned
  delay(1000);
  //read sim-module response
  Serial.println("Response: ");
  while( mySerial.available() )
  {
    char c = mySerial.read();
    Serial.print(c);
  }

  mySerial.write("at+cmee=2"); //set sim-module into debug mode

  delay(1000);

  mySerial.write("at+cpin?"); //check if pin is necessary

  //read sim-module response
  while( mySerial.available() )
  {
    char c = mySerial.read();
    Serial.print(c);
  }

}

```

But it gives me the following output as a loop:

```
 Sending AT command
 Response:
 Sending AT command
 Response:
 Sending AT command
 Response:

```

And I've noticed that a yellow LED is blinking on the Arduino while running the program so I assume there has to be some input from the SIM800 but I can't read the data at the moment. On the 800L-board itself is also an LED that blinks in an interval of about one second, wich tells you that it has no connection (I live in a relatively remote area) but even if there's no connection shouldn't it still return OK when sending AT?

If you need any further information feel free to ask. I would appreciate every idea you come up with :)

Edit: On the photo the wire goes from the Arduino directly to the 800L but I've changed it so the 800L-power comes from a battery now.

# Answer
> 1 votes
Here is some edit in your code

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

//Arduino Micro
//SIM 800l

SoftwareSerial mySerial(9,10); // RX, TX

void setup()
{
  // Open serial communication
  Serial.begin(9600);

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);

  Serial.println("Setup finished");

}

void loop() // run over and over
{
  Serial.println("Sending AT command");
  mySerial.write("AT\r\n"); //OK should be returned
  delay(1000);
  //read sim-module response
  Serial.println("Response: ");
  while( mySerial.available() )
  {
    String c = mySerial.readString();
    Serial.println(c);
  }

  mySerial.write("at+cmee=2\r\n"); //set sim-module into debug mode

  delay(1000);

  mySerial.write("at+cpin?\r\n"); //check if pin is necessary

  //read sim-module response
  while( mySerial.available() )
  {
    String c = mySerial.readString();
    Serial.println(c);
  }

}

```

Change UART pins to 9,10 as 0,1 are already used in normal serial. Secondly change Seria.read() to Serial.readString() because as far as i know the response is string.

---
Tags: gsm, softwareserial, arduino-micro, signal-processing
---


# Question
Title: Is it possible to have two serialEvent() in Arduino code?
I am developing a code on Arduino and need to implement a condition that if data is available form "serial2" then only get the input for "Serial" terminal of Arduino.

I have tried with below code, but its behavior is when I am sending something from "serial" terminal of arduino, control goes into the loop "serialEvent()" otherwise even if I am sending the data over "serial2" it is not entering in that loop.

Below is my code snippet:

```
void serialEvent()
{
  int DATAaddressMSb, DATAaddressLSb;
  digitalWrite(DIR485, LOW);
  delay(100);
  delay(10);
  while (Serial2.available()>0)
  {
    Serial.println("serial2 data available");
    int i = 0;
    int bufferIn1[9] = { int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00) };
    bufferIn1[i] = Serial2.read();
    Serial.print(bufferIn1[i], DEC);
    Serial.print(" ");
    if(i == 0){Serial.print("BUFFER VAL 0");
    Serial.print( bufferIn1[i], DEC);}
    if(i == 1){Serial.print("BUFFER VAL 1");
    Serial.print( bufferIn1[i], DEC);}
    if(i == 2){Serial.print("BUFFER VAL 2");
    Serial.print( bufferIn1[i], DEC);}
    i++;
  }

  while (Serial.available()&& pos < sizeof my_str - 1) {
    char c = Serial.read();
    if (c == '\n') {            // \n means "end of message"
            my_str[pos] = '\0';     // terminate the buffer
            pos = 0;                // reset to start of buffer
            String str((char*)my_str);    // converte char array in string
            if (str == "PCB-CODE") { Serial.println(SN_CODE); }
            if (str == "FW-VERSION") { Serial.println(FW_ver); }
            if (str == "STOP" ) { TESTcode = 0; IDcode = 999; }
            if (str == "TEST1") { TESTcode = 1; delay(6000); Serial.println("Enter ID "); }
            if (str == "TEST2") { Serial.println("Initialising Board ");  delay(6000); TESTcode = 2; }           // For all tests

            if (str == "ID0") { IDcode = 999; }
            if (str == "ID1") { delay(60); IDcode = 1; }       // Test for FW version
            if (str == "ID2") { IDcode = 2; }       // Test for 3.3V
            if (str == "ID3") { IDcode = 3; }       // Test for Main power
            if (str == "ID4") { delay(50); IDcode = 4; }       // Test for +15V
            if (str == "ID5") { IDcode = 5; }       // Test for +10V
            if (str == "ID6") { IDcode = 6; }       // Test for +8V
            if (str == "ID7") { IDcode = 7; }       // Test for +5.5V
            if (str == "ID8") { IDcode = 8; }       // Test for +1.2V
            if (str == "ID9") { IDcode = 9; }       // Test for +2.5V
            if (str == "ID10") { IDcode = 10; }     // Test for -15V
            if (str == "ID11") { IDcode = 11; }     // Test for POW_LIGHT
            if (str == "ID12") { IDcode = 12; }     // Test for +s_stab
            if (str == "ID13") {delay(50); IDcode = 13; }     // Test for +CELLA
            if (str == "ID14") { IDcode = 14; }     // Test for FPGA_GPIO
            if (str == "ID15") { IDcode = 15; }     // Test for DAC_OUT
            if (str == "ID16") { IDcode = 16; }     // Test for CURRENT_LOOP
            if (str == "ID17") {delay(50); IDcode = 17; }     // Test for Torque signal
            if (str == "ID18") { IDcode = 18; }     // Test for EXT_TRIGGER
            if (str == "ID19") { IDcode = 19; }     // Test for Encoder
            if (str == "ID20") { IDcode = 20; }     // Test for RAM
            if (str == "ID21") { IDcode = 21; }     // Test for SD Card
            if (str == "ID22") { IDcode = 22; }     // Test for Ethernet
            if (str == "ID23") { IDcode = 23; }     // Test for CAN
            if (str == "ID24") { IDcode = 24; }     // Test for I2C
     for( int i = 0; i < sizeof(my_str);  ++i )    // resetta la stringa ricevuta         // reset the received string
          my_str[i] = (char)0;
        }
        else {my_str[pos++] = c;}
  }
 }

```

Please guide. Thank you........

# Answer
According to https://www.arduino.cc/en/Reference/SerialEvent

Arduino Mega handles:

```
void serialEvent1(){
//statements
}

void serialEvent2(){
//statements
}

void serialEvent3(){
//statements
}

```

Every other Arduino has only single:

```
void serialEvent(){
//statements
}

```
> 1 votes

---
Tags: c++, softwareserial
---


# Question
Title: How do I make a counter that counts the amount of active inputs
I want to make a direction guide using green, yellow and red LEDs. The lights need to change when ever the active input1 reaches a set value, for example:

* Green when the value is lower than 12;
* Yellow when the value is higher than 11 and lower than 20;
* Red when its higher than 19.

I've been searching for a few days but I couldn't find any references.

---

1 By *active inputs* I mean, a series of buttons being pressed at the same time, if there is 29 buttons then when less then 12 of them is pressed the green light would be turned on.

# Answer
> 0 votes
You need something like:

```
const int BUTTON_MAX = 29;
const int button[BUTTON_MAX] = { 5, 6, 7, ... };
const int GREEN_LED = 2;
const int YELLOW_LED = 3;
const int RED_LED = 4;
int current_led;

void setup()
{
   // Setup inputs (buttons)
   for (int i = 0; i < BUTTON_MAX; i++) pinMode(button[i], INPUT_PULLUP);

   // Setup outputs (led)
   pinMode(GREEN_LED, OUTPUT);
   pinMode(YELLOW_LED, OUTPUT);
   pinMode(RED_LED, OUTPUT);

   // Initial state
   current_led = GREEN_LED;
   digitalWrite(GREEN_LED, HIGH);
   digitalWrite(YELLOW_LED, LOW);
   digitalWrite(RED_LED, LOW);
}

void loop()
{
   // Count number of active buttons
   int count = 0;
   for (int i = 0; i < BUTTON_MAX; i++) count += digitalRead(button[i]);

   // Map number of active buttons to led
   int new_led;
   if (count < 12)
      new_led = GREEN_LED;
   else if (count < 20)
      new_led = YELLOW_LED;
   else
      new_led = RED_LED;

   // Check for change and update
   if (new_led != current_led) {
      digitalWrite(current_led, LOW);
      digitalWrite(new_led, HIGH);
      current_led = new_led;
   }

   // Add a few milli-seconds for debounce
   delay(20);
}

```

---
Tags: programming
---


title: Servo Motors PWM pins, Arduino Uno

text:
# Question
Title: Servo Motors PWM pins, Arduino Uno
I wanted to understand how people are connecting a servo motor to pins without PWM, so I went searching and I read that the Servo library uses the timer1 of pin 9 and pin 10 to be able to use other pins.

I would like to ask some questions about this.

1. Could I connect a servo motor on pin 12 by emulation of the library, and another servo on pin 9, another on pin 10 and another on pin 11 at the same time?
2. Or using the Servo library the PWM in pin 9 and 10 stops working?
3. I could then through library emulation connect one servo on pin 7, another on 8, another on 12 and another on 13 ?
4. 4 emulations at the same time?

# Answer
> 1 votes
Have you read the Servo library page?

The library support upto 12 servos outputs. You can use any pin you want.

The library disables analogWrite() (PWM) functionality on pins 9 and 10.

# Answer
> 1 votes
For those looking for more information on PWM in arduino, a must see page is this one: http://www.righto.com/2009/07/secrets-of-arduino-pwm.html. Once you read it you may undestand, what is software and hardware PWM and which are the limitations.

To do the software PWM the servo library takes over one of the three arduino's timers. So pin 9,10 are not available to analoWrite() anymore, resting Timer0 (pins 5,6) and Timer2 (pins 11,3).

Note that internally arduino must use Timer0 to its timing functions (such as delay(), milis(), etc).

So to answer your question:

1) Yes, you can since the library is managing your timers it may allocate fine (as software emulation though).

2) Yes and No. It works for the library itself but may be not at disposal for other libraries or for your code. Example: if you want use it along with RH\_ASK (radio frequency library) you have an conflict of timer usage and may be needed to change the config of one of them to move to another Timer.

3) Yes.

4) Yes (you can get all 20 pins working as PWM if you want. SoftPWM library does that).

Best regards,

gl

---
Tags: arduino-uno, motor, pwm, servo
---


title: AtTiny analog read always 1023

text:
# Question
Title: AtTiny analog read always 1023
I am trying to replicate Low power LED firefly project. So what I'm trying to do is to do an analog read from a LED, to detect light. To simplify it a bit, I am using different pins and different leds for IN and OUT. The code:

```
#define PIN1 don't use this pin! /*this is RESET*/
#define PIN2 3
#define PIN3 4
#define PIN4 don't use this pin! /*this is GND*/
#define PIN5 0
#define PIN6 1
#define PIN7 2
#define PIN8 don't use this pin! /*this is VCC*/
#define ANL1 PIN7
#define ANL2 PIN3
#define ANL3 PIN2

// the setup function runs once when you press reset or power the board
void setup() {
  digitalWrite(PIN3, LOW);
  pinMode(PIN3, INPUT);
}

#define BLINK true
// the loop function runs over and over again forever
void loop() {

  const int value = analogRead(PIN3);
  if(value>=1023) {
    pinMode(PIN2, OUTPUT);
    digitalWrite(PIN2, HIGH);
    delay(500);
    digitalWrite(PIN2, LOW);
    delay(3);
  }
  else {
    delay(1);
  }
}

```

This is the setup. I am using much smaller resistor, but I'm still getting 1023 on analog read, as indicated by the output led always being on:

simulate this circuit – Schematic created using CircuitLab

What's wrong?

# Answer
In this article the following steps are used when using an LED as a light detector:

1. Light up the LED by making the anode positive (logic one) and the cathode negative (logic zero) - this fully discharges the LED as a capacitor.
2. Charge up the capacitor by making the anode negative and the cathode positive, as this is a small capacitor it will take no time at all in other words for as short a time as you can.
3. Put the diode into the measurement mode, by making the anode negative (it already is) and the cathode connected to an analogue input.
4. Make a measurement of the analogue voltage, this is a reference level to be used later.
5. Wait while the photon current is integrated - the longer the more sensitive but too long and effects other than photo current dominate.
6. Measure the voltage again and subtract it from the reference value you took before the integration time. This figure is your light reading.

Looking at the code in the above question it is not apparent where you switch from forward bias to revers bias. Also, it does not appear there are two samples taken and the difference between the two samples is found.
> 1 votes

---
Tags: led, attiny, attiny13
---


# Question
Title: White screen when I perform grapicstest in ili9341
I get a white screen when I perform grapicstest in ili9341. I used the below code:

```
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {
  Serial.begin(9600);
  Serial.println("ILI9341 Test!");

  tft.begin();

  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);

  Serial.println(F("Benchmark                Time (microseconds)"));
  delay(10);
  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(500);

  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(3000);

  Serial.print(F("Lines                    "));
  Serial.println(testLines(ILI9341_CYAN));
  delay(500);

  Serial.print(F("Horiz/Vert Lines         "));
  Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
  delay(500);

  Serial.print(F("Rectangles (outline)     "));
  Serial.println(testRects(ILI9341_GREEN));
  delay(500);

  Serial.print(F("Rectangles (filled)      "));
  Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
  delay(500);

  Serial.print(F("Circles (filled)         "));
  Serial.println(testFilledCircles(10, ILI9341_MAGENTA));

  Serial.print(F("Circles (outline)        "));
  Serial.println(testCircles(10, ILI9341_WHITE));
  delay(500);

  Serial.print(F("Triangles (outline)      "));
  Serial.println(testTriangles());
  delay(500);

  Serial.print(F("Triangles (filled)       "));
  Serial.println(testFilledTriangles());
  delay(500);

  Serial.print(F("Rounded rects (outline)  "));
  Serial.println(testRoundRects());
  delay(500);

  Serial.print(F("Rounded rects (filled)   "));
  Serial.println(testFilledRoundRects());
  delay(500);

  Serial.println(F("Done!"));

}

void loop(void) {
  for(uint8_t rotation=0; rotation<4; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(1000);
  }
}

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  tft.fillScreen(ILI9341_RED);
  yield();
  tft.fillScreen(ILI9341_GREEN);
  yield();
  tft.fillScreen(ILI9341_BLUE);
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  return micros() - start;
}

unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}

unsigned long testLines(uint16_t color) {
  unsigned long start, t;
  int           x1, y1, x2, y2,
                w = tft.width(),
                h = tft.height();

  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1 = y1 = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t     = micros() - start; // fillScreen doesn't count against timing

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = w - 1;
  y1    = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = 0;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = w - 1;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);

  yield();
  return micros() - start;
}

unsigned long testFastLines(uint16_t color1, uint16_t color2) {
  unsigned long start;
  int           x, y, w = tft.width(), h = tft.height();

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
  for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);

  return micros() - start;
}

unsigned long testRects(uint16_t color) {
  unsigned long start;
  int           n, i, i2,
                cx = tft.width()  / 2,
                cy = tft.height() / 2;

  tft.fillScreen(ILI9341_BLACK);
  n     = min(tft.width(), tft.height());
  start = micros();
  for(i=2; i<n; i+=6) {
    i2 = i / 2;
    tft.drawRect(cx-i2, cy-i2, i, i, color);
  }

  return micros() - start;
}

unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
  unsigned long start, t = 0;
  int           n, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  n = min(tft.width(), tft.height());
  for(i=n; i>0; i-=6) {
    i2    = i / 2;
    start = micros();
    tft.fillRect(cx-i2, cy-i2, i, i, color1);
    t    += micros() - start;
    // Outlines are not included in timing results
    tft.drawRect(cx-i2, cy-i2, i, i, color2);
    yield();
  }

  return t;
}

unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(x=radius; x<w; x+=r2) {
    for(y=radius; y<h; y+=r2) {
      tft.fillCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int           x, y, r2 = radius * 2,
                w = tft.width()  + radius,
                h = tft.height() + radius;

  // Screen is not cleared for this one -- this is
  // intentional and does not affect the reported time.
  start = micros();
  for(x=0; x<w; x+=r2) {
    for(y=0; y<h; y+=r2) {
      tft.drawCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testTriangles() {
  unsigned long start;
  int           n, i, cx = tft.width()  / 2 - 1,
                      cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  n     = min(cx, cy);
  start = micros();
  for(i=0; i<n; i+=5) {
    tft.drawTriangle(
      cx    , cy - i, // peak
      cx - i, cy + i, // bottom left
      cx + i, cy + i, // bottom right
      tft.color565(i, i, i));
  }

  return micros() - start;
}

unsigned long testFilledTriangles() {
  unsigned long start, t = 0;
  int           i, cx = tft.width()  / 2 - 1,
                   cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(cx,cy); i>10; i-=5) {
    start = micros();
    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(0, i*10, i*10));
    t += micros() - start;
    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(i*10, i*10, 0));
    yield();
  }

  return t;
}

unsigned long testRoundRects() {
  unsigned long start;
  int           w, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  w     = min(tft.width(), tft.height());
  start = micros();
  for(i=0; i<w; i+=6) {
    i2 = i / 2;
    tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
  }

  return micros() - start;
}

unsigned long testFilledRoundRects() {
  unsigned long start;
  int           i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(tft.width(), tft.height()); i>20; i-=6) {
    i2 = i / 2;
    tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
    yield();
  }

  return micros() - start;
}

```

# Answer
> 1 votes
Are you sure you have wired everything correctly? In particular:

* In most cases I have seen, the source of the problem was incorrect wiring of MOSI and SCLK. Do not trust the default constructor, better use the constructor that specifies the values of those pins.
* Check that the reset pin on your 9341 board is wired correctly.
* Power the 9341 with 5V; if you feed it 3.3V, the voltage regulator will not be able to supply a high enough voltage for the controller to work correctly.

You also haven't mentioned what you are running this on!

---
Tags: arduino-uno
---


title: DHT11 + ESP plus Arduino

text:
# Question
Title: DHT11 + ESP plus Arduino
Someone could help me? I want to use dht11 with arduino and esp. Both will read data from dht11 the problem is that simultaneously cannot be done. So the solution will be to set one as a master and the other one as a slave. the control will be done like so... another wire from arduino pin-\>set as output -\>esp pin-\>set as input. if wire == 1 then dht11 will be read by arduino if wire == 0 then esp will read dht. with some delay ofcourse. but the problem is that i dk how to stop the communication between one board and the sensor when the other board will read it. so does it not exist any conflict

# Answer
> 0 votes
**Disclaimer:**

I've never used an ESP chip based board I know almost nothing about them. I am going to assume that it works, in software terms, like an Arduino, and base my answer on Arduino code. If the esp chip works differently, you'll need to adapt my suggestion.

---

Try something like this:

Connect a GPIO line between the microcontrollers. Also connect that line - through a 10K resistor - to +5V.

Have both microcontrollers set up it's GPIO as an input.

(We'll call the GPIO pin on both microcontrollers the "DHT\_available" line. It will be HIGH when the DHT sensor is not being used by the other controller.)

When one of the microcontrollers wants to read the DHT11, have it check the GPIO line. If it's HIGH switch the GPIO line to an output and pull it low, then take a reading. When the reading is complete, switch the GPIO line back to an input.

If the GPIO line is LOW, wait and check again.

---

Alternately you could attach each of the microcontroller's GPIO lines to interrupt handlers on a rising edge. Then have the interrupt handler set the GPIO line to an output, pull it to LOW, and set a flag that means "begin reading".

Have your loop function check the "begin reading" flag, and if true, trigger a read from the DHT, and once it's complete, set the GPIO back to an input.

With the first option, each microcontroller would need to poll the "DHT\_available" line continuously until it goes HIGH before beginning reading.

With the second option, as soon as one of your microcontrollers is done taking a reading, it would stop pulling the communications line LOW, the other one's rising edge interrupt would fire, and the other one would immediately begin reading.

# Answer
> 1 votes
Also.. i would see a problem there. Lets say so.. Sensor data. Gnd. Vcc uC 2560 uC Esp If sensor data is linked to both uC And use a line dht\_available btween 2560 and esp to handle the uC reading.. then.. If dht\_available == HIGH then 2560 read after switch dht line to Low If dht\_available == LOW then esp read after reading dhtline》 HIGH But the sensor wil continue to send data to both.. regqrding the dhtline is high or low. I dk how to say to sensor.. if dhtline is LOW stop sending data to 2560 because is esp time to read.

---
Tags: temperature
---


# Question
Title: H Bridge for microcontroller power management?
Is it fine to use L298 N Dual H Bridge Stepper Motor Driver Module to control power of other ICs in a multiple microcontroller setup?

I intend to reduce power consumption in by powering communication ICs through the H bridge to allow switcching them off if not needed. Does a L298 based H bridge module like shown below supply clean stable DC current to someting like the ESP8266?

Module shown below contains condensators, i assume to reduce ripple effect created by L298.

# Answer
> 3 votes
While it *may* be possible to bend one of those to your proposed usage, it's far from ideal, for a number of reasons:

1. It's far more expensive than the single P-FET that you need to get the job done
2. It's risky: you can easily reverse the current through your components and blow them up
3. It imposes a ground offset which can cause you communication problems.

All you need is a single P-channel MOSFET (assuming you are switching 5V with a 5V logic signal) and a single resistor (10kΩ would be fine, but any large value is ok).

simulate this circuit – Schematic created using CircuitLab

Pull the GPIO LOW and the power switches on. As simple as that.

If you want to switch a higher voltage then simple use an N-channel MOSFET to pull the GPIO line LOW for you - which you then switch with your GPIO signal.

---
Tags: power, h-bridge
---


title: Arduino Pro Micro - switch off LEDs

text:
# Question
Title: Arduino Pro Micro - switch off LEDs
I am using a Arduino Pro Micro as a keyboard (USB HID device). Each time I press a key, the RX LED and TX LED light up. Can I switch them off in software?

# Answer
Kind of.

You don't have to change `pins_arduino.h`.
Try the `LED_BUILTIN_TX` and the `LED_BUILTIN_RX`.
The pins are turned on and off by the code for the SerialUSB port. That can not be changed without changing the Arduino libraries. Setting that pin to INPUT in your sketch in the setup() function will turn them off:

```
pinMode(LED_BUILTIN_TX,INPUT);
pinMode(LED_BUILTIN_RX,INPUT);

```

If you have troubles with the `LED_BUILTIN_TX` and the `LED_BUILTIN_RX`, then you can use this as well:

```
bitClear(DDRD,5);
bitClear(DDRB,0);

```

The code for the SerialUSB port still writes to that pin, but once they are set as INPUT, that code will turn on and off the pullup resistor. That is no problem since those leds are connected to VCC.

To turn them on is also possible, but then those pins needs to be OUTPUT and LOW. They will **not** stay on when the SerialUSB port is used.
> 6 votes

# Answer
Kind of.

You would need to edit the `pins_arduino.h` file for the Pro Micro board to change the definitions of the `TXLED0`, `TXLED1`, `RXLED0`, `RXLED1` and `TX_RX_LED_INIT` macros.

You want them to all be defined, but empty.

```
#undef TXLED0
#undef TXLED1
#undef RXLED0
#undef RXLED1
#undef TX_RX_LED_INIT

#define TXLED0
#define TXLED1
#define RXLED0
#define RXLED1
#define TX_RX_LED_INIT

```

That will remove the current definitions, and then create new empty definitions. Without the empty definitions, you will get errors when compiling.
> 2 votes

---
Tags: arduino-pro-micro
---


# Question
Title: FT232RL Chip pinout to flash Arduino Pro Mini
Looks I have a FTDI USB to TTL adapter that doesn't follow the standard Arduino FTDI pinout order. The chipset is FT232RL and here is the link to Amazon page.

https://www.amazon.com/Adapter-Serial-Converter-Development-Projects/dp/B075N82CDL#customerReviews

Please can someone tell me the right pinout to connect this to Arduino Pro Mini 3.3v Thanks!

# Answer
This is the standard FTDI Basic connections. CTS is an input to the module and is typically just connected to Gnd as seen on the right side here from the Arduino Promini schematic (so the FT232 is always Clear(ed) To Send, i.e. no flow control is used).

DTR may be broken out on one of the side holes. RTS may work for you in place of DTR to create the reset pulse to start the bootloader code. If not, you may have to cut the trace and wire the RTS header pin to DTR. DTR is pin 2 on the FT232, use a meter and confirm it goes to one of the side holes, that way you don't have to try a solder a wire on to a pin.
> 2 votes

---
Tags: arduino-pro-mini, ftdi
---


# Question
Title: Which pins are represented by these constants from ABR library?
The following code comes from AtTiny serial library that I want to use:

```
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// change these to use another pin
#define TX_PORT PORTB
#define TX_PIN  PB0
#define TX_DDR  DDRB
#define TX_DDR_PIN DDB0

```

I have no idea which pins to connect. What do these constants mean and where are they documented?

# Answer
> 1 votes
The mapping can be found in the io.h file but also in Arduino core files.

Below is the pin mapping:

```
                        ATtinyX4
                      +----U----+
  (VCC)-------------1-|VCC   GND|-14------------(GND)
  (D10)-------------2-|PB0   PA0|-13----------(D0/A0)
  (D9)--------------3-|PB1   PA1|-12----------(D1/A1)
  (/RESET)----------4-|PB3   PA2|-11----------(D2/A2)
  (D8)--------------5-|PB2   PA3|-10-------(D3/A3/SS)
  (D7/A7)-----------6-|PA7   PA4|-9---(D4/A4/SCL/SCK)
  (MISO/SDA/D6/A6)--7-|PA6   PA5|-8------(D5/A5/MOSI)
                      +---------+

```

The serial library uses:

```
#define TX_PIN  PB0

```

Which is `ATtinyX4 Pin #2`, or Arduino attiny core digital pin `D10` https://github.com/damellis/attiny/blob/master/variants/tiny14/pins\_arduino.h.

Cheers

---
Tags: attiny, uart, attiny13
---


# Question
Title: Is my Realtime Clock Locking Up My Arduino? If so, how would I solve it?
I am having a very strange issue with the realtime clock in Arduino that I cannot seem to solve. Basically, I have a program that logs data from a terrarium kit and saves each session to an SD card as a file named after the time the program started. 0

The problem with the program is that the code hangs on the statement before the setup section: “DateTime now = RTC.now().” The realtime clock appears to be functioning correctly with the example program which makes this issue even more strange. I am unsure if this is purely a software or hardware issue. From scouring the internet, I have found people with a similar problem to mine where the RTC will freeze up the i2c bus on the Arduino. However, I am unsure whether this is the issue plaguing me. If this is indeed the issue plaguing my program, unsure of how to work around it. I found an online solution here, however my program freezes upon launch so this would not work for me.

So far, I have tried: -Replacing the coin-cell battery in the realtime clock (I am using 3 volt batteries) -Replacing the datalogger shield with a new one -Replacing the Arduino with a new one -Checking to make sure that the jumpers were correctly soldered to the datalogger shield (Adafruit support checked mine through images and said they looked good)

I am running this program on IDE Version 1.6.9 with a program with the newer Adafruit datalogger shield on the Arduino Mega.

Any help would be greatly appreciated

```
//The libraries we need for our terrarium kit
//Download and install them all at this link:  https://drive.google.com/drive/folders/10XAFdYmnyz0dg9I6YYj80vJlHebFIZhN
#include <OneWire.h> //Import OneWire library
#include <DallasTemperature.h> //Import DallasTemperature library
#include <Adafruit_Sensor.h> //Import Adafruit Sensor library
#include <DHT.h> //Import first part of the DHT library
#include <TimerOne.h> //Import TimerOne library
#include <SPI.h>
#include <SD.h>  //this refers to an old SD library needed specifically for
#include "RTClib.h"  //this is from the rtc example folder code

//SD Card & Realtime Clock: Initialization
File logfile;
RTC_DS1307 RTC;

//Humidity Sensor: Constants
//This #define defines the pin that the DHT is plugged into
#define DHT_PIN 2
//This #define defines the type of the DHT
#define DHT_TYPE DHT22
//This tells the code that a DHT is plugged into port DHT_PIN and the DHT is of type DHT_TYPE
DHT dht(DHT_PIN, DHT_TYPE);

//Moisture Sensor: Variables
int MS_sigPin = A5; //Set the signal pin as analog pin 5
int MS_digPin = 7; //Set the digital pin as 2
float MS_upper = 0; //Declare highest value variable

//Other variables
int measurementNumber = 1; //Number of measurements taken

//Filename:
  DateTime now = RTC.now(); //Initialize the RTC
//  String seconds = (String)(now.second());  //Stores the seconds from the RTC upon setup as a string
 const String minutes = (String)(now.minute()); //Stores the seconds from the RTC upon setup as a string
 const String hours = (String)(now.hour());  //Stores the seconds from the RTC upon setup as a string
 const String days = (String)(now.day());  //Stores the seconds from the RTC upon setup as a string
 const String months = (String)(now.month());  //Stores the seconds from the RTC upon setup as a string
 const String years = (String)(now.year());  //Stores the seconds from the RTC upon setup as a string
 const String filename = "D_" + minutes + hours + days + months + years; //Create the file name as a timestamp

void setup() {

  int chipSelect = 10; //chipSelect pin for the SD card

  // put your setup code here, to run once:
  Serial.begin(115200); //Set the baud rate at 56700
//If RTC is already updated, the below is commented out
  RTC.begin();
  RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));//this is to force rtc update
//  if (!RTC.isrunning()) {
//
//    Serial.println("RTC is NOT running! Starting it now.");
//    RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
//
//  }// end rtc if

//{
//The below is copied from wired, contains a second try, hoping for sd success herein.
 pinMode(chipSelect, OUTPUT);
 digitalWrite(chipSelect, HIGH);
 SD.begin(chipSelect);
//  if (!SD.begin(10, 11, 12, 13)) {
//    Serial.println("Card failed, or not present");
//    delay(50);
//    Serial.println("Trying again...");
//    if (!SD.begin(50, 51, 52, 53)) {
//      Serial.println("Card failed, or not present");
//    }
//  }

 /******************************** CSV FORMAT ******************************/

//  Serial.print("Current Position: ");
//  Serial.println(logfile.position());
  if(logfile.position() == 0)//Below print header line for datafile
  logfile.println("Unix Time, Date, Time, Light, Humidity, Temperature");
  //logfile.println("uni,date,time,Temperature");

  /**************************************************************************/

//  sensors.begin();
//  sensors.setResolution(12);

  //Humidity Sensor:
   dht.begin();

  //Moisture Sensor:
  pinMode(MS_sigPin, OUTPUT); //Set the signal pin as an output
  pinMode(MS_digPin, OUTPUT); //Set the digital pin as an output
  digitalWrite(MS_digPin, HIGH); //Turn the digital pin on

  Serial.println("DIP THE MOISTURE SENSOR IN A CUP OF WATER MAKING SURE NOT TO SUBMERGE THE TOP OF IT INTO THE WATER, ENTER IN ANY KEY WHEN YOU ARE READY TO CALIBRATE"); //Print out useful information
  while (Serial.available() == 0) //Hang the program until the user inputs a key to continue
  {

  }
  Serial.println("Starting Calibration"); //Print out useful information
  Timer1.initialize(1000000); //Initialize an interrupt every 1 second
  Timer1.attachInterrupt(Calibrate); //When the interrupt is called run the “Calibrate” function

}
//Calibrate the moisture sensor
void Calibrate() //Function to calibrate the sensor
{
if (analogRead(MS_sigPin) > MS_upper) //If the value read by the sensor is higher than the past highest value
{
 MS_upper = analogRead(MS_sigPin); //Set the current value as the new highest value
  }
}

void loop() {

//Photocell: Variables
int photocellPin = A0; // the cell and 10K pulldown are connected to a0

  char fileCharStorage[(filename.length()+5)]; //+4 Characters to include ".csv"
  filename.toCharArray(fileCharStorage, filename.length()+5);
  fileCharStorage[filename.length()] = 'V'; //Set the file name
  fileCharStorage[filename.length()-1] = 'S'; //Set the file name
  fileCharStorage[filename.length()-2] = 'C'; //Set the file name
  fileCharStorage[filename.length()-3] = '.'; //Set the file name
  Serial.println(filename); //Print out the filename
  Serial.println(sizeof(fileCharStorage)); //Print the length of the array storing the file name
  logfile = SD.open(fileCharStorage, FILE_WRITE);  //Creates (or opens) a file names "MMHHDDMMYYYY.CSV"

  if (logfile)
  {
    Serial.println("The SD Card is functioning properly");
  }
  else
  {
    Serial.println("A Critical Error occured while trying to initialize the SD Card!");
  }
  //Realtime Clock
  DateTime now = RTC.now();

 //Photocell:
 int photocellReading = analogRead(photocellPin); //Variable that stores the amount of light detected by the photocell as an integer

  // This code gets the humidity from the DHT
  float dhtHumidity = dht.readHumidity();
  /*
  This code gets the temperature from the DHT
  */
  float dhtTemperature = dht.readTemperature();

  Serial.println(""); //Text Formatting
  Serial.println("Starting New Measurement (" + (String)measurementNumber + ")");
  Serial.println(""); //Text Formatting
  delay(1000);

  //Print out data from the number of measurements taken
  Serial.println("The Arduino has been active for " + (String)((measurementNumber*10)-10) + " seconds");
  measurementNumber++;

  //Print out data from the RTC
    Serial.print("Unix Time (Seconds since 1/1/1970): ");
    Serial.print(now.unixtime()); // seconds since 1/1/1970
    Serial.println(", ");
    Serial.print("RTC time: ");
    Serial.print(now.month(), DEC);
    Serial.print("/");
    Serial.print(now.day(), DEC);
    Serial.print("/");
    Serial.print(now.year(), DEC);
    Serial.print(",");
    Serial.print(now.hour(), DEC);
    Serial.print(":");
    Serial.print(now.minute(), DEC);
    Serial.print(":");
    Serial.print(now.second(), DEC);
    Serial.println("");
    Serial.println("");

  //Photocell:
  Serial.println("Data from the photocell:");
  Serial.print("Analog reading = ");
  Serial.print(photocellReading); // the raw analog reading

  if (photocellReading < 10) {
  Serial.println(" - Dark"); //says that if any number is lower than 10 then it prints out dark.
  } else if (photocellReading < 200) {
  Serial.println(" - Dim"); //says that if any number is lower than 200 then it prints out dim.
  } else if (photocellReading < 500) {
  Serial.println(" - Light"); //says that if any number is lower than 500 then it prints out light.
  } else if (photocellReading < 800) {
  Serial.println(" - Bright"); //says that if any number is lower than 800 then it prints out bright
  } else {
  Serial.println(" - Very bright"); //says that if any number higher than 800 then it prints out very bright
}
  Serial.println("");

// Humidity Sensor:
  Serial.println("Data from the humidity sensor:");
  Serial.print("Humidity: ");
  Serial.print(dhtHumidity);
  Serial.print(" %, Temp: ");
  Serial.print(dhtTemperature);
  Serial.println(" Celsius");
  Serial.println("");

  //Moisture Sensor:
  Serial.println("Data from the moisture sensor:");
  float percent = (analogRead(MS_sigPin)/MS_upper)*100; //Calculate moisture percentage
  Serial.println("Moisture = " + (String)percent + "%"); //Print out the moisture percentage

  Serial.println("");
  Serial.println("--------------------------------------------------");

    //Log everything onto the SD card
    logfile.print(now.unixtime()); // seconds since 1/1/1970
    logfile.print(", ");
    logfile.print(now.month(), DEC);
    logfile.print("/");
    logfile.print(now.day(), DEC);
    logfile.print("/");
    logfile.print(now.year(), DEC);
    logfile.print(",");
    logfile.print(now.hour(), DEC);
    logfile.print(":");
    logfile.print(now.minute(), DEC);
    logfile.print(":");
    logfile.print(now.second(), DEC);
    logfile.print(", ");
    logfile.print(photocellReading);
    logfile.print(", ");
    logfile.print(dhtHumidity);
    logfile.print(", ");
    logfile.print(dhtTemperature);
    logfile.println();
    logfile.close();
//  Delay by 1+9 (10) seconds between measurements
  delay(9000);
}

```

# Answer
I'm guessing that you can't call `RTC.now()` before setup like that.

It would be helpful if you told us what RTC you were using, and provided a link to the library you were using for it.

At a guess, since I don't have that info, you should probably change the declaration like this:

```
  //Filename:
  DateTime now;

```

And then in your `setup()`:

```
RTC.begin();

if (!RTC.isrunning()) {
  Serial.println("RTC is NOT running! Starting it now.");
  RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
} // end rtc if
now = RTC.now(); //Initialize the RTC

```
> 2 votes

---
Tags: arduino-mega
---


title: Reading text line by line from SD

text:
# Question
Title: Reading text line by line from SD
Why does the following code return this error? How can I make this work?

> Error: exit status 1 invalid conversion from 'const char\*' to 'char' \[-fpermissive\]

```
#include "FS.h"
#include "SD.h"
#include "SPI.h"

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

  if (!SD.begin(33)) {
    Serial.println("Card Mount Failed");
  } else {
    Serial.println("Card Mount Succeeded");
  }

  File offline = SD.open("/offlineLog.txt", FILE_READ);

  while (offline.available()) {
    String line = offline.readStringUntil("\n");
    Serial.println(line);
  }
}

```

The docs say that stream.readStringUntil returns a string...

# Answer
> 2 votes
The error has nothing to do with what `readStringUntil` returns. It has to do with what parameters it accepts.

The function expects a *single character* to look for. Instead you are passing it a string (C string) containing one character.

In C you represent a string (`char *`) using `""`, and a single character (`char`) using `''`.

Since `readStringUntil` expects a `char`, not a `char *`, you need to use `''`:

```
String line = offline.readStringUntil('\n');

```

---
Tags: programming, esp32
---


title: How to parse 20180810T143000Z to time_t

text:
# Question
Title: How to parse 20180810T143000Z to time_t
What is the shortest/most elegant way (i.e. use existing lib functions) to parse a string in the form of `20180810T143000Z` to a `time_t`? Note that the literal always represents a UTC timestamp.

I started parsing the string and assigning values to a `struct tm *tm` in order to do a `mktime(tm)` at the end. That feels overly complicated, though.

# Answer
Parsing the string really is the only way. However there are many ways of doing it.

My preferred method is to first check that the format is correct, by looking for the T and Z being in the right place:

```
if (timeString[8] == 'T' && timeString[15] == 'Z') {
    ... parse in here
}

```

And the parsing is just making numbers with multiplication:

```
int year = (timeString[0] - '0') * 1000 +
           (timeString[1] - '0') * 100 +
           (timeString[2] - '0') * 10 +
           (timeString[3] - '0');

```

You can clean things up with a macro if you like:

```
#define NUM(off, mult) ((timeString[(off)] - '0') * (mult))

```

Then:

```
int year =   NUM(0, 1000) + NUM(1, 100) + NUM(2, 10) + NUM(3, 1);
int month =  NUM(4, 10)   + NUM(5, 1);
int day =    NUM(6, 10)   + NUM(7, 1);
int hour =   NUM(9, 10)   + NUM(10, 1);
int minute = NUM(11, 10)  + NUM(12, 1);
int second = NUM(13, 10)  + NUM(14, 1);

```

And then, yes, put them in a `struct tm` (or directly assign them calculation results without using the intermediate variables) and call `mktime()`.
> 4 votes

# Answer
```
#include <Time.h>

void setup() {

  Serial.begin(115200);

  char buff[] = "20180810T143000Z";
  for (int i = 0; i < sizeof(buff); i++) {
    buff[i] = buff[i] - '0';
  }
  int yr = buff[0] * 1000 + buff[1] * 100 + buff[2] * 10 + buff[3];
  if (yr > 99)
    yr = yr - 1970;
  else
    yr += 30;
  TimeElements tm;
  tm.Year = yr;
  tm.Month = buff[4] * 10 + buff[5];
  tm.Day = buff[6] * 10 + buff[7];
  // 8 T
  tm.Hour = buff[9] * 10 + buff[10];
  tm.Minute = buff[11] * 10 + buff[12];
  tm.Second = buff[13] * 10 + buff[14];

  time_t t = makeTime(tm);

  sprintf(buff, "%02d%02d%02d %02d%02d%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));

  Serial.println(buff);

}

void loop() {

}

```

You can install TimeLib in Library Manager. It works on all Arduino platforms.
> 2 votes

# Answer
Here is yet another way to convert the time stamp string to time\_t. There are several great answers here already, but you may want to compare binary file sizes. This sketch's is 3884 bytes (IDE Version 1.0.6.2, GCC 4.2.1).

```
#include <Time.h>
TimeElements myTimeElements;
char timeString[] = "20180810T143000Z";

void setup(){

  Serial.begin(9600);

  myTimeElements.Year = CalendarYrToTm((timeString[0] - '0') * 1000 + (timeString[1] - '0') * 100 + (timeString[2] - '0') * 10 + (timeString[3] - '0'));
  myTimeElements.Month = (timeString[4] - '0') * 10 + (timeString[5] - '0');
  myTimeElements.Day = (timeString[6] - '0') * 10 + (timeString[7] - '0');
  myTimeElements.Hour = (timeString[9] - '0') * 10 + (timeString[10] - '0');
  myTimeElements.Minute = (timeString[11] - '0') * 10 + (timeString[12] - '0');
  myTimeElements.Second = (timeString[13] - '0') * 10 + (timeString[14] - '0');

  // Assemble time elements into time_t.
  time_t t = makeTime(myTimeElements);

  // Print out the contents of "t" one "piece" at a time using the "time_t" functions.
  Serial.println(year(t));
  Serial.println(month(t));
  Serial.println(day(t));
  Serial.println(hour(t));
  Serial.println(minute(t));
  Serial.println(second(t));

}

void loop(){}

```
> 2 votes

# Answer
For the sake of completeness here's my "answer" working with `String`s rather than `char[]`.

```
time_t convertToTime(String calTimestamp) {
  struct tm tm;
  Serial.println("Parsing " + calTimestamp);
  String year = calTimestamp.substring(0, 4);
  String month = calTimestamp.substring(4, 6);
  if (month.startsWith("0")) {
    month = month.substring(1);
  }
  String day = calTimestamp.substring(6, 8);
  if (day.startsWith("0")) {
    month = day.substring(1);
  }
  tm.tm_year = year.toInt() - 1900;
  tm.tm_mon = month.toInt() - 1;
  tm.tm_mday = day.toInt();
  tm.tm_hour = calTimestamp.substring(9, 11).toInt();
  tm.tm_min = calTimestamp.substring(11, 13).toInt();
  tm.tm_sec = calTimestamp.substring(13, 15).toInt();
  return mktime(&tm);
}

```
> 1 votes

# Answer
This is not complete without sscanf.

I took the sketch by @Juraj and declared seperate integers to be sure that every %d would match with an integer.

```
#include <Time.h>

void setup() {

  Serial.begin(115200);

  char buff[] = "20180810T143000Z";

  TimeElements tm;

  int yr, mnth, d, h, m, s;
  sscanf( buff, "%4d%2d%2dT%2d%2d%2dZ", &yr, &mnth, &d, &h, &m, &s);

  tm.Year = yr - 1970;
  tm.Month = mnth;
  tm.Day = d;
  tm.Hour = h;
  tm.Minute = m;
  tm.Second = s;

  time_t t = makeTime(tm);

  sprintf(buff, "%02d-%02d-%02d %02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));

  Serial.println(buff);
}

void loop() {
}

```

Marcel Stör, there are now four good solutions. In my opinion they are equally good.
> 1 votes

# Answer
Alternative to my first answer would be to use standard C functions from time.h and sscanf. C function strptime can't parse the timestamp without delimiters. But sscanf can parse your input.

```
#include <time.h>

void setup() {

  Serial.begin(115200);

  const char* buff = "20180810T143000Z";

  tm tms;
  sscanf(buff, "%04d%02d%02dT%02d%02d%02d", &(tms.tm_year), &(tms.tm_mon), &(tms.tm_mday), &(tms.tm_hour), &(tms.tm_min), &(tms.tm_sec));
  tms.tm_year -= 1900;
  tms.tm_mon -= 1;
  tms.tm_isdst = 0;
  time_t t = mktime(&tms);

  Serial.println(ctime(&t));
}

void loop() {
}

```

In AVR "%02hhd" must be used because the corresponding members in struct tm are int8\_t.
> 1 votes

# Answer
```
String datetimestr = "20180810T143000Z";
int splitted = datetimestr.indexOf("T");
String datestr = datetimestr.substring(0, splitted); //20180810
String timestr = datetimestr.substring(splitted + 1, datetimestr.length() - 1); //143000

```
> 0 votes

---
Tags: esp8266, c, time
---


# Question
Title: Is there an open source compiler for Arduino Sketch codes?
I am working on a web app to program some nodeMCU devices that were flashed with the arduinoOTA library.

http://esp8266.github.io/Arduino/versions/2.0.0/doc/ota\_updates/ota\_updates.html

I tried the example and the OTA upload of the binary file compiled from Arduino IDE works.

Let's say my web app will allow user to code in Sketch, is there any open source server side or client side compiler that can compile the Sketch code into the bin file?

# Answer
> 1 votes
Just have a look here https://github.com/arduino/Arduino/wiki/Build-Process to understand the process.

In fact Arduino code is not "C or C++" at 100%. You can't compile directy as some informations are missing. This is why when you "compile" with the IDE, it copies the files in a temp folder, add some lines at beginning of theses files and then call the basic and well known avr-gcc. If you have a dedicated server you just have to search for the avr-gcc package according to the OS. Eg, for Debian: https://packages.debian.org/stretch/gcc-avr

Then or you send directly the code avr-gcc is waitng for, or you apply on the code the same changes the IDE is doing before sending the code to GCC.

Hope this help

# Answer
> 0 votes
Arduino IDE runs external tools to create the hex or bin file. First the ino files of a project are processed by arduino builder to cpp file. Then the arduino builder invokes the toolchain of the MCU architecture - compiler and linker. For example AVR tools for 328p or 2560; ARM toolchain from SAMD; xtensa tools for Espressif chips.

New is Arduino CLI, which focuses on using Arduino with command line.

Tha Arduino builder, Arduino CLI and esp8266 Arduino core are Open Source. Extensa tools and Espressif SDK are not open source, but are free.

# Answer
> 0 votes
Try PlatformIO: https://platformio.org

Opensource and cross platform.

---
Tags: nodemcu, sketch, compiler
---


# Question
Title: Problem with arduino starter kit project 7
Can someone pls help me only the two buttons clossest to the big green wire work and i don^t know why i have already tried swapping buttons

EDIT 1: my code

and i know the first two are working because they generate a tone with the piezo the third one does nothing and the last one only makes static noises

# Answer
> 0 votes
~~I see the problem. The connections to the first 2 buttons are correct. You're missing a yellow wire linking the output of the bottom 2 buttons to AO however, so the 3rd and 4th buttons are not connected to your A0 pin at all. Add a yellow wire between row 24 and row 20 on your breadboard.~~

## EDIT:

I see now that there is a green wire connecting rows 24 and 20 together. However, that is the likely place where things go wrong. I would suggest taking a couple of jumpers and connecting them to a multimeter set to continuity mode. Put one in row 28, and then test continuity to row 24, row 20, and row 16.

One of your wires may not be seated into the breadboard properly, or you may even have a bad row on your breadboard. I've seen that before.

## EDIT #2:

A multimeter is your friend. If you don't have one, you should get one, and learn how to use it. It's invaluable for troubleshooting circuits. (Get one that has a continuity mode that beeps when it detects continuity, and that has auto-ranging voltage and resistance measurements.)

---
Tags: arduino-uno, electronics
---


# Question
Title: How do you combine 2 different sketches together
(Before you down-vote this, note that it is a "ringer" to answer a FAQ, with a self-answer.)

This question comes up all the time. How do you combine 2 different sketches together? Say I have a sample sketch for a DTH temp/humidity sensor and another sketch for a LCD sensor. How do I combine them?

# Answer
This question comes up all the time. I'll explain what you need to do in general terms. Try it, and if you have problems, post a question showing your 2 starting sketches, your attempt at combining them, and detailed info on what goes wrong.

There are 3 basic parts to the main.ino file of an Arduino sketch:

1. The declarations:

* `#includes`
    * `#defines`
    * global variables
2. The `setup()` function
3. The `loop()` function.

You need to merge those parts separately.

1. You should merge the subsections of the declarations together (Put all the `#includes` together, all the `#define`s together, and all the global variables together. Remove any duplicate `#include`s.

If there are any duplicate `#define`s or global variables, you need to figure out how to resolve that. If the symbol and the name are the same

2. The same applies to the two `setup()`-functions you want to merge. Also, duplicate parts usually need to be there only once (considering things like `Serial.begin(...)`).
3. Also the two `loop()`s are combined the same way, but if you make use of `delay()`s you must keep in mind that these will sum up in the final sketch, making it slower than the initial sketches were. It might also might (probably won't) work correctly. You will likely need to refactor your code to use millis() instead of `delay()`.

After combining two sketches this way your global variables will be shared. You'll need to resolve any naming conflicts, or rename global variables that are different in your source sketches but should be the same. You may also have shared resources like sensors and LCD displays.

(Note that if the 2 sketches use the same resource for different things it gets more complicated, e.g. using the same pin for different purposes, using the same timer in both sketches, or using the same interrupt. Those things will require analysis and case-by-case changes.)
> 7 votes

---
Tags: programming
---


# Question
Title: Wanted to control 2 servos with serial read
I want to use 2nd servo only when 1st is in up state by asking user whether he wants to fire or not.(code in bold is not working )

```
#include <Servo.h>

    Servo myservo;
    Servo trigervo;
    int pos = 0;
    int u = 0, p = 0, t = 0;
    int incomingByte = 0; // for incoming serial data

    void setup() {
      Serial.begin(9600);
      myservo.attach(9);
      trigervo.attach(10);
      pinMode(13, OUTPUT);
      myservo.write(0);
    }

    void loop() {
      if (Serial.available() > 0) {
        // read the incoming byte:
        incomingByte = Serial.read();
        Serial.print("I received: ");
        if (incomingByte == 111 && u == 0) {
          for (pos = 0; pos <= 80; pos += 1) {
            myservo.write(pos);
            delay(5); //
            digitalWrite(13, HIGH);
          }
          u = 1;
          p = 0;
          Serial.println(incomingByte, DEC);
          Serial.print("Want to Shoot? \n");
          Serial.print("1\n");
          ***t = Serial.read(); // from here
          if (t == 107) {
            Serial.print("2\n");
            trigervo.write(60);
            trigervo.write(0);
          } // to here, it is not working***
        } else if (incomingByte == 102 && p == 0) {

          for (pos = 100; pos >= 0; pos -= 1) {
            myservo.write(pos);
            delay(7);
            digitalWrite(13, HIGH);
          }
          u = 0;
          p = 1;
          Serial.println(incomingByte, DEC);
        }
        Serial.println(incomingByte, DEC);

      }
    }

```

# Answer
Without knowing, what exactly you want it to do (since you didn't tell us), I see 2 problems in your code:

1. The code around the line marked with "from here" will ask the user over Serial, if he wants to shoot, but directly after it, it will read a value, without waiting for the user to input something. `Serial.read()` will not wait for data to arrive, it will just return -1 if nothing is in the buffer. You have to check, if there is actually something in the buffer with `Serial.available()` and only proceed, if there is actually data to read.
2. In the following if-statement, you first write the value 60 to the servo and directly after it, without any delay, the value 0. The servo doesn't have enough time to get to 60 - or to even start to move - before you tell him to go to 0. The servo needs time for movements.

---

Apart from the specific problems with your code, I would use a finite state machine (FSM), to implement it, instead. You declare a global state variable, which represents the possible states, in which your machine can be. If I assume some type of gun/shooting device, these states could be `ASK_USER_TO_POSITION_GUN' and 'ASK_USER_TO_SHOOT'. In each state you check the Serial interface (first with` Serial.available()`then reading with`Serial.read()\` if it returns something greater than 0) and based on that input you first take the appropriate action and then do the state transition, by changing the state variable.

As example of the general structure:

```
int state = 0;

void loop(){
    switch(state){
        case 0:
            if(Serial.available()>0){
                int input = Serial.read();
                //take appropriate action
                state = 1; //do state transistion
            }
            break;
        case 1:
            if(Serial.available()>0){
                int input = Serial.read();
                //take appropriate action
                state = 0; //do state transition
            }
            break;
    }
}

```

Depending on the exact actions to do, you can also tune this, by reading Serial outside of the switch statement and in the case statement only check the input variable. In this case reset the input variable after every interaction.

EDIT: For giving a better explanation about finite state machines, I've drawn a graphical representation of the states. Mostly it is way easier to code, when you first have drawn such a graph to visualize the codes functionality. Note, that this is the logic from your code. You may want it to work another way, but this is beyond the scope and only for understanding. Also note the different numbers of the states than I used above, which I only change, because I needed more states.

See first this graph:

We begin in state 0, where we are waiting for user input through serial. If we go some input, we make a decision: If the value is 111, we will transition to the next state (state 1) to position the gun, else we will wait again for more input. In stage 1, we are positioning the gun and go directly to state 2. There we are again waiting for user input. If we received something, we will again make a decision: On the value 107 we will do the transition to state 3 to shoot, else we will go to state 0, to ask again for positioning, like we did before. In state 3 we are shooting and directly go to state 0 again. This is rather strict division into states.

Since in state 1 and 3 we are only doing a short action and then going directly to another state, we might cut those states away, implementing the corresponding code in the transition from state 0 to 2 and vice versa. This is the logic from my FSM code example above (action together with transition). The graph would look like this:

Which version you should implement depends on other factors. If you are OK with the action code to be blocking, you can implement version 2, since it has less states. If you want to write the action in a non-blocking style, you might find version 1 easier to implement.
> 1 votes

---
Tags: arduino-uno, serial, arduino-ide, servo, communication
---


title: Question about a code

text:
# Question
Title: Question about a code
This code is used to toggle an arduino on and off , the problem is that i can't comprehend it at all. can someone explain to me how does it work ?

```
New = digitalRead(button);
  if ( New!=old)
  {
    if ( New == HIGH ){
      if (LEDstatus == LOW)
    {  digitalWrite(LED,HIGH);
    LEDstatus = HIGH;
    }
    else
    {
      digitalWrite(LED,LOW);
      LEDstatus=LOW;
    }
    }
    old=New;
  }

```

# Answer
First, fix the indentation:

```
New = digitalRead(button);
if ( New!=old) {                        // If the button state has changed
    if ( New == HIGH ) {                // If the button is now in the pressed state
        if (LEDstatus == LOW) {         // If the LED was off
            digitalWrite(LED,HIGH);     // Turn the LED on
            LEDstatus = HIGH;           // Remember the LED state for next time
        } else {                        // The LED was on, so turn it off
            digitalWrite(LED,LOW);
            LEDstatus=LOW;              // Remember the LED state for next time
        }
    }
    old=New;
}

```

That makes the code a whole lot easier to understand.

It only does something when the button is pressed (switches to HIGH state). It doesn't do anything when you release the button.

Each button press changes the state of the LED.

if it was off, it turns it on. If it was on, it turns it off.
> 1 votes

---
Tags: arduino-uno
---


title: Does bool return an int?

text:
# Question
Title: Does bool return an int?
I know that for the Arduino (and C in general) that for comparison sake, "false" is 0, while any non-zero integer is "true". The question that I have is does the bool data type "return" a concrete integer for "true" or "false"?

When I tried `Serial.print(true == 1)`, it printed `1` (which I assumed to be "true"), but when I tried `Serial.print(true == 2)`, it printed `0` (which I assumed to be "false"). When I tried `Serial.print(false == 1)`, it printed `0` and `Serial.print(false == 0)` printed a `1`.

I didn't know if "true" always evaluated to 1 and "false" always evaluated to 0, or if this is not supposed to happen.

# Answer
> 1 votes
If you look at `Arduino.h`, you'll see `true`, `false` and `bool` defined as:

```
#define true 0x1
#define false 0x0
typedef uint8_t boolean;

```

Using a simple test sketch, it appears that comparing `true` or `false` to anything besides a 1 or 0 does not "work".

```
void setup(){

  Serial.begin(9600);

  if(false == 0){Serial.println("false=0");}
  if(false == 1){Serial.println("false=1");}
  if(false == 2){Serial.println("false=2");}
  if(false == -1){Serial.println("false=-1");}
  if(true == 0){Serial.println("true=0");}
  if(true == 1){Serial.println("true=1");}
  if(true == 2){Serial.println("true=2");}
  if(true == -1){Serial.println("true=-1");}

}

void loop(){}

```

# Answer
> 0 votes
true is indeed 1, and false is 0.

This follows your tests:

```
(true == 1) -> prints 1, because 1 == 1
(true == 2) -> prints 0, because 1 != 2
(false == 1) -> prints 0, because 0 != 1

```

In C true and false are defines and a bool/boolean is a typedef (mostly to an int, unsigned int or unsigned char), where normally false is defined to 0 and true to 1 OR 255. So you cannot rely on a specific value.

In C++ the values of true and false are resp. 1 and 0, when casted to an int.

# Answer
> 0 votes
A 'bool' is defined data type based on (and identical to) an int. It's reason for existence is documentary: it's name describes how you intend to use it. There is no other difference.

'true' and 'false' are the constants 1 and 0, respectively. If you assign 'true' to a bool or any other integer type, it will get the value '1'. If you make a comparison or any other logical test (one that evaluates to true or false), that test results in a numerical value, either 1 or 0.

However you *can* evaluate (i.e. test) any integral value logically (true or false): if it is equal to zero the result will be false (0); otherwise the result will be true (1) - no matter what non-zero value the expression itself has. That is because the logical operators, '==', '!=', '\>', etc., are (similar to) functions which can only return one of two values 'true' and 'false', regardless of the values of their inputs. That is another meaning of the bool datatype: when it is applied to a function, it implies to the compiler and to the reader that this function returns either true or false.

---
Tags: programming
---


# Question
Title: Send big amouts of data to PHP script via gsm module SIM800L
I'm looking for a way to get lots of sensory data from my Arduino Micro to a PHP script. My current attempt is using the following AT-commands:

```
Sent: [AT+HTTPPARA=URL,www.example.com/newData.php?data=t0_20.75,l_0.00,m_584,h_42,td_22,d_21x44x54]
Res: [AT+HTTPPARA=URL,www.example.com/newData.php?data=t0_20.75,l_]

```

As you can see I send a long GET-parameter to my server with shortened parameter Names like t0 for temperature sensor number zero, l for light and so on.

In the response from my **SIM800l** I get back a string with exactly 63 characters, so I assume there's some lenght limitation there on the SIM-module.

After that command when it tries to finish the HTTP request I get a lot of errors as AT-command responses and no GET data arrives on my script.

---

I check wheter or not data has arrived with the following function on my server:

```
ob_start();
echo "Var_dump of GET\n";
var_dump($_GET);

echo "Var_dump of POST\n";
var_dump($_POST);
$vd_res = ob_get_clean();

file_put_contents('postdump.log', $vd_res."\n",FILE_APPEND);

```

When typing some data directly into the browser it saves my sent data in postdump.log so I'm pretty sure the SIM-module can't handle the given amount of data.

Do you have any idea how I can send bigger amounts of data all at once? For energy saving purposes I would prefer if it would be possible in only a single request.

# Answer
> 2 votes
> Do you have any idea how I can send bigger amounts of data all at once? For energy saving purposes I would prefer if it would be possible in only a single request.

Do a POST request. You can send huge amounts of data in the body.

> In the response from my SIM800l I get back a string with exactly 63 characters, so I assume there's some lenght limitation there on the SIM-module.

Nope.

I guess you're doing something like:

```
sendCommand("AT+HTTPPARA=URL,www.example.com/newData.php?data=t0_20.75,l_0.00,m_584,h_42,td_22,d_21x44x54");
delay(1000);
printResponse();

```

The problem there is that you're relying on the internal buffer of `SoftwareSerial` (or `HardwareSerial` if you use a real serial port). You wait for a predefined time for characters to arrive, and then after that time print them out. The serial code has a 64 byte buffer.

I see that kind of code all over the place, and it's the worst possible way of reading serial. Whoever posted the first instance of such code and started this chain of evil should be taken outside and shot.

Instead you must read the serial *properly*. Being lazy like that doesn't work.

Read this blog post to learn more about reading serial data properly.

---
Tags: communication, gsm, arduino-micro, signal-processing
---


# Question
Title: Issue with Indenting the Serial Print data in the Serial Monitor
I have a question with Serial Print. I want the Sensor reading values to fall under 3 columns, and each column should have the readings from the same sensor.

Raw Value | Sensor 1 | Sensor 2 | Sensor 3

how can I modify this code do this?

Below I have posted my code and what I currently see using the Serial Monitor

```
    void loop(){

  RawValue0 = analogRead(analogIn0);
  Voltage0 = (RawValue0 / 1023.0) * 5000; // 5000 to get millivots.
  tempC0 = (Voltage0-500) * 0.1; // 500 is the offset
  tempF0 = (tempC0 * 1.8) + 32; // conver to F
  Serial.print("Raw Value = " );  // shows pre-scaled value
  Serial.print(RawValue0);
  Serial.print("\t milli volts = "); // shows the voltage measured
  Serial.print(Voltage0,0); //
  Serial.print("\t Sensor 1: Temperature in C = ");
  Serial.print(tempC0,1);
  Serial.print("\t Sensor 1: Temperature in F = ");
  Serial.println(tempF0,1);
  delay(500);

```

# Answer
Columns with lines?

The `sprintf` function can fill data with spaces to align them. However, the Arduino `sprintf` function does not support floating point variables. The `dtostrf` function has already a fixed output width by itself.
The sketch below is a combination of UTF-8 characters and the `dtostrf` and `sprintf` functions.

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

  Serial.println();
  Serial.println("┏━━━━━━┳━━━━━━━━┳━━━━━━━━┓");
  Serial.println("┃  raw ┃   °C   ┃   °F   ┃");
  Serial.println("┣━━━━━━╋━━━━━━━━╋━━━━━━━━┫");
}

void loop() {
  int raw = random(0, 1024);
  float c = random(-1000, 1000) / 10.0;
  float f = random(-500, 1500) / 10.0;

  char buffer_c[20];
  char buffer_f[20];

  dtostrf(c, 6, 1, buffer_c);
  dtostrf(f, 6, 1, buffer_f);

  char buffer[80];
  sprintf(buffer, "┃ %4d ┃ %s ┃ %s ┃", raw, buffer_c, buffer_f);
  Serial.println(buffer);

  delay(500);
}

```

---

The strlen() function can not be used before printing a floating point number to the serial port, since its length is determined while printing characters to the serial port. The final number of bytes that is written is the return value.
There is a way to use that return value, by using a dummy write to a dummy serial port. After that the number of spaces to align the floating point number can be calculated.

That reduces the code size from 6160 to 4708 for an Arduino Uno.

```
class DummyClass : public Stream
{
  int available() {return 0;}
  int read() {return 0;}
  int peek() {return 0;}
  void flush() {return;}
  size_t write(uint8_t) {return 1;}
  using Print::write;
};

DummyClass Dummy;

const int width_r = 4;
const int width_c = 6;
const int width_f = 6;

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

  Serial.println();
  Serial.println("┏━━━━━━┳━━━━━━━━┳━━━━━━━━┓");
  Serial.println("┃  raw ┃   °C   ┃   °F   ┃");
  Serial.println("┣━━━━━━╋━━━━━━━━╋━━━━━━━━┫");
}

void loop() {
  int raw = random(0, 1024);
  float c = random(-1000, 1000) / 10.0;
  float f = random(-500, 1500) / 10.0;

  int i;
  Serial.print("┃ ");
  Spaces(width_r - Dummy.print(raw));
  Serial.print(raw);
  Serial.print(" ┃ ");
  Spaces(width_c - Dummy.print(c,1));
  Serial.print(c,1);
  Serial.print(" ┃ ");
  Spaces(width_f - Dummy.print(f,1));
  Serial.print(f,1);
  Serial.print(" ┃");
  Serial.println();

  delay(500);
}

void Spaces(int n)
{
  for(int i=0; i<n; i++) {
    Serial.print(' ');
  }
}

```

I advise not to use this "Dummy" trick. It is mere a coding exercise. I can not find a problem with this trick, but I'm not 100% sure that it is okay.
> 2 votes

# Answer
Here is a sketch that uses a different approach than Jot uses in his answer. There is no question that Jot's answer is excellent and takes very few lines of code to accomplish.

I thought it would look nice if the Raw Value, an integer, was centered under the "Raw Value" column when it was at it's maximum value of 1023. A value of 1 would be right-ish justified, but still aligned with the center in mind.

The floating point numbers, which could be positive or negative, should be right justified I thought, so I wrote a second function to deal with those numbers.

```
int RawValue0;
float Voltage0, tempC0, tempF0;

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

  Serial.println();
  Serial.println("Raw Value | Sensor 1 | Sensor 2 | Sensor 3");
  Serial.println("------------------------------------------");

  RawValue0 = 1023; //analogRead(analogIn0);
  Voltage0 = 11.0; //(RawValue0 / 1023.0) * 5000; // 5000 to get millivots.
  tempC0 = -100.0; //(Voltage0-500) * 0.1; // 500 is the offset
  tempF0 = 1212.0; //(tempC0 * 1.8) + 32; // conver to F
}

void loop(){

  // Increment the variables to simulate test data.
  RawValue0 += 51;
  if(RawValue0 > 1023){RawValue0 = 0;}
  Voltage0 += 99.99;
  if(Voltage0 > 9999.99){Voltage0 = 0.0;}
  tempC0 -= 99.99;
  if(tempC0 < -9999.99){tempC0 = 0.0;}

  // Print out the data in columns.
  printNumber(RawValue0);
  Serial.print("   | ");
  printNumber(Voltage0);
  Serial.print(" | ");
  printNumber(tempC0);
  Serial.print(" | ");
  printNumber(tempF0);
  Serial.println();
  delay(250);
}

long printNumber(int number){
  Serial.print("   ");
  int spaces = 0;
  if(number < 1000){spaces = 1;}
  if(number < 100){spaces = 2;}
  if(number < 10){spaces = 3;}
  for(int i = 0; i < spaces; i++){
    Serial.print(" ");
  }
  Serial.print(number);
}

float printNumber(float number){
  int spaces = 0;
  if(number > -1000.00){Serial.print(" ");}
  if(number < 1000){spaces = 1;}
  if(number < 100){spaces = 2;}
  if(number < 10){spaces = 3;}
  if(number < 0){spaces = 0;}
  if(number == -99.99){spaces = 1;}
  for(int i = 0; i < spaces; i++){
    Serial.print(" ");
  }
  Serial.print(number);
}

```

When I compile Jot's sketch, it's 6640 bytes. If you remove his "fancy" header, it drops to 6414 bytes. My sketch is 5124 bytes. There is a certain amount of "overhead" involved when using `sprintf()`.

The question you have to ask yourself is, "Does saving 1000 bytes matter?".
> 1 votes

---
Tags: serial
---


# Question
Title: Can i use Arduino IDE with the Wemos D1 R2 AND also use its ESP8266 module to send AT commands?
I have recently started digging into ESP8266 and learned a little about AT commands and i would really like to add the Wi-Fi functionality in my electronics project, which already uses an Arduino UNO R3. I think it would be much easier to use the Wemos D1 R2 since it is basically an UNO + ESP8266. Here is a link to the official product information page: https://wiki.wemos.cc/products:d1:d1 and its schematic: https://wiki.wemos.cc/\_media/products:d1:d1\_v2.0.0.pdf

I would like to know if it's possible to use the Arduino IDE to program on the Wemos D1 as i do with the normal UNO but also at the same time, be able to send AT commands using its on-board ESP8266?

# Answer
> 1 votes
*A year ago I ported my project from Uno with esp8266 (Uno WiFi Dev Ed) to Wemos D1 R2.*

Wemos D1 R2 board has esp8266 as the only MCU. The AT firmware is an application running in the esp8266. An Arduino sketch with esp8266 boards package is an application too, so it replaces the AT firmware.

Instead of AT commands you will use for networking the WiFi library of the esp8266 arduino package. It is much simpler and there are many examples.

The esp8266 and the D1 R2 board have 3.3 V logic level on pins. So be careful with inputs and check if your devices will read the 3.3 V as HIGH.

In code use Dx constants matching the labels on the board. D1 R2 has less pins then Uno. I recommend to use I2C devices if possible. I had a Grove Base shield on D1 R2, so I have a mapping of D1 R2 pins to 'Uno' pins.

Some of the esp8266 pins are read at boot as boot configuration. Pins D3 (io 0) and D4 (io 2) have pull-up on board and pin D8 (io 15) has pull-down on board. Not all devices will work on this pins. Here is a pin overview of the NodeMcu and Wemos boards.

The esp8266 has only one ADC pin. The A0 of the esp8266 can read 0 to 1 V. Wemos boards have a voltage divider on A0 so the board's pin can read 0 to 3.3 V. Don't read A0 in every loop. WiFi part of the esp8266 uses the ADC hardware too and continuous reading of A0 interferes with WiFi operations.

The Wemos D1 R2 has a strong power regulator 7 to 20 V for Vin and power jack. You can power devices from 5V and 3.3V pin. I use Grove relay modules powered from 5V pin and controlled by logic signal at 3.3 V.

---
Tags: esp8266, wifi
---


# Question
Title: How can I discard power from a device I want to read from?
I want to read the data line from a device that normally interfaces with a controller. It has 3 pins, 3.3v power, gnd, and data. I don't need the power line since the Arduino will be USB powered and I obviously don't want to just connect it straight to ground. What would be the best way to handle this without introducing extra hardware components. Can I just connect the power to an input pin, and then I can use that to see if the device is on?

I'm using an Arduino Mega2560

# Answer
> 1 votes
You don't need to "discard" power. You just ignore it.

If you don't need a connection, then don't connect it. The only important connection is the ground connection. Everything else can be used, or not used, at your discretion.

There's nothing "magical" about a power connection. It's just a voltage that comes from a source that happens to be able to provide more current. If you want to use it to power something, you can. If you want to just sense what the voltage is, you can. If you want to ignore it, you can.

It's not like a mountain: just because it's there, it doesn't mean you *have* to climb it...

# Answer
> 0 votes
I believe you want to check whether your device is on or not without drawing power from it. Something like the following circuit could be useful:

simulate this circuit – Schematic created using CircuitLab

R2 limits the current going into Arduino input pin. Resistor with value around 1K should be good given the voltages you mentioned. Arduino can read the input pin to see whether the device is on or off.

R1 pulls Arduino input pin to ground in when the device is off. This gives a "0" value at the input pin. R1 can be a high value ~10K. High value would limit current leakage to ground via R1. Though this answer won't exactly satisfy your requirement of not using additional components.

---
Tags: power, pins, atmega2560
---


title: SD.h causing constant reboot

text:
# Question
Title: SD.h causing constant reboot
I have a nice sketch running which monitors a few things and displays output on an OLED display. Now I want to save the data to an SD card, but with or without the card module attached I'm getting constant reboots when I add 1 single line of code:

```
#include <SD.h>

```

Any idea what may be happening?

# Answer
> 2 votes
The following libraries are probably used:

* SD Card, using a buffer of 512 bytes (see also the comment of DataFiddler below).
* SSD1306 OLED library, using a buffer of 1,024 bytes
* Serial, using a buffer of 128 bytes (64 for RX, 64 for TX, see comment of Majenko below)

Since there is only 2,048 bytes of SRAM in an Arduino, this leaves 384 bytes. If you actually READ a file you are already above the maximum.

Your own global variables also will consume a considerable amount of SRAM.

Than, if you execute your sketch, parameters and local variables are stored on the stack (in SRAM), so even if your program starts well, it might/will run in problems when calling functions.

---
Tags: sd-card
---