Yun possibly crashing from arduino sketch/ need help optimizing the sketch

Hi, i am currently making a sketch that will move servo and take a picture when a reed switch is open or a PIR detects motion but i am currently running into an issue that it will loop (main_alarm()) a few times then it just stops working which i need to turn off the power to the board then back on. I think the issue is the board is doing too much at once but i need a second opinion and any solutions you might have

Also i am using a website i made to turn on/off the board and also rotate servos

Thanks, also below is the current code i am using

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <Process.h>
#include <Servo.h>
#include <SPI.h>

const int DoorReed = 2;
const int WindowReed = 3;
int Buzzer = 8;
int pir_right = 4;
int pir_center = 7;
int pir_left = 9;

Process stream; //check
Process picture;
String filename;

String path = "/mnt/sda1/arduino";

YunServer server;
Servo PanServo;
Servo TiltServo;

void setup() {

  PanServo.attach(5);
  TiltServo.attach(6);
  Bridge.begin();
  server.listenOnLocalhost();
  server.begin();
  Console.begin();
  pinMode(Buzzer, OUTPUT);
  pinMode(DoorReed, INPUT);
  pinMode(WindowReed, INPUT);
  pinMode(pir_right, INPUT);
  pinMode(pir_center, INPUT);
  pinMode(pir_left, INPUT);
  stream.runShellCommand("/etc/init.d/mjpg-streamer start");
}

void loop() {

     
      YunClient client = server.accept();

    if (client) {
      process(client);
      client.stop();
    }
    delay(20);
    
  }


 
  void process(YunClient client) {
    String command = client.readStringUntil('/');

    if (command == "servo") {
      servoCommand(client);
    }

  }

  void servoCommand(YunClient client) {
    int pin, value;

    pin = client.parseInt();

    if (client.read() == '/') {
      value = client.parseInt();

      if (pin == 5)
      {
        Console.println(F("Servo P"));
        PanServo.write(value);
      }

      else if (pin == 6)
      {
        Console.println(F("Servo T"));
        TiltServo.write(value);        
      }
      else if (pin == 99)
      {
        Console.println(F("Servo C"));
        PanServo.write(value);
        TiltServo.write(value);        
      }
      else if (pin == 1) //Alarm On
      {
        Console.println(F("Alarm On"));
      digitalWrite(Buzzer, HIGH);
      delay(50);
      digitalWrite(Buzzer, LOW);
      delay(50);
                main_alarm();
      }
      else if (pin == 0) //Alarm Off
      {
        Console.println(F("Alarm Off"));
      digitalWrite(Buzzer, LOW);
      delay(150);
      digitalWrite(Buzzer, HIGH);
      delay(150);
      digitalWrite(Buzzer, LOW);
      delay(50);
loop();       
      }
    }

  }


  void main_alarm() {
Console.println(F("Alarm Active"));
    if (digitalRead(DoorReed) == 1)
    {
      Console.println(F("Alarm Active, Door Open"));
      PanServo.write(120); //need to change
      TiltServo.write(60); //need to change
      delay(500);
      AlarmTriggered();
    }
    
    if (digitalRead(WindowReed) == 1)
    {
      Console.println(F("Alarm Active, Window Open"));
      PanServo.write(120); //need to change
      TiltServo.write(60); //need to change
      delay(500);     
  AlarmTriggered();
      }
      
      if (digitalRead(pir_left) == true)
      { 
Console.println(F("Alarm Active, motion detected at left of house"));
      PanServo.write(120); //need to change
      TiltServo.write(60); //need to change
      delay(500);
  AlarmTriggered();
    }
    
    if (digitalRead(pir_center) == true)
      { 
Console.println(F("Alarm Active, motion detected at center of house"));
      PanServo.write(120); //need to change
      TiltServo.write(60); //need to change
      delay(500);
  AlarmTriggered();
    }
    
    if (digitalRead(pir_right) == true)
      { 
Console.println(F("Alarm Active, motion detected at right of house"));
      PanServo.write(120); //need to change
      TiltServo.write(60); //need to change
      delay(500);
  AlarmTriggered();
    }
     
     Console.println(F("Alarm Active, Still Scanning")); 
           YunClient client = server.accept();

    if (client) {
      process(client);
      client.stop();
    }
    delay(500);
//   main_alarm();
    
  }

void AlarmTriggered(){
  stream.runShellCommand("/etc/init.d/mjpg-streamer stop");
  delay(1000);
    filename = "";
    picture.runShellCommand("date +%s");
    while(picture.running());

    while (picture.available()>0) {
      char c = picture.read();
      filename += c;
    } 
    filename.trim();
    filename += ".png";
 
    picture.runShellCommand("fswebcam " + path + filename + " -r 1280x720");
    while(picture.running());
    delay(1000);
    stream.runShellCommand("/etc/init.d/mjpg-streamer start");
    delay(200);
    digitalWrite(Buzzer, HIGH);
    Console.println(F("Picture taken")); 
  main_alarm();  
}

You seem to have circular references. For example main_alarm() calls AlarmTriggered() which calls main_alarm().

That will quickly cause you to run out of memory.

I suspect you think it is necessary to call the parent function at the end of a function. It is not. When a function gets to the end of its code it automatically returns to the calling function at the point from which it was called.

And, if you are trying to get a different sequence to the flow of code you are not doing it the correct way.

...R

I agree with Robin, all of your alarm processing is happening inside the call to process the client alarm on command: once the alarm is on, you are stetting up your own loop to keep calling main_alarm(), but the context for the original process(client) call is still active on the stack. Then inside main_alarm(), you once again call process(client) which can call main_alarm() again. At that point, the stack still has the context for the original process(client) call, the original main_alarm() call, and the second process(client) and main_alarm() calls. The functions never return to unwind the stack: the stack just keeps getting deeper and deeper until it overflows and the program crashes.

You need a Boolean flag to control whether the alarm is on or off. Then inside process(client), rather than call main_alarm(), set or clear the flag to turn the alarm on or off - do not call main_alarm inside process(client). Instead, in loop(), add an if statement to check if the alarm on flag is set, and call main_alarm() there.

Finally, alarm_trggered() must not call main_alarm(), and main_alarm() must not call process(client).

The general idea is that loop() should make one pass through your code and return. It should not keep looping on its own, that will be done automatically by loop() getting called over and over. process(client) should only handle the incoming commands, do what it needs to do (like move a servo or set a flag) and then get out. Similarly, main_alarm() should make one pass through the logic to check the sensors, and then get out.

Hi, thanks for you help i changed my code around getting rid of what you said and it is now working. Thanks