Arduino Opla (MKR WiFi 1010) restarts when using the cloud

When I use the cloud my arduino restarts about every 20 seconds. When I disable it (by setting cloud = false) it works perfectly well.
.ino file:

#include "thingProperties.h"
#include "Arduino_APA102.h"
#include <Arduino_MKRIoTCarrier.h>
#include "pitches.h"
MKRIoTCarrier carrier;

int dataPin = 5;
int clockPin = 4;
int totalLEDs = 5;
Arduino_APA102 leds(totalLEDs, dataPin, clockPin);

int pir;
int pirState = 0;
int light = 0;
float Gx, Gy, Gz;

uint32_t redColor = carrier.leds.Color( 0, 150, 0);
uint32_t noColor = carrier.leds.Color( 0, 0, 0);

bool light_event;
bool movement_event;
bool shake_event;

bool enabled = true;
int disabled_time = 0;
int disabled_for = 0;
int screen = 10000;
int old_light = 0;
float old_Gx, old_Gy, old_Gz;
int light_start = 0;

const bool sound = false;
const bool carrier_case = true;

String correct_password = "ab";
int max_seconds = 300;
int pir_sensitivity = HIGH;
int light_sensitivity = 80; // increase to make it less sensitive
int movement_sensitivity = 20; // increase to make it less sensitive
int last_cloud_update = 0;

const bool cloud = true;

// COLOR FORMAT: RRRRRGGGGGGBBBBB (5 bits red, 6 bits green, 5 bits blue)
// 31727 = white
// 31712 = yellow
// 30720 = red
// 992 = green
// 0 = black

void setup() {

  Serial.begin(9600);
  delay(1500);

  if (cloud) {
    initProperties();
    ArduinoCloud.begin(ArduinoIoTPreferredConnection);
    setDebugMessageLevel(4);

    ArduinoCloud.printDebugInfo();

    while (ArduinoCloud.connected() != 1) {
      Serial.println("Cloud");
      ArduinoCloud.update();

    }
  } else {
    light_alarm = true;
    movement_alarm = true;
    shake_alarm = true;
    stuck = false;
    message_update = "";
  }
  message_update.reserve(100);

  delay(500);
  CARRIER_CASE = carrier_case;
  carrier.begin();
  pir = carrier.getBoardRevision() == 1 ? A5 : A0;
  carrier.display.setRotation(0);
  carrier.display.fillScreen(31727);
  carrier.display.setCursor(20, 100);
  carrier.display.setTextColor(ST77XX_BLACK);
  carrier.display.setTextSize(2);

  while (!carrier.Light.colorAvailable()) {
    delay(5);
  }
  int none;
  carrier.Light.readColor(none, none, none, light);
  old_light = light;
  carrier.IMUmodule.readGyroscope(old_Gx, old_Gy, old_Gz);

  leds.begin();

  delay(1500);
  pinMode(pir, INPUT);


}

