Sketch stops working after a few hours

Exactly. Maybe it's the fact that i call Serial.begin many times without any Serial.end? I will try it out and i will let you know.

I think I might have found the problem, you are not terminating either of the SMS you are sending properly to the GSM module. Instead of "mySerial.write(26)" try with "mySerial.println((char)26)" (2 places in the code).

hum, I don't think you need to send CR+LF after the Ctrl Z (ASCII SUB)

This did not work.

I tried your suggestion. Still the problem exists.

Please post your current sketch and a useful diagram of the circuit..

I have tried almost everything without success.
I posted the revised code below. I excluded eventually part of the code to identify the cause.
The problem disappeared when i commented out the send_sms function within measurements_final function. This means that the GSM module was not enabled within the loop.

I am not experienced in programming. However, i believe that the problem may be due to the serial interface. Maybe the buffer fills up quickly and it resets. Please check the code and any suggestions are welcome.

Diagram: An AT328P is connected to DS3231, SIM808 module, HX711, DHT21 and DS18B20 thermometers and a security siren. PCB is powered by 4 AA batteries, and SIM module is supported by 10000uF capacitor since it requires 2A bursts.

//Libraries
#include <DHT.h>        // Adafruit DHT Library
#include <DS3232RTC.h> //JChristensen DS3231 library
#include "HX711.h" // HX711 library
#include <SoftwareSerial.h> //Software serial library
#include <OneWire.h> //Wire temp sensor
#include <DallasTemperature.h> //Wire temp sensor
#include <avr/sleep.h>
#include "LowPower.h"


//Software serial
SoftwareSerial mySerial(8, 7);
char response[150];

// Settings for measuring battery level
float adc_voltage = 0.0;
float in_voltage = 0.0;
float R1 = 2589.0;
float R2 = 3000.0;
float ref_voltage = 5.0;
int adc_value = 0;


//DHT setup
#define DHTPIN 10
#define DHTTYPE DHT21
DHT dht(DHTPIN, DHTTYPE);

//Brood temp setup
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float Celcius = 0;

//Siren setup
#define SIREN 12

//HX711 setup
#define CALIBRATION_FACTOR -23550.0
#define OFFSET_FACTOR 113299
#define LOADCELL_DOUT_PIN  5
#define LOADCELL_SCK_PIN  6
HX711 scale;

//SIM800 POWER ON
#define SIMSWITCH 9

//Setup battery level pins
#define MAINBAT A1
#define MAINBATSW A0

//TILT settings
volatile bool emergency = false;
const byte switchPin = 3;
byte oldSwitchState = HIGH;  // assume switch open because of pull-up resistor
const unsigned long debounceTime = 10;  // milliseconds
unsigned long switchPressTime;  // when the switch last changed state

//counter set for 4 times a time recording of variables
const uint8_t measure_hours[] = { 8, 12, 16, 20 };
uint8_t last_measure = 0;


void setup() {
  pinMode(switchPin, INPUT);
  pinMode(SIMSWITCH, OUTPUT);
  pinMode(SIREN, OUTPUT);
  pinMode(MAINBAT, INPUT);
  pinMode(MAINBATSW, OUTPUT);

  //Start all temperature sensors and loadcell
  dht.begin();//Start the DHT sensor
  sensors.begin(); //Start onwire library
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  scale.set_scale(CALIBRATION_FACTOR);
  scale.set_offset(OFFSET_FACTOR);


  turnonsim();
  mySerial.println(F("AT+CMGF=1"));
  while (mySerial.available() < 2);
  updateSerial();
  mySerial.println(F("AT+CMGS=\"phone number\""));
  while (mySerial.available() == 0);
  updateSerial();
  mySerial.print(F("Beescale"));
  mySerial.println((char)26);
  delay(3000);
  updateSerial();
  turnoffsim();


  scale.power_down();
  delay(500);
  attachInterrupt(digitalPinToInterrupt(3), emergency_isr, CHANGE);//attaching a interrupt to TILT sensor
}

