Atmega 328P resets before executing loop

Go To Last Post
38 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I am new to this forum. The problem i have is that when the IF statement in the loop section is true and tries to execute FINAL_MEASUREMENTS, the Atmega328p seems to reset itself and executes the setup section again before the loop. Normally, the MCU should be execute only the loop section since it enters sleep mode and wakes up every 8 seconds to check the loop section if something is true.

 

I have attached the full code below. I cant find the problem with the code. Thanks in advance.

 

//Libraries
#include <DHT.h>        // Adafruit DHT Library
#include <DS3232RTC.h>  //RTC Library https://github.com/JChristensen/DS3232RTC
#include "HX711.h"
#include <SoftwareSerial.h>
#include <OneWire.h> //Wire temp sensor
#include <DallasTemperature.h> //Wire temp sensor
#include "Timer.h"
#include "LowPower.h"

//Software serial
SoftwareSerial mySerial(8, 7);

// 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;

//TinyGSM configuation
#define TINY_GSM_MODEM_SIM808
#include <TinyGsmClient.h>
TinyGsm modem(mySerial);

//Interrupt pin
#define TILT 3

//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
//#define PWR 4 //disable if PWR connected to GND

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

//flag for tilt interrupt
volatile bool emergency = false;

//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(TILT, 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);

  Serial.begin(9600);
  mySerial.begin(9600);
  TURNONSIM();
  delay(1000);
  mySerial.println("AT+CMGF=1");
  delay(500);
  updateSerial();
  mySerial.println("AT+CMGS=\"my phone number\"");
  delay(500);
  updateSerial();
  mySerial.print("Test message");
  delay(500);
  updateSerial();
  mySerial.println(char(26));
  delay(3000);
  TURNOFFSIM();
  scale.power_down();
  delay(1000);
  attachInterrupt(digitalPinToInterrupt(3), EMERGENCY, CHANGE);//attaching a interrupt to TILT sensor
}

void loop() {
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  setSyncProvider(RTC.get);

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

  if (emergency) {
    emergency = false;
    Serial.println("Alarm");
  }
}

void MEASUREMENTS_FINAL() {
  Battery();
  send_sms();
  TURNOFFSIM();
}

void EMERGENCY() {
  emergency = true;
}

void TURNONSIM() {
  digitalWrite(SIMSWITCH, HIGH);
  delay(2000);
  if (!modem.waitForNetwork()) {
    delay(5000);
    return;
  }
}

void TURNOFFSIM() {
  delay(1000);
  digitalWrite(SIMSWITCH, LOW);
}

//sends software serial data to arduino serial
void updateSerial()
{
  delay(500);
  while (Serial.available())
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while (mySerial.available())
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

//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();
  delay(500);
  float t = dht.readTemperature();
  delay(500);
  sensors.requestTemperatures();
  delay(500);
  float ht = Celcius = sensors.getTempCByIndex(0);
  delay(500);
  scale.power_up();
  delay(500);
  float w = scale.get_units();
  delay(500);
  scale.power_down();
  delay(500);
  TURNONSIM();
  Serial.begin(9600); //delete on final version
  mySerial.begin(9600);
  updateSerial();
  mySerial.println("AT+CMGF=1");
  delay(1000);
  updateSerial();
  mySerial.println("AT+CMGS=\"my phone number\"");
  delay(1000);
  updateSerial();
  mySerial.print("Weight:");
  mySerial.print(-w - 4.8);
  mySerial.println("kg");
  mySerial.print("Amb:");
  mySerial.print(t);
  mySerial.println("C");
  mySerial.print("Hum:");
  mySerial.print(h);
  mySerial.println("%");
  mySerial.print("HTemp:");
  mySerial.print(ht);
  mySerial.println("C");
  mySerial.print("Battery:");
  mySerial.print(in_voltage, 2);
  mySerial.print("%");
  mySerial.println(char(26));
  delay(3000);
}

 

Last Edited: Fri. Oct 8, 2021 - 09:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I spent a few minutes looking for an uninitialised variable and found this:

HX711 scale;

I don't know the llibrary, so it may or may not be the problem.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Welcome to AVRFreaks.

 

Presumably, this is on an Arduino?

 

When writing C code, note that it's conventional for names in ALL_CAPITALS to be reserved for preprocessor #defines ("macros")

 

sanast wrote:
when the IF statement in the loop section is true and tries to execute FINAL_MEASUREMENTS, the Atmega328p seems to reset itself

How do you determine that?

 

void MEASUREMENTS_FINAL() {
  Battery();
  send_sms();
  TURNOFFSIM();
}