void loop() {
  if (cloud && last_cloud_update + 30 * 1000 < millis()) {
    ArduinoCloud.update();
    last_cloud_update = millis();
    Serial.println("Cloud update");
  }

  Serial.println("\nEnable: ");
  Serial.println(enabled);
  Serial.println("Time now: ");
  Serial.println(millis());
  Serial.println("Disabled time: ");
  Serial.println(disabled_time);
  Serial.println("Disabled for: ");
  Serial.println(disabled_for);
  Serial.println("Enable time: ");
  Serial.println(disabled_time + disabled_for * 1000);
  Serial.println("Values:");
  Serial.println(light_alarm);
  Serial.println(movement_alarm);
  Serial.println(shake_alarm);

  if (!enabled && millis() > disabled_time + disabled_for * 1000) {
    Serial.println("Enabling 105");
    enabled = true;
    leds.setPixelColor(0, 0, 0, 0);
    leds.setPixelColor(1, 0, 0, 0);
    leds.setPixelColor(2, 0, 0, 0);
    leds.setPixelColor(3, 0, 0, 0);
    leds.setPixelColor(4, 0, 0, 0);
    leds.show();
    light_start = millis();
  } else if (millis() <= disabled_time + disabled_for * 1000) {
    enabled = false;
    Serial.println("Disabling 109");
  }

  if (enabled && screen != 0) {
    screen = 0;
    carrier.display.fillScreen(31727);
    carrier.display.setTextColor(ST77XX_BLACK);
    carrier.display.setCursor(80, 105);
    carrier.display.print("Enabled");
    carrier.display.setCursor(105, 10);
    carrier.display.print("1m");
    carrier.display.setCursor(20, 70);
    carrier.display.print("5m");
    carrier.display.setCursor(190, 70);
    carrier.display.print("10s");
    carrier.display.setCursor(30, 170);
    carrier.display.print("10m");
    carrier.display.setCursor(160, 170);
    carrier.display.println("ENBL");
  }
  else if (!enabled && screen != 1) {
    screen = 1;
    carrier.display.fillScreen(ST77XX_BLACK);
    carrier.display.setTextColor(31727);
    carrier.display.setCursor(70, 105);
    carrier.display.print("Disabled");
    carrier.display.setCursor(105, 10);
    carrier.display.print("1m");
    carrier.display.setCursor(20, 70);
    carrier.display.print("5m");
    carrier.display.setCursor(190, 70);
    carrier.display.print("10s");
    carrier.display.setCursor(30, 170);
    carrier.display.print("10m");
    carrier.display.setCursor(160, 170);
    carrier.display.println("ENBL");
  }

  if (millis() > light_start + 30 * 1000) {
    leds.setPixelColor(0, 0, 0, 0);
    leds.setPixelColor(1, 0, 0, 0);
    leds.setPixelColor(2, 0, 0, 0);
    leds.setPixelColor(3, 0, 0, 0);
    leds.setPixelColor(4, 0, 0, 0);
    leds.show();
  }

  pirState = digitalRead(pir);

  while (!carrier.Light.colorAvailable()) {
    delay(5);
  }
  int none;
  carrier.Light.readColor(none, none, none, light);

  old_Gx = Gx;
  old_Gy = Gy;
  old_Gz = Gz;
  carrier.IMUmodule.readGyroscope(Gx, Gy, Gz);

  Serial.print("Gyroscope:");
  Serial.print(" X: ");
  Serial.print(Gx);
  Serial.print(" Y: ");
  Serial.print(Gy);
  Serial.print(" Z: ");
  Serial.println(Gz);
  Serial.print("Old gyroscope:");
  Serial.print(" X: ");
  Serial.print(old_Gx);
  Serial.print(" Y: ");
  Serial.print(old_Gy);
  Serial.print(" Z: ");
  Serial.println(old_Gz);

  Serial.print("Light: ");
  Serial.println(light);
  Serial.print("Old light: ");
  Serial.println(old_light);

  Serial.print("PIR State: ");
  Serial.println(pirState);

  Serial.println(millis());
  Serial.println(disabled_time + disabled_for * 1000);

  if (enabled) {
    if (light_alarm == true) {
      if (light - old_light > light_sensitivity) {
        light_event = true;
        message_update = "Light alarm breached!";
      }
    }
    if (movement_alarm == true) {
      if (pirState == pir_sensitivity) {
        movement_event = true;
        message_update = "Movement alarm breached!";
      }
    }
    if (shake_alarm == true) {
      if (abs(Gx - old_Gx) > movement_sensitivity || abs(Gy - old_Gy) > movement_sensitivity || abs(Gz - old_Gz) > movement_sensitivity) {
        shake_event = true;
        message_update = "Shake alarm breached!";
      }
    }
  }
  old_light = light;

  bool event = light_event || movement_event || shake_event;
  if (event) {
    if (sound) {
      carrier.Buzzer.sound(500);
    }
    if (cloud) {
      ArduinoCloud.update();
    }
    int start = millis();
    String to_send = "";
    to_send.reserve(100);
    Serial.println(message_update);
    while (millis() < start + max_seconds * 1000) {
      to_send = "";
      String password = "";
      password.reserve(100);
      int letters = 0;
      screen = 2;
      carrier.display.fillScreen(31712);
      carrier.display.setCursor(90, 90);
      carrier.display.print("Enter");
      carrier.display.setCursor(70, 110);
      carrier.display.print("password:");
      carrier.display.setCursor(118, 10);
      carrier.display.print("b");
      carrier.display.setCursor(20, 70);
      carrier.display.print("a");
      carrier.display.setCursor(210, 70);
      carrier.display.print("c");
      carrier.display.setCursor(30, 170);
      carrier.display.print("DEL");
      carrier.display.setCursor(175, 170);
      carrier.display.println("END");

      leds.setPixelColor(0, 0, 0, 0);
      leds.setPixelColor(1, 0, 0, 0);
      leds.setPixelColor(2, 0, 0, 0);
      leds.setPixelColor(3, 0, 0, 0);
      leds.setPixelColor(4, 0, 0, 0);
      leds.show();

      while (millis() < start + max_seconds * 1000) {
        carrier.Buttons.update();
        if (carrier.Buttons.onTouchDown(TOUCH0)) {
          String new_password = "";
          new_password.reserve(100);
          for (int i = 0; i < letters - 1; i++) {
            new_password += password[i];
          }
          password = new_password;
          carrier.display.fillScreen(31712);
          carrier.display.setCursor(90, 90);
          carrier.display.print("Enter");
          carrier.display.setCursor(70, 110);
          carrier.display.print("password:");
          carrier.display.setCursor(70, 130);
          carrier.display.print(password);
          carrier.display.setCursor(118, 10);
          carrier.display.print("b");
          carrier.display.setCursor(20, 70);
          carrier.display.print("a");
          carrier.display.setCursor(210, 70);
          carrier.display.print("c");
          carrier.display.setCursor(30, 170);
          carrier.display.print("DEL");
          carrier.display.setCursor(175, 170);
          carrier.display.println("END");
          leds.setPixelColor(0, 150, 150, 150);
          leds.setPixelColor(1, 0, 0, 0);
          leds.setPixelColor(2, 0, 0, 0);
          leds.setPixelColor(3, 0, 0, 0);
          leds.setPixelColor(4, 0, 0, 0);
          leds.show();
          letters--;
          Serial.println(password);
        }
        if (carrier.Buttons.onTouchDown(TOUCH1)) {
          password += "a";
          carrier.display.setCursor(70 + 12 * letters, 130);
          carrier.display.print("a");
          leds.setPixelColor(1, 150, 150, 150);
          leds.setPixelColor(0, 0, 0, 0);
          leds.setPixelColor(2, 0, 0, 0);
          leds.setPixelColor(3, 0, 0, 0);
          leds.setPixelColor(4, 0, 0, 0);
          leds.show();
          letters++;
          Serial.println(password);
        }
        if (carrier.Buttons.onTouchDown(TOUCH2)) {
          password += "b";
          carrier.display.setCursor(70 + 12 * letters, 130);
          carrier.display.print("b");
          leds.setPixelColor(2, 150, 150, 150);
          leds.setPixelColor(0, 0, 0, 0);
          leds.setPixelColor(1, 0, 0, 0);
          leds.setPixelColor(3, 0, 0, 0);
          leds.setPixelColor(4, 0, 0, 0);
          leds.show();
          letters++;
          Serial.println(password);
        }
        if (carrier.Buttons.onTouchDown(TOUCH3)) {
          password += "c";
          carrier.display.setCursor(70 + 12 * letters, 130);
          carrier.display.print("c");
          leds.setPixelColor(3, 150, 150, 150);
          leds.setPixelColor(0, 0, 0, 0);
          leds.setPixelColor(1, 0, 0, 0);
          leds.setPixelColor(2, 0, 0, 0);
          leds.setPixelColor(4, 0, 0, 0);
          leds.show();
          letters++;
          Serial.println(password);
        }
        if (carrier.Buttons.onTouchDown(TOUCH4)) {
          Serial.println("end");
          leds.setPixelColor(4, 150, 150, 150);
          leds.setPixelColor(0, 0, 0, 0);
          leds.setPixelColor(1, 0, 0, 0);
          leds.setPixelColor(2, 0, 0, 0);
          leds.setPixelColor(3, 0, 0, 0);
          leds.show();
          to_send = password;
          break;
        }
        delay(300);
      }
      if (to_send == "") {
        to_send = password;
      }
      Serial.println("\nPassword: ");
      Serial.println(to_send);
      Serial.println("Correct password: ");
      Serial.println(correct_password);
      carrier.display.setTextColor(31727);
      carrier.display.setTextSize(3);
      if (to_send == correct_password) {
        screen = 3;
        message_update = "";
        carrier.display.fillScreen(992);
        carrier.display.setCursor(60, 100);
        carrier.display.print("Correct");
        carrier.display.setTextColor(ST77XX_BLACK);
        carrier.display.setTextSize(2);
        carrier.Buzzer.noSound();
        delay(4000);
        leds.setPixelColor(0, 0, 0, 0);
        leds.setPixelColor(1, 0, 0, 0);
        leds.setPixelColor(2, 150, 150, 150);
        leds.setPixelColor(3, 0, 0, 0);
        leds.setPixelColor(4, 0, 0, 0);
        leds.show();
        light_start = millis();
        break;
      } else {
        screen = 4;
        carrier.display.fillScreen(30720);
        carrier.display.setCursor(75, 100);
        carrier.display.print("Wrong");
        carrier.display.setTextColor(ST77XX_BLACK);
        carrier.display.setTextSize(2);
        if (sound) {
          carrier.Buzzer.sound(500);
        }
        delay(4000);
      }
    }
    if (to_send != correct_password) {
        stuck = true;
        if (cloud) {
          ArduinoCloud.update();
        }
        while (true) {
          leds.setPixelColor(0, 150, 0, 0);
          leds.setPixelColor(1, 150, 0, 0);
          leds.setPixelColor(2, 150, 0, 0);
          leds.setPixelColor(3, 150, 0, 0);
          leds.setPixelColor(4, 150, 0, 0);
          leds.show();
          delay(10000);
        }
    }
    enabled = false;
    Serial.println("Disabling 204");
    disabled_time = millis();
    disabled_for = 60;
    event = false;
    light_event = false;
    movement_event = false;
    shake_event = false;
  }

  delay(200);
  carrier.Buttons.update();

  // Normal events
  if (!event) {
    if (carrier.Buttons.onTouchDown(TOUCH0)) {
      disabled_for = 10 * 60;
      disabled_time = millis();
      leds.setPixelColor(0, 150, 150, 150);
      leds.setPixelColor(1, 0, 0, 0);
      leds.setPixelColor(2, 0, 0, 0);
      leds.setPixelColor(3, 0, 0, 0);
      leds.setPixelColor(4, 0, 0, 0);
      leds.show();
      light_start = millis();
    }
    if (carrier.Buttons.onTouchDown(TOUCH1)) {
      disabled_for = 5 * 60;
      disabled_time = millis();
      leds.setPixelColor(0, 0, 0, 0);
      leds.setPixelColor(1, 150, 150, 150);
      leds.setPixelColor(2, 0, 0, 0);
      leds.setPixelColor(3, 0, 0, 0);
      leds.setPixelColor(4, 0, 0, 0);
      leds.show();
      light_start = millis();
    }
    if (carrier.Buttons.onTouchDown(TOUCH2)) {
      disabled_for = 1 * 60;
      disabled_time = millis();
      leds.setPixelColor(0, 0, 0, 0);
      leds.setPixelColor(1, 0, 0, 0);
      leds.setPixelColor(2, 150, 150, 150);
      leds.setPixelColor(3, 0, 0, 0);
      leds.setPixelColor(4, 0, 0, 0);
      leds.show();
      light_start = millis();
    }
    if (carrier.Buttons.onTouchDown(TOUCH3)) {
      disabled_for = 10;
      disabled_time = millis();
      leds.setPixelColor(0, 0, 0, 0);
      leds.setPixelColor(1, 0, 0, 0);
      leds.setPixelColor(2, 0, 0, 0);
      leds.setPixelColor(3, 150, 150, 150);
      leds.setPixelColor(4, 0, 0, 0);
      leds.show();
      light_start = millis();
    }
    if (carrier.Buttons.onTouchDown(TOUCH4)) {
      disabled_for = 0;
      enabled = true;
      Serial.println("Enabling 238");
      leds.setPixelColor(0, 0, 0, 0);
      leds.setPixelColor(1, 0, 0, 0);
      leds.setPixelColor(2, 0, 0, 0);
      leds.setPixelColor(3, 0, 0, 0);
      leds.setPixelColor(4, 150, 150, 150);
      leds.show();
      light_start = millis();
    }
  }
}