void loop() {

  setSyncProvider(RTC.get);

  int hr = hour();


  //checks for measurements trigger 4 times a day, 8am, 12pm, 4pm, 8pm
  if ( (hr != last_measure) && ((hr == 8) || (hr == 12) || (hr == 16) || (hr == 20)) )
  {
    last_measure = hr;
    measurements_final();
  }

  if (emergency) {
    emergency = false;
    byte switchState = digitalRead (switchPin);

    // has it changed since last time?
    if (switchState != oldSwitchState)
    {
      // debounce
      if (millis () - switchPressTime >= debounceTime)
      {
        switchPressTime = millis ();  // when we closed the switch
        oldSwitchState =  switchState;  // remember for next time
        if (switchState == LOW)
        {

          //Serial.print(F("Alarm"));

          //digitalWrite(SIREN, HIGH);
          //delay(500);
          //digitalWrite(SIREN, LOW);
        }  // end if switchState is LOW
        else
        {

        }
      }
    }
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
}



void measurements_final() {
  battery();
  send_sms();
}

void emergency_isr() {
  emergency = true;
}

void wakeup() {
  sleep_disable();
  detachInterrupt (digitalPinToInterrupt(2));
}


void turnonsim() {
  digitalWrite(SIMSWITCH, HIGH);
  delay(1000);
  mySerial.begin(19200);
  while ( sendATcommand("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000) == 0 );
}

void turnoffsim() {
  mySerial.end();
  delay(1000);
  digitalWrite(SIMSWITCH, LOW);
}


//Battery reading

void battery() {

  digitalWrite(MAINBATSW, HIGH);
  delay(500);
  adc_value = analogRead(MAINBAT);

  // Determine voltage at ADC input
  adc_voltage  = (adc_value * ref_voltage) / 1024.0;

  // Calculate voltage at divider input
  in_voltage = ((adc_voltage / (R2 / (R1 + R2))) - 5.6) / 1.0 * 100.0;

  digitalWrite(MAINBATSW, LOW);
  delay(500);
}

void send_sms() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  sensors.requestTemperatures();
  float ht = Celcius = sensors.getTempCByIndex(0);
  scale.power_up();
  delay(500);
  float w = scale.get_units();
  scale.power_down();
  delay(500);
  turnonsim();
  mySerial.println(F("AT+CMGF=1"));
  while (mySerial.available() < 2);
  updateSerial();
  mySerial.println(F("AT+CMGS=\phone number\""));
  while (mySerial.available() == 0);
  updateSerial();
  mySerial.print(F("Weight:"));
  mySerial.print(-w);
  mySerial.println(F("kg"));
  mySerial.print(F("Amb:"));
  mySerial.print(t);
  mySerial.println(F("C"));
  mySerial.print(F("Hum:"));
  mySerial.print(h);
  mySerial.println(F("%"));
  mySerial.print(F("HTemp:"));
  mySerial.print(ht);
  mySerial.println(F("C"));
  mySerial.print(F("Battery:"));
  mySerial.print(in_voltage, 2);
  mySerial.print(F("%"));
  mySerial.println((char)26);
  delay(3000);
  while (mySerial.available() == 0);
  updateSerial();
  turnoffsim();
}

void updateSerial()
{
  delay(500);
  mySerial.read();
}

int8_t sendATcommand(char const* ATcommand, char const* expected_answer1, char const* expected_answer2, unsigned int timeout) {
  uint8_t x = 0, answer = 0;
  unsigned long previous;
  memset(response, '\0', 150); // Initialize the string
  delay(100);
  while ( mySerial.available() > 0) mySerial.read(); // Clean the input buffer
  mySerial.println(ATcommand); // Send the AT command
  x = 0;
  previous = millis();
  // this loop waits for the answer
  do {
    // if there are data in the UART input buffer, reads it and checks for the asnwer
    if (mySerial.available() != 0) {
      response[x] = mySerial.read();
      x++;
      if (x >= 150) { //Overflow protection
        Serial.println(response);
        memset(response, 0, 150); // Initialize the string
        x = 0;
      }
      // check if the desired answer 1 is in the response of the module
      if (strstr(response, expected_answer1) != NULL)
      {
        answer = 1;
      }
      // check if the desired answer 2 is in the response of the module
      else if (strstr(response, expected_answer2) != NULL)
      {
        answer = 2;
      }
    }
  }
  // Waits for the asnwer with time out
  while ((answer == 0) && ((millis() - previous) < timeout));
  Serial.println(response);
  return answer;
}

If I had this issue I would shut down a "device + library include" one at a time until it no longer stops.

This is not a diagram, it says nothing about how the individual components are wired and powered. If the GSM module is powered by pin named "SIMSWITCH" that is an issue. The GSM module uses 9600 baud by default, unless configured otherwise using 19200 may be an issue.

You have changed the "updateSerial()" function, so it no longer empties the incoming serial data.

void updateSerial()
{
  delay(500);
  //mySerial.read(); //This is wrong
  while (mySerial.available()) mySerial.read(); //This is right
}

Hi,
If you have produced a PCB, then you must have a schematic of some sort.
Please post a copy?
If it is from a CAD then please EXPORT a jpg image, not a screen shot.

If you do not have a schematic, then PLEASE draw one, pen(cil) and paper are fine.

Tom.... :smiley: :+1: :coffee: :australia:

Hi,

I have attached the schematic and the revised code i tested yesterday.

I believe i have narrowed down the problem to the datatype of the function. If i change the datatype of send_sms and send_initial_sms from void to bool, it seems to work initially but fail after a few hours of sleep. I do not exactly understand the datatypes. Or i may have run out of RAM.

I also added serial print to the code for every step in order to identify the problem. The problem occurs during the execution of the readings() function and turnonsim();

I am sure this is not a power supply problem as i uploaded a new sketch with only turning on the mosfet of the GSM module and there is no reset.


//Libraries
#include <DHT.h>        // Adafruit DHT Library
#include <DS3232RTC.h> //JChristensen DS3231 library
#include "HX711.h" // HX711 library
#include <SoftwareSerial.h> //Software serial library
#include <OneWire.h> //Wire temp sensor
#include <DallasTemperature.h> //Wire temp sensor
#include "LowPower.h"

//Software serial & SIM declarations
SoftwareSerial mySerial(8, 7);
String destinationNumber = "phonenumber";
char response[150];

// Settings for measuring battery level
float adc_voltage = 0.0;
float in_voltage = 0.0;
float R1 = 2589.0;
float R2 = 3000.0;
float ref_voltage = 5.0;
int adc_value = 0;

// Comment out to turn off debugging (if desired) to Serial Monitor
#define DEBUG

//DHT setup
#define DHTPIN 10
#define DHTTYPE DHT21
DHT dht(DHTPIN, DHTTYPE);
int t = 0;
int h = 0;

//Brood temp setup
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float Celcius = 0;
int ht = 0;

//Siren setup
#define SIREN 12

//HX711 setup
#define CALIBRATION_FACTOR -23550.0
#define OFFSET_FACTOR 113299
#define LOADCELL_DOUT_PIN  5
#define LOADCELL_SCK_PIN  6
HX711 scale;
float w = 0.0;
float old_w = 0.0;
char difference[5] = "00.0";

//SIM800 POWER ON
#define SIMSWITCH 9
#define SIMPWR 4

//Setup battery level pins
#define MAINBAT A1
#define MAINBATSW A0

//interrupt flag for alarm
volatile bool measurement = false;

//TILT settings
volatile bool emergency = false;
const byte switchPin = 3;
byte oldSwitchState = HIGH;  // assume switch open because of pull-up resistor
const unsigned long debounceTime = 10;  // milliseconds
unsigned long switchPressTime;  // when the switch last changed state

void updateSerial()
{
  delay(500);
  while (mySerial.available())
    mySerial.read();
}

int8_t sendATcommand(char const* ATcommand, char const* expected_answer1, char const* expected_answer2, unsigned int timeout) {
  uint8_t x = 0, answer = 0;
  unsigned long previous;
  memset(response, '\0', 150); // Initialize the string
  delay(100);
  while ( mySerial.available() > 0) mySerial.read(); // Clean the input buffer
  mySerial.println(ATcommand); // Send the AT command
  x = 0;
  previous = millis();
  // this loop waits for the answer
  do {
    // if there are data in the UART input buffer, reads it and checks for the asnwer
    if (mySerial.available() != 0) {
      response[x] = mySerial.read();
      x++;
      if (x >= 150) { //Overflow protection
        Serial.println(response);
        memset(response, 0, 150); // Initialize the string
        x = 0;
      }
      // check if the desired answer 1 is in the response of the module
      if (strstr(response, expected_answer1) != NULL)
      {
        answer = 1;
      }
      // check if the desired answer 2 is in the response of the module
      else if (strstr(response, expected_answer2) != NULL)
      {
        answer = 2;
      }
    }
  }
  // Waits for the asnwer with time out
  while ((answer == 0) && ((millis() - previous) < timeout));
  Serial.println(response);
  return answer;
}

bool emergency_isr() {
  emergency = true;
}

bool wakeup() {
  detachInterrupt (digitalPinToInterrupt(2));
  measurement = true;
}

bool turnonsim() {
#ifdef DEBUG
  Serial.print(F("Turning on GSM"));
#endif
  digitalWrite(SIMSWITCH, HIGH);
  delay(500);
  while ( sendATcommand("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000) == 0 );
#ifdef DEBUG
  Serial.println(F("Obtained signal"));
#endif
}

bool turnoffsim() {
#ifdef DEBUG
  Serial.print(F("Turning off GSM"));
#endif
  delay(1000);
  digitalWrite(SIMSWITCH, LOW);
}

void readings() {
  //battery reading
#ifdef DEBUG
  Serial.println(F("Getting battery readings"));
#endif
  digitalWrite(MAINBATSW, HIGH);
  delay(500);
  adc_value = analogRead(MAINBAT);
  adc_voltage  = (adc_value * ref_voltage) / 1024.0;
  in_voltage = ((adc_voltage / (R2 / (R1 + R2))) - 5.6) / 1.0 * 100.0;
  digitalWrite(MAINBATSW, LOW);
  delay(500);

#ifdef DEBUG
  Serial.println(F("Getting other readings"));
#endif

  //temperature reading
  h = dht.readHumidity();
  delay(500);
  t = dht.readTemperature();
  delay(500);
  sensors.requestTemperatures();
  delay(500);
  ht = Celcius = sensors.getTempCByIndex(0);
  delay(500);

#ifdef DEBUG
  Serial.println(F("Starting scale"));
#endif
  //weight reading
  scale.power_up();
  delay(500);

  w = scale.get_units();
  delay(500);
  scale.power_down();
  delay(500);

#ifdef DEBUG
  Serial.println(F("Readings completed"));
#endif
}

bool send_sms() {

#ifdef DEBUG
  Serial.println(F("Measurements SMS sending"));
#endif

  readings();
  turnonsim();

  dtostrf((w - old_w), 5, 2, difference);

  mySerial.println(F("AT+CMGF=1\r"));
  while (mySerial.available() < 2);
  updateSerial();
  mySerial.print(F("AT+CMGS=\""));
  mySerial.print(destinationNumber);
  mySerial.println(F("\""));
  while (mySerial.available() == 0);
  updateSerial();
  mySerial.print(F("Weight:"));
  mySerial.print(-w);
  mySerial.print(F("kg"));
  mySerial.print(F("("));
  mySerial.print(difference);
  mySerial.println(F(")"));
  mySerial.print(F("Amb:"));
  mySerial.print(t);
  mySerial.println(F("C"));
  mySerial.print(F("Hum:"));
  mySerial.print(h);
  mySerial.println(F("%"));
  mySerial.print(F("HTemp:"));
  mySerial.print(ht);
  mySerial.println(F("C"));
  mySerial.print(F("Battery:"));
  mySerial.print(in_voltage, 0);
  mySerial.print(F("%"));
  mySerial.println((char)26);
  delay(3000);
  while (mySerial.available() == 0);
  updateSerial();
  turnoffsim();
  old_w = w;

#ifdef DEBUG
  Serial.println(F("SMS sent"));
#endif
}

bool send_initial_sms() {

#ifdef DEBUG
  Serial.println(F("Initial SMS sending"));
#endif
  readings();
  old_w = w;
  delay(1000);
  turnonsim();

  mySerial.println(F("AT+CMGF=1\r"));
  while (mySerial.available() < 2);
  updateSerial();
  mySerial.print(F("AT+CMGS=\""));
  mySerial.print(destinationNumber);
  mySerial.println(F("\""));
  while (mySerial.available() == 0);
  updateSerial();
  mySerial.print(F("Starting"));
  mySerial.println(F("Weight:"));
  mySerial.print(-w);
  mySerial.println(F("kg"));
  mySerial.print(F("Amb:"));
  mySerial.print(t);
  mySerial.println(F("C"));
  mySerial.print(F("Hum:"));
  mySerial.print(h);
  mySerial.println(F("%"));
  mySerial.print(F("HTemp:"));
  mySerial.print(ht);
  mySerial.println(F("C"));
  mySerial.print(F("Battery:"));
  mySerial.print(in_voltage, 0);
  mySerial.print(F("%"));
  mySerial.println((char)26);
  delay(3000);
  while (mySerial.available() == 0);
  updateSerial();
  turnoffsim();

#ifdef DEBUG
  Serial.println(F("Initial SMS sent"));
#endif
}

void setup() {
  delay(500);
  pinMode(switchPin, INPUT);
  pinMode(SIMSWITCH, OUTPUT);
  pinMode(SIREN, OUTPUT);
  pinMode(MAINBAT, INPUT);
  pinMode(MAINBATSW, OUTPUT);


  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  scale.set_scale(CALIBRATION_FACTOR);
  scale.set_offset(OFFSET_FACTOR);
  dht.begin();//Start the DHT sensor
  sensors.begin(); //Start onwire library

  //Serial begin
#ifdef DEBUG
  Serial.begin(9600);
#endif
  mySerial.begin(9600);

#ifdef DEBUG
  Serial.println(F("Beescale has started"));
#endif

  RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
  RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
  RTC.alarmInterrupt(ALARM_1, false);
  RTC.alarmInterrupt(ALARM_2, false);
  RTC.squareWave(SQWAVE_NONE);

#ifdef DEBUG
  Serial.println(F("Setup complete"));
#endif
  send_initial_sms();


  scale.power_down();
  delay(500);
  attachInterrupt(digitalPinToInterrupt(3), emergency_isr, CHANGE);//attaching a interrupt to TILT sensor

#ifdef DEBUG
  Serial.println(F("Attached siren"));
#endif

  setSyncProvider(RTC.get);
  int hr = hour();

  if (hr < 8 || hr > 20) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0 , 8, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

  if (hr >= 8 && hr < 12) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 12, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

  if (hr >= 12 && hr < 16) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 16, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

  if (hr >= 16 && hr < 20) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 20, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

}

void loop() {


  attachInterrupt (digitalPinToInterrupt(2), wakeup, FALLING);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

  setSyncProvider(RTC.get);
#ifdef DEBUG
  Serial.println(F("RTC sync complete"));
#endif

  int hr = hour();

  if (hr < 8 || hr > 20) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 8, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

  if (hr >= 8 && hr < 12) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 12, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

  if (hr >= 12 && hr < 16) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 16, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

  if (hr >= 16 && hr < 20) {
    RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 20, 0);
    RTC.alarm(ALARM_1);
    RTC.alarmInterrupt(ALARM_1, true);
    RTC.squareWave(SQWAVE_NONE);
  }

  if (measurement) {
    measurement = false;
    Serial.println("Measurments time");
    send_sms();
  }

  if (emergency) {
    emergency = false;
    byte switchState = digitalRead (switchPin);

    // has it changed since last time?
    if (switchState != oldSwitchState)
    {
      // debounce
      if (millis () - switchPressTime >= debounceTime)
      {
        switchPressTime = millis ();  // when we closed the switch
        oldSwitchState =  switchState;  // remember for next time
        if (switchState == LOW)
        {
#ifdef DEBUG
          Serial.print(F("Alarm"));
#endif

          //digitalWrite(SIREN, HIGH);
          //delay(500);
          //digitalWrite(SIREN, LOW);
        }
      }
    }
  }
}

Your circuit diagram seems over-complicated, and it does not clarify what may be the issue. I guess that you use pre-build modules so it makes little sense to post the diagram for a SIM800 module. What would have been helpful was a diagram (or even some pictures of the assembly) that illustrates how the modules are wired together. I cannot see any decoupling capacitors on the MCU's VCC pins, which may be a problem.

Do not start to use the "String" class / data type, it is known to cause instability and even though it is not an issue in the latest code, it just an unnecessary deroute. I still cannot figure out how the SIM module is switched on/off, this is essential info for trouble shooting. Did you know that most of those SIM module have a low power sleep mode which could be used instead of a "switch"?

I do spot a little problem in the code, though.. "difference" has the size of 5 chars and you are instructing "dtostrf" to create a null terminated number of 5 digits. That means 5 chars + 1 null terminator = 6 chars and this can cause resets and other weird behaviour so let "difference" be at least 6 chars wide.

I do also think that your code for setting alarms is un-pretty:

void set_rtc_alarm(int hr)
{
  RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, hr, 0);
  RTC.alarm(ALARM_1);
  RTC.alarmInterrupt(ALARM_1, true);
  RTC.squareWave(SQWAVE_NONE);
}

void next_rtc_alarm()
{
  int hr = hour();
  if ((hr < 8) && (hr > 20)) set_rtc_alarm(8);
  else if ((hr >= 8) && (hr < 12)) set_rtc_alarm(12);
  else if ((hr >= 12) && (hr < 16)) set_rtc_alarm(16);
  else if ((hr >= 16) && (hr < 20)) set_rtc_alarm(20);
}

void setup()
{
  //No alarm setting here..
}

void loop()
{
  //Power attachments down
  next_rtc_alarm();
  //Sleep
  //Power attachments up
  //Work
}

Much nicer..

No. I have built the PCB 100%. No pre-build parts.

There are decoupling capacitors on the MCU (AT1, AT2, AT3 parts on schematic)

I removed it. Still not fix.

Through the LDO (MIC) which is used only for powering the GSM module. There is another LDO (MAX8880) for the rest of the parts. The GSM LDO is enabled though the EN pin of it which is directly controlled by the MCU. See part MIC on the top left of the schematic.

Do you mean to make the following:

char difference[5] = "00.0";
to
char difference[6] = "00.0";

Sounds like a commercial prototype or something, you could let someone in the General electronics forum check it for mishaps.

Yes, at least 6 are required.

I have narrowed down the problem to the deep sleep mode. If the arduino is in sleep mode for more than 5 minutes, after wake up it crashes immediately. Any suggestions are welcome. If it's in deep sleep for 3 minutes for example, it is working as expected.

How can i identify a stack overflow problem through arduino ide?

The problem disappears if i remove software serial library and all commands related with it. I also used NeoSWSerial without success. How can i overcome this problem?

Your problem is most likely that you are either 1) Writing out of bounds of a buffer, thereby changing other variables or pointers which causes malfunction or 2) Your problem is electrical, a bad capacitor, a cold solder joint or something else. You can try to post your current code and I will have a look but I suspect a hardware issue may be the problem.