well, that send_sms() function is huge, with loads of floating-point and interaction with, presumably, your GSM modem - so that would be a prime suspect.

 

does that function work in isolation?

 

Note that you are making the classic mistake of using "blind" delays:

  TURNONSIM();
  delay(1000);
  mySerial.println("AT+CMGF=1");
  delay(500);
  updateSerial();
  mySerial.println("AT+CMGS=\"my phone number\"");
  delay(500);
  updateSerial();
  mySerial.print("Test message");
  delay(500);
  updateSerial();
  mySerial.println(char(26));
  delay(3000);
  TURNOFFSIM();
  scale.power_down();
  delay(1000);

ie, your code just blindly continues without paying any attention to whether the operation succeeded, and the modem is ready & in the correct state for the next command:

 

https://www.avrfreaks.net/commen...

https://www.avrfreaks.net/commen... - point #2

https://www.avrfreaks.net/commen...

 

etc, etc, ...

 

EDIT

 

In particular, sending an SMS depends on the network, so it will sometimes take an unusually long time - and may fail completely.

 

Also, some modems (possibly depending on configuration) will give two responses on sending an SMS:

  1. an immediate "OK" to say that the command was valid;
  2. a later, "unsolicited", response when the Network confirms that the message was accepted.

 

If your modem does that, is your code ready for it?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Oct 8, 2021 - 07:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Things that can break you out of loops unexpectedly..

 

1) an interrupt enabled for which no ISR is provided (and the default handler resets AVR)

 

2) the watchdog. If enabled but not regularly reset it will cause a chip reset

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sanast wrote:
wakes up every 8 seconds

 

Do sum all delays and you will collect more than 11s of execution. Change 8s to 13s.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:
I don't know the llibrary, so it may or may not be the problem.

 

This is correct as per library

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

grohote wrote:
Do sum all delays and you will collect more than 11s of execution. Change 8s to 13s.

 

What do you mean increase to 13sec; the slepp? Watchdog sleep for AT328P cannot exceed 8s.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sanast wrote:
Watchdog sleep for AT328P cannot exceed 8s

 

No problem- do change each 1s delay to 0.5s delay, and you can be safe. Do sum all delays for yourself.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sanast wrote:
This is correct as per library

In that case you can try the "Divide & Conquer" method of isolating the fault.

void MEASUREMENTS_FINAL() {
  Battery();
  send_sms();
  TURNOFFSIM();
}

Start by only calling Battery() then only calling send_sms(). Etc. etc

 

Another method is strip the program back to a very minimal set of functions then start adding stuff back in bit-by-bit.

It cam be tempting to write a sh1tload of code and then start testing, but the incremental strategy is actually how you should have written the program in the first place anyway.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Make some routine like my_serial_print_delay, so you can call it instead & it will include the delay (maybe even pass the value if you want variability).

Then you can get rid of all of these delay(500) all over...the code will be MUCH shorter & therefore MUCH easier to read.

 

If you need a lot of delays, that is also a sign you might want to think about an alternative method, though not a requirement

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have disclosed below the new code. I have added serial.print at regular intervals in order to identify where exactly the problem is. The MCU crashes after printing "Readings completed"; at the end of readings() function. It restarts every time it reaches this point and the serial monitor prints the same lines from the beginning.

 

 This is not a power supply problem as i have tested the GSM module with minimal code and it runs normally. I have also checked the memory with an arduino library and at all points have about 1.1k bytes available. Please let me know your suggestions as i am trying for days to make this work without success.

 


//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);
const PROGMEM char destinationNumber[] = {"phone number"};
char response[150];
char char_sms;

// Settings for measuring battery level
byte adc_voltage = 0;
byte in_voltage = 0;
int R1 = 2589;
int R2 = 3000;
byte ref_voltage = 5;
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);
char t = 0;
byte h = 0;

//Brood temp setup
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
char Celcius = 0;
char 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.00;
float old_w = 0.0;
char difference[5] = "00.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;
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

//RTC variables
byte hr = 0;

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

void emergency_isr() {
  emergency = true;
}

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

void turnonsim() {

#ifdef DEBUG
  Serial.println(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
}

void turnoffsim() {

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

  delay(1000);
  digitalWrite(SIMSWITCH, LOW);
}

void set_alarm() {

#ifdef DEBUG
  Serial.println(F("Setting alarm"));
#endif

  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 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 temp and hum"));
#endif

  //temperature reading
  h = dht.readHumidity();
  t = dht.readTemperature();

  if (isnan(h) || isnan(t)) {

    #ifdef DEBUG
    Serial.println(F("Failed to read from DHT sensor!"));
    #endif

    return;
  }

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

  if (ht != DEVICE_DISCONNECTED_C)
  {
#ifdef DEBUG
    Serial.println(F("Brood temp success"));
#endif
  }
  else
  {

#ifdef DEBUG
    Serial.println(F("Brood temp error"));
#endif

    return;
  }

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

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

  if (scale.wait_ready_retry(10)) {
    w = scale.get_units(10);
    delay(500);
  }
  else {
    return;
  }

  scale.power_down();
  delay(1000);

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

}

void 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=\""));
  for (byte k = 0; k < strlen_P(destinationNumber); k++) {
    char_sms = pgm_read_byte_near(destinationNumber + k);
  }
  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
}