void onLightAlarmChange() {
  Serial.println("somehting works");
}
void onMovementAlarmChange()  {
  Serial.println("somehting works");
}
void onShakeAlarmChange()  {
  Serial.println("somehting works");
}

thiingProperties.h:

// Code generated by Arduino IoT Cloud, DO NOT EDIT.

#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>

const char SSID[]     = SECRET_SSID;    // Network SSID (name)
const char PASS[]     = SECRET_OPTIONAL_PASS;    // Network password (use for WPA, or use as key for WEP)

void onLightAlarmChange();
void onMovementAlarmChange();
void onShakeAlarmChange();

String message_update;
bool light_alarm;
bool movement_alarm;
bool shake_alarm;
bool stuck;

void initProperties(){

  ArduinoCloud.addProperty(message_update, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(light_alarm, READWRITE, ON_CHANGE, onLightAlarmChange);
  ArduinoCloud.addProperty(movement_alarm, READWRITE, ON_CHANGE, onMovementAlarmChange);
  ArduinoCloud.addProperty(shake_alarm, READWRITE, ON_CHANGE, onShakeAlarmChange);
  ArduinoCloud.addProperty(stuck, READ, ON_CHANGE, NULL);

}

WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);

Any help would be greatly appreciated.

1 Like

Hi @ktothehacker.

I think this code is your problem. In order to allow your Arduino IoT Cloud Things to automatically recover from a hang, the ArduinoIoTCloud library includes a "watchdog timer". This automatically resets your board if 16000 ms pass without ArduinoCloud.update() being called:

https://docs.arduino.cc/arduino-cloud/getting-started/technical-reference#watchdog-timer-wdt

You should call ArduinoCloud.update() on every iteration of the loop function and also be careful not to have any code in your sketch that will cause the loop function execution to be blocked for a significant amount of time.

In case that really isn't possible, you can disable the watchdog timer by following the instructions at the link above, but you should be aware that if you don't call ArduinoCloud.update() frequently, it will impact the responsiveness of Arduino IoT Cloud to your Thing.

3 Likes

Thanks a lot. This was the problem. The code was added because it was restarting and I thought that maybe it was calling the cloud very often. This wasn't the only part of the code that had this problem. There is a loop that will run for 300 seconds inside loop that was causing the restarts. I can't thank you enough. I had spent 5 hours trying to solve this problem.

2 Likes

You are welcome. I'm glad it is working now. Nice work on spotting the blocking part of your code!

Regards,
Per

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.