Please find attached.
The PCB works as expected with other sketch i upload. How can this be a hardware problem? I have also not ran out of RAM. I checked with the freeRAM arduino library.


//Libraries
#include <DHT.h>        // Adafruit DHT Library
#include <DS3232RTC.h> //JChristensen DS3231 library
#include "HX711.h" // HX711 library
#include <SoftwareSerial.h> //Software serial library
#include <OneWire.h> //Wire temp sensor
#include <DallasTemperature.h> //Wire temp sensor
#include <avr/sleep.h>

//Software serial & SIM declarations
SoftwareSerial mySerial(8, 7);
#define SQW 2

// Settings for measuring battery level
float in_voltage = 0;

// Comment out to turn off debugging (if desired) to Serial Monitor
#define DEBUG

//DHT setup
#define DHTPIN 10
#define DHTTYPE DHT21
DHT dht(DHTPIN, DHTTYPE);
int t = 0;
int h = 0;

//Brood temp setup
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
int Celcius = 0;
int ht = 0;

//Siren setup
#define SIREN 12

//HX711 setup
#define CALIBRATION_FACTOR -23550.0
#define OFFSET_FACTOR 113299
#define LOADCELL_DOUT_PIN  5
#define LOADCELL_SCK_PIN  6
HX711 scale;
float w = 0.0;
float old_w = 0.0;
float difference = 0.0;