void 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=\""));
  for (byte k = 0; k < strlen_P(destinationNumber); k++) {
    char_sms = pgm_read_byte_near(destinationNumber + k);
  }
  mySerial.print(destinationNumber);
  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();
  turnoffsim();

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

/*void web_data() {
  float h = dht.readHumidity();
  delay(500);
  float t = dht.readTemperature();
  delay(500);
  sensors.requestTemperatures();
  delay(500);
  float ht = Celcius = sensors.getTempCByIndex(0);
  delay(500);
  scale.power_up();
  delay(500);
  float w = scale.get_units();
  delay(500);
  scale.power_down();
  delay(500);
  turnonsim();
  mySerial.println("AT+CIPSHUT");
  delay(1000);

  mySerial.println("AT+CIPSTATUS");
  delay(1000);

  mySerial.print("AT+CIPMUX=0");
  delay(1000);

  mySerial.println("AT+CSTT=<cytamobile>,<>,<>");
  delay(1000);

  mySerial.println("AT+CIFSR");
  delay(1000);

  mySerial.println("AT+CIICR");
  delay(1000);

  mySerial.println("AT+CIPSPRT=0");
  delay(1000);

  mySerial.println("AT+CIPSTART=<TCP>,<api.thingspeak.com>,<80>");
  delay(1000);

  mySerial.println("AT+CIPSEND");
  delay(1000);
  String str = "GET https:/api.thingspeak.com/update?api_key=9WBYFTONXVMXMS2H&field1=" + String(h) + "&field2=" + String(t) + "field3=" + String(ht) + "field4=" + String(w) + "field5=" + String(in_voltage, 2);
  mySerial.println(str);
  mySerial.println((char)26);
  delay(4000);
  turnoffsim();
  }*/

void setup() {
  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(1000);
  attachInterrupt(digitalPinToInterrupt(3), emergency_isr, CHANGE);//attaching a interrupt to TILT sensor

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

  setSyncProvider(RTC.get);
  hr = hour();
  set_alarm();
}

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

  hr = hour();

  set_alarm();

  if (measurement) {
    measurement = false;
    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.println(F("Siren"));
#endif

          //digitalWrite(SIREN, HIGH);
          //delay(500);
          //digitalWrite(SIREN, LOW);
          turnonsim();
          mySerial.println(F("ATD+ phone number;"));
          updateSerial();
          delay(10000);
          mySerial.println(F("ATH"));
          updateSerial();
        }
      }
    }
  }
}

 