//SIM800 POWER ON
#define SIMSWITCH 9

//Setup battery level pins
#define MAINBAT A1
#define MAINBATSW A0

//interrupt flag for alarm
volatile bool measurement = false;

//TILT settings
volatile bool emergency = false;
const byte switchPin = 3;

void updateSerial()
{
  delay(500);
  while (mySerial.available())
    mySerial.read();
}

int8_t sendATcommand(char const* ATcommand, char const* expected_answer1, char const* expected_answer2, unsigned int timeout) {
  char response[150];
  uint8_t x = 0, answer = 0;
  unsigned long previous;
  memset(response, '\0', 150); // Initialize the string
  delay(100);
  while ( mySerial.available() > 0) mySerial.read(); // Clean the input buffer
  mySerial.println(ATcommand); // Send the AT command
  x = 0;
  previous = millis();
  // this loop waits for the answer
  do {
    // if there are data in the UART input buffer, reads it and checks for the asnwer
    if (mySerial.available() != 0) {
      response[x] = mySerial.read();
      x++;
      if (x >= 150) { //Overflow protection
        Serial.println(response);
        memset(response, 0, 150); // Initialize the string
        x = 0;
      }
      // check if the desired answer 1 is in the response of the module
      if (strstr(response, expected_answer1) != NULL)
      {
        answer = 1;
      }
      // check if the desired answer 2 is in the response of the module
      else if (strstr(response, expected_answer2) != NULL)
      {
        answer = 2;
      }
    }
  }
  // Waits for the asnwer with time out
  while ((answer == 0) && ((millis() - previous) < timeout));
  Serial.println(response);
  return answer;
}