Last Edited: Thu. Oct 14, 2021 - 05:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again a quick browse though (there's a lot of code here) shows that "Readings completed" marks the end of function Readings().

In all cases function turnonsim() is executed within a few lines of Readings.

 

Now then:  turnonsim() would print "Turning on GSM" as it's first line. You say that doesn't happen therefore your program probably crashes on return from Readings().

You can test this by adding another "Debug Print" on each line after Readings();

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:
You can test this by adding another "Debug Print" on each line after Readings();

 

I did that already and it crashes at the end of readings() function. Do you think that problem may be due to using a function within a function (nested functions)? Within send_sms which is called during loop, other functions are called like readings(), turnonsim() etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sanast wrote:
I did that already and it crashes at the end of readings() function.

 

OK - In that case the readings() function never returns after the debug print "Readings completed". The most likely cause  is stack corruption within readings()

 

The most suspect line I found was:

  if (isnan(h) || isnan(t)) {

Where h and t are 8-bit integers. isnan and friends operate on floats and doubles.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

This whole program reminds me of a bad train wreck

something like

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

Is much simpler & easier to look at  as

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

Why does your program seem a million lines long to do just a couple simple operations??  More places for a typo, more diluted to blur the overall scheme, more scrolling around to miss errors.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. Oct 14, 2021 - 03:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
This whole program reminds me of a bad train wreck

'fraid so.

 

Another:

sanast wrote:

  mySerial.print(F("AT+CMGS=\""));
  for (byte k = 0; k < strlen_P(destinationNumber); k++) {
    char_sms = pgm_read_byte_near(destinationNumber + k); 
  }                                                       
  mySerial.print(destinationNumber);

What is the point of that loop? You never use the char_sms value.

 

And there's still the dreaded Blind Delays:

sanast wrote:

  mySerial.println("AT+CIFSR");
  delay(1000);

  mySerial.println("AT+CIICR");
  delay(1000);

  mySerial.println("AT+CIPSPRT=0");
  delay(1000);

  mySerial.println("AT+CIPSTART=<TCP>,<api.thingspeak.com>,<80>");
  delay(1000);

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

N.Winterbottom wrote:
turnonsim() would print "Turning on GSM" as it's first line. You say that doesn't happen therefore your program probably crashes on return from Readings().

Does the Arduino printing have any buffering?

If it does, the program will have progressed some way before the message appears out of the serial port - so it's possible that it's crashing sometime after the return from Readings()...

 

Note that turning on a GSM module is likely to cause a very large current surge; so, if your power supply and all its associated connections are not good and solid, the supply voltage will drop - which could well cause your system to crash...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
Note that turning on a GSM module is likely to cause a very large current surge; so, if your power supply and all its associated connections are not good and solid, the supply voltage will drop - which could well cause your system to crash...

 

It crashes before trying to turn on the GSM module. I have a 10000uF capacitor next to the GSM module.

 

I have attached the revised code below. The setup function executes without errors. Rarely i do get resets after readings() function. After an RTC alarm interrupt while in the loop, it crashes again and restarts from the beginning. I used within the code a freeRAM arduino library and after the executions of readings() i have about 1100 bytes of free ram. So if this not a memory problem, what can it be? Maybe a serial problem? How can i simplify the code even more?

 


//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);
char response[150];

// Settings for measuring battery level
float adc_voltage = 0.0;
float in_voltage = 0.0;
float R1 = 2589.0;
int R2 = 3000.0;
int ref_voltage = 5.0;
int adc_value = 0.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.00;
float old_w = 0.0;
char difference[10] = "00.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;
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;
}

void emergency_isr() {
  emergency = true;
}

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

void turnonsim() {

#ifdef DEBUG
  Serial.println(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
}

void turnoffsim() {

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

  delay(1000);
  digitalWrite(SIMSWITCH, LOW);
}

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

  digitalWrite(MAINBATSW, HIGH);
  delay(100);
  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(100);

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

void temp() {
  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(500);

  if (scale.wait_ready_retry(10)) {
    w = scale.get_units(10);
    delay(100);
  }
  else {
    return;
  }

  scale.power_down();
  delay(500);

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

}

void send_sms() {

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

  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(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_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 < 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);


  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(19200);
#endif

  mySerial.begin(19200);

#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

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


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

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

void loop() {

  setSyncProvider(RTC.get);

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

  next_rtc_alarm();

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


  if (measurement) {
    measurement = false;

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

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

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you really want to be doing these over and over? Surely they should be done just once in setup()?

 

void loop() {

  setSyncProvider(RTC.get);

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

  next_rtc_alarm();

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

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
Do you really want to be doing these over and over? Surely they should be done just once in setup()?

 

Yes as every time it wakes up it has to set a new alarm for a different time.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see you've split your old readings() into battery(), temp() and weight(). This is good.

Have you determined which of those three causes the crash ?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:
Have you determined which of those three causes the crash ?

 

Yes the weight () function. After the serial monitor prints "Readings completed", it crashes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sanast wrote:
It crashes before trying to turn on the GSM module.

How do you know that? Did you see my comment about buffering?

 

I have a 10000uF capacitor next to the GSM module.

that's good, but not necessarily sufficient.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
How do you know that? Did you see my comment about buffering?

 

Because, the GSM is powered by an LDO which is switched off at the beginning of the sketch and enabled by the MCU after printing in the serial monitor "Turning on GSM". The crash occurs before this event. 

 

How do i know if arduino has any buffering? I am a newbie as this is my first arduino project.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sanast wrote:
How do i know if arduino has any buffering?

That was my question! I don't know - hopefully others can answer ...

 

But you understand how that could mislead ?

 

the GSM is powered by an LDO

Are you sure that LDO is up to managing the peak currents required by the GSM module ?

 

They can be on the order of amps ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
Are you sure that LDO is up to managing the peak currents required by the GSM module ?

 

Yes the LDO is Microchip MIC29302 which is adequate for the needs of the GSM module.

 

Something else i want to point out in relation to buffer of serial. The PCB i use was soldered by me. The PCB has also an FTDI on board with a USB connection. After i upload the sketch to the MCU, i disconnect the USB but the TX, RX lines are still connected between the MCU and FTDI. When awake, the MCU tries to send serial information to the FTDI, however there is no response since the FTDI is powered off. Maybe this can cause a buffer overflow and cause the reset?

 

I will try to remove all serial.print statements from the code and test again.

Last Edited: Fri. Oct 15, 2021 - 09:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sanast wrote:
After i upload the sketch to the MCU, i disconnect the USB but the TX, RX lines are still connected between the MCU and FTDI. When awake, the MCU tries to send serial information to the FTDI, however there is no response since the FTDI is powered off. Maybe this can cause a buffer overflow and cause the reset?

No - it just sends the data; it neither knows nor cares whether anyone's listening!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

sanast wrote:

After i upload the sketch to the MCU, i disconnect the USB but the TX, RX lines are still connected between the MCU and FTDI. When awake, the MCU tries to send serial information to the FTDI, however there is no response since the FTDI is powered off. Maybe this can cause a buffer overflow and cause the reset?

 

No - it just sends the data; it neither knows nor cares whether anyone's listening!

 

I tried it already. Still no fix. After wakeup interrupt the MCU resets. I don't know what else to try. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Probably time to take a few steps back.

 

Start with a simple sketch, build & test just one function at a time.

 

Once you have the functions thoroughly debugged and tested on their own, then start integrating them together.

 

In particular, get the GSM working on its own - without all the other code - and get rid of those Blind Delays.

 

Get the other code working without the GSM.

 

The fewer unknowns you have at once, the better.

 

See: https://www.avrfreaks.net/forum/help-it-doesnt-work

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Oct 15, 2021 - 01:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sanast wrote:
I don't know what else to try.
linter, debugger, logic analyzer

Your program is significant (length) such that code review, a best practice, isn't complete (C's ambiguities are numerous, linters are detectors of ambiguities and known defect patterns)

 

debugWIRE via USB UART | AVR Freaks

 

GitHub - jdolinay/avr_debug: Source level debugger for Arduino - GDB stub for Atmega328 microcontroller used in Arduino Uno.

via avr-stub — PlatformIO 5.2.0a5 documentation

though the size of an AVR GDB stub may be comparable to Arduino's Serial.

 

Troubleshooting real-time software issues using a logic analyzer - Embedded.com

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
Probably time to take a few steps back.

1++

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

Lets go Brandon!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

2++

 

(also confirms the argument for modular code with unit testing!) 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:
The most likely cause  is stack corruption within readings()

Stack Underflow and Overflow Resets | 8-bit PIC® and AVR® MCU Design and Troubleshooting Checklist

[before last paragraph]

Stack Overflow (or Unhandled Interrupt) Detector for AVR®

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After a lot of testing i have found out something. If i reset the MCU, it executes the code normally. If the alarm which triggers the interrupt is within 3 minutes, it wakes up and there is no reset. However, if the alarm is after 10 minutes for example after last reset, the MCU crashes when it wakes up. What can cause such a behaviour?

 

I tried simplifying the code and left out libraries part by part. It seems the issue is not a specific library or code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds like stack overflow (as already noted). 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

Sounds like stack overflow (as already noted). 

 

Is there any process to help me identify the problem?

 

Free ram during the whole sketch is above 1K bytes. How can a stack overflow happen? And why it only occurs after a deep sleep period of 5 min or more? 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could implement a stack usage monitor routine as shown in https://www.avrfreaks.net/forum/soft-c-avrgcc-monitoring-stack-usage, just to insure it is not related to a stack overflow.

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sanast wrote:
Is there any process to help me identify the problem?
Yes to identify the fault (stack overflow); the defect may not be coincident with the fault.

sanast wrote:
How can a stack overflow happen?
Several of the many defects :

  • buffer overflow that clobbers a limit
  • excessive recursion
  • off-by-1 (relational defect)
  • (rare) compiler code generator anomaly

Linters can detect some of these defects.

sanast wrote:
And why it only occurs after a deep sleep period of 5 min or more? 
Brown out and/or over-volt? (a regulator's stability may be dependent on a bit of preload)

 


Defect -> Fault -> Failure

by OCD (maybe) :

Stack Overflow Detection Using Data Breakpoint | Microchip Studio

Detector :

Stack Underflow and Overflow Resets | 8-bit PIC® and AVR® MCU Design and Troubleshooting Checklist (bottom half)

Monitor :

Using the GNU Compiler Collection (GCC): AVR Options

[1/3 page]

-mcall-prologues

Functions prologues/epilogues are expanded as calls to appropriate subroutines. Code size is smaller.

 

"Dare to be naïve." - Buckminster Fuller