void emergency_isr() {
  emergency = true;
}

void wakeup() {
  sleep_disable();
  detachInterrupt(digitalPinToInterrupt(2));
  measurement = true;
}

void turnonsim() {

#ifdef DEBUG
  Serial.println(F("Turning on GSM"));
#endif

  digitalWrite(SIMSWITCH, HIGH);
  delay(100);
  while ( sendATcommand("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000) == 0 );

#ifdef DEBUG
  Serial.println(F("Obtained signal"));
#endif
}

void turnoffsim() {

#ifdef DEBUG
  Serial.println(F("Turning off GSM"));
#endif

  digitalWrite(SIMSWITCH, LOW);
}

void battery() {

#ifdef DEBUG
  Serial.println(F("Getting battery readings"));
#endif

  digitalWrite(MAINBATSW, HIGH);
  float adc_value = analogRead(MAINBAT);
  float adc_voltage  = (adc_value * 5.0) / 1024.0;
  in_voltage = ((adc_voltage / (3000.0 / (2589.0 + 3000.0))) - 5.6) / 1.0 * 100.0;
  digitalWrite(MAINBATSW, LOW);
}

void temp() {

#ifdef DEBUG
  Serial.println(F("Getting temp and hum"));
#endif

  h = dht.readHumidity();
  t = dht.readTemperature();

  sensors.requestTemperatures();
  ht = Celcius = sensors.getTempCByIndex(0);

}


void weight() {

#ifdef DEBUG
  Serial.println(F("Starting scale"));
#endif

  //weight reading
  scale.power_up();
  delay(100);

  w = scale.get_units(10);

  scale.power_down();
  delay(100);

#ifdef DEBUG
  Serial.println(F("Readings completed"));
#endif

}

void send_sms() {

#ifdef DEBUG
  Serial.println(F("Measurements SMS sending"));
#endif

  difference = w - old_w;

  mySerial.println(F("AT+CMGF=1\r"));
  while (mySerial.available() < 2);
  updateSerial();
  mySerial.print(F("AT+CMGS=\""));
  mySerial.print(F("phonenumber"));
  mySerial.println(F("\""));
  while (mySerial.available() == 0);
  updateSerial();
  mySerial.print(F("Weight:"));
  mySerial.print(-w);
  mySerial.print(F("kg"));
  mySerial.print(F("("));
  mySerial.print(difference);
  mySerial.println(F(")"));
  mySerial.print(F("Amb:"));
  mySerial.print(t);
  mySerial.println(F("C"));
  mySerial.print(F("Hum:"));
  mySerial.print(h);
  mySerial.println(F("%"));
  mySerial.print(F("HTemp:"));
  mySerial.print(ht);
  mySerial.println(F("C"));
  mySerial.print(F("Battery:"));
  mySerial.print(in_voltage, 0);
  mySerial.print(F("%"));
  mySerial.println((char)26);
  delay(3000);
  while (mySerial.available() == 0);
  updateSerial();
  old_w = w;

#ifdef DEBUG
  Serial.println(F("SMS sent"));
#endif

}

void send_initial_sms() {

#ifdef DEBUG
  Serial.println(F("Initial SMS sending"));
#endif

  old_w = w;
  delay(1000);
  mySerial.println(F("AT+CMGF=1\r"));
  while (mySerial.available() < 2);
  updateSerial();
  mySerial.print(F("AT+CMGS=\""));
  mySerial.print(F("phonenumber"));
  mySerial.println(F("\""));
  while (mySerial.available() == 0);
  updateSerial();
  mySerial.println(F("Setup"));
  mySerial.print(F("Weight:"));
  mySerial.print(-w);
  mySerial.println(F("kg"));
  mySerial.print(F("Amb:"));
  mySerial.print(t);
  mySerial.println(F("C"));
  mySerial.print(F("Hum:"));
  mySerial.print(h);
  mySerial.println(F("%"));
  mySerial.print(F("HTemp:"));
  mySerial.print(ht);
  mySerial.println(F("C"));
  mySerial.print(F("Battery:"));
  mySerial.print(in_voltage, 0);
  mySerial.print(F("%"));
  mySerial.println((char)26);
  delay(3000);
  while (mySerial.available() == 0);
  updateSerial();


#ifdef DEBUG
  Serial.println(F("Initial SMS sent"));
#endif
}

void set_rtc_alarm(int hr)
{
  RTC.setAlarm(ALM1_MATCH_MINUTES, 0, hr, 0, 0);
  RTC.alarm(ALARM_1);
  RTC.alarmInterrupt(ALARM_1, true);
  RTC.squareWave(SQWAVE_NONE);
}

void next_rtc_alarm()
{
  int hr = hour();
  if ((hr < 8) || (hr > 20)) set_rtc_alarm(30);
  else if ((hr >= 8) && (hr < 9)) set_rtc_alarm(9);
  else if ((hr >= 9) && (hr < 10)) set_rtc_alarm(10);
  else if ((hr >= 10) && (hr < 11)) set_rtc_alarm(11);
}



void setup() {

  pinMode(switchPin, INPUT);
  pinMode(SIMSWITCH, OUTPUT);
  pinMode(SIREN, OUTPUT);
  pinMode(MAINBAT, INPUT);
  pinMode(MAINBATSW, OUTPUT);
  pinMode(SQW, INPUT);

  //Serial begin

#ifdef DEBUG
  Serial.begin(19200);
#endif

  mySerial.begin(19200);


  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  scale.set_scale(CALIBRATION_FACTOR);
  scale.set_offset(OFFSET_FACTOR);
  dht.begin();//Start the DHT sensor
  sensors.begin(); //Start onwire library


  RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
  RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
  RTC.alarmInterrupt(ALARM_1, false);
  RTC.alarmInterrupt(ALARM_2, false);
  RTC.squareWave(SQWAVE_NONE);



  battery();
  turnonsim();
  temp();
  weight();
  turnonsim();
  send_initial_sms();
  turnoffsim();


  scale.power_down();
  delay(1000);
  attachInterrupt(digitalPinToInterrupt(switchPin), emergency_isr, CHANGE);//attaching a interrupt to TILT sensor


#ifdef DEBUG
  Serial.println(F("Setup complete"));
#endif
}

void loop() {

  setSyncProvider(RTC.get);


#ifdef DEBUG
  Serial.println(F("RTC sync complete"));
#endif

  next_rtc_alarm();

  ADCSRA = 0;

  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  noInterrupts ();
  attachInterrupt (digitalPinToInterrupt(SQW), wakeup, FALLING);
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS);
  interrupts ();  // one cycle
  sleep_cpu ();   // one cycle

  if (measurement) {
    measurement = false;

    battery();
    turnonsim();
    temp();
    weight();
    send_sms();
    turnoffsim();

  }

  if (emergency) {
    byte oldSwitchState = HIGH;  // assume switch open because of pull-up resistor
    const unsigned long debounceTime = 10;  // milliseconds
    unsigned long switchPressTime;  // when the switch last changed state
    emergency = false;
    byte switchState = digitalRead (switchPin);

    // has it changed since last time?
    if (switchState != oldSwitchState)
    {
      // debounce
      if (millis () - switchPressTime >= debounceTime)
      {
        switchPressTime = millis ();  // when we closed the switch
        oldSwitchState =  switchState;  // remember for next time
        if (switchState == LOW)
        {
#ifdef DEBUG
          Serial.println(F("Siren"));
#endif

          //digitalWrite(SIREN, HIGH);
          //delay(500);
          //digitalWrite(SIREN, LOW);

          turnonsim();
          mySerial.println(F("ATD+ phonenumber;"));
          updateSerial();
          delay(10000);
          mySerial.println(F("ATH"));
          updateSerial();
          turnoffsim();

        }
      }
    }
  }
}

Which "other sketch" is working? "freeRam()" is not useful and I do not think you problem is related to a lack of memory. If a device does not work and the code is not the problem, then the hardware must be the culprit. If an attachment is pulling more current during power up than is available, this will result in a voltage drop that may cause a reset. Removing the "SoftwareSerial" library basically removes the SIM800 module, this could be a hint that the module may need a beefy capacitor to handle any inrush current spikes.

The code is not very well structured and that makes it hard to debug. There are a lot of potential for "endless loops" in the code and if the watchdog is enabled, this may cause resets. In the emergency code (according to the schematic this is a tilt switch), there is some erroneous debouncing which may cause unwanted behaviour. Also, the datatypes for "t" and "h" (read from DHT) should be float points and not integers.

The whole code crashes even if i leave the SIM800 module fully turned off by keeping the LDO switched off. I have also tried a simple sketch which just turns on the SIM module and it works without any reset.

The other modules on the PCB (DHT21, HX711, DS18B20) consume power in the order of a few mA.

Can you provide me with an example in the code in order to understand what you mean?

I have also tried it with float variables and still no fix.

Can the above function cause an error? Within send_sms function i am calling mySerial.available once and after this i call the updateSerial function above which calls for a consecutive time the mySerial.available.