Unexpected Restart

Hey all,

Got a new little problem. I am trying to do a serial read and a bunch of other stuff and it causes the arduino to reset. There is no command in there for a software reset (and to my knowledge there is no such thing anyway) any ideas on what might cause this behavior? vector overflow? something having to do with memory usage? i searched the forum and was unable to find anyone with a similar issue.

Thanks
Dan

Most causes of unexpected resets are power related. However software errors could cause the sketch to jump into the tall weeds and case rabbits. Posting your code and maybe a drawing of your wiring might help someone figure it out for you.

Lefty

Thanks for the reply, the code is big so hold on...

//LIBRARY DECLARATIONS
  
  //FOR PID CONTROL
      #include <PID_v1.h>  //PID Libarary
  //FOR PID CONTROL


  //For Motor Control
      #include <ServoTimer2.h>  // the servo library
  //For Motor Control

//LIBRARY DECLARATIONS



int dan1=0;
//ULTRASONIC RANGEFINDER VARIABLES

int rangepin=7;


//ULTRASONIC RANGEFINDER VARIABLES

//EXPERIMENTAL Low Level Flight Control Var

int desiredalt=24;  //Desired altitude in inches
int altthrottlebias=0;


//EXPERIMENTAL Low Level Flight Control Var




//Global Variable Declarations
  
  //GUIDANCE CONTROL TEST VARIABLES
     // double pitchval;
      double PitchBias;
     // double rollval;
      double RollBias;
  //GUIDANCE CONTROL TEST VARIABLES

//FOR MOTOR CONTROL
// define the pins for the servos
#define rollPin  5
#define pitchPin 4
#define yawPin   3
#define danPin   2

ServoTimer2 servoRoll;    // declare variables for up to eight servos
ServoTimer2 servoPitch;
ServoTimer2 servoYaw;
ServoTimer2 servoDan;
int spd1;  //Motor control numbers go Counter clock wise from nose
int spd2;
int spd3;
int spd4;
//FOR MOTOR CONTROL


//FOR PID CONTROL
  double Setpoint, Input, Output;
  double Setpointalt,Inputalt,Outputalt;
  PID myPID(&Input, &Output, &Setpoint,2,5,1,DIRECT);
  PID AltPID(&Inputalt, &Outputalt, &Setpointalt,2,5,1,DIRECT);
//FOR PID CONTROL






//AHRS GLOBAL VARIABLE DECLARATIONS

char incoming=-1;
int counta=0;
int count=0;
float rollval;
float pitchval;
float yawval;
char checker=-1;
int searchcount=0;
int chrrecord;
int chrcheck;
char commacheck=0;
char rollstring[8]="";
char pitchstring[8]="";
char yawstring[8]="";
int invaliddata=0;
int mastercountercheck=0;
int incomingcheck=0;
//AHRS GLOBAL VARIABLE DECLARATIONS





 void setup()
{

 
   
   
  Serial.begin(57600);  //DATA OUTPUT STREAM
  Serial1.begin(57600);  //AHRS DATA INPUT STREAM
  Serial3.begin(4800);  //GPS DATA INPUT STREAM
 Serial.println("Arduino Reset");
 //FOR PID CONTROL
  myPID.SetMode(AUTOMATIC);  //Activates the PID Subroutine
  AltPID.SetMode(AUTOMATIC);  //Activates the low level Altitude control PID Subroutine
  myPID.SetOutputLimits(-25,25);  //Sets a Throttle Bias of +-25% as maximum (values converted to percentage later in prog)
  AltPID.SetOutputLimits(-50,50);  //Sets a Throttle Bias of +-50% as maximum (values converted to percentage later in prog)
//FOR PID CONTROL
  
  
//FOR MOTOR CONTROLLER
  servoRoll.attach(rollPin);     // attach a pin to the servos and they will start pulsing
  servoPitch.attach(pitchPin);
  servoYaw.attach(yawPin);
  servoDan.attach(danPin);
  delay(5000);
  
  servoRoll.write(1000);  //Sends Activation Signal to ESC's
  servoPitch.write(1000);  //Sends Activation Signal to ESC's
  servoYaw.write(1000);  //Sends Activation Signal to ESC's
  servoDan.write(1000);  //Sends Activation Signal to ESC's
  delay(3000);  //Delay to make sure that all ESC's have recieved signal
  
  servoRoll.write(1350);  //Sends Activation Signal to ESC's
  servoPitch.write(1350);  //Sends Activation Signal to ESC's
  servoYaw.write(1350);  //Sends Activation Signal to ESC's
  servoDan.write(1350);  //Sends Activation Signal to ESC's
  delay(5000);  //Waits for people to clear before idling motors (5s)
//FOR MOTOR CONTROLLER

}



 void loop()
 {
  gpsgo=0;
 
 //while(dan1==0)
 //{







//AHRS DATA READ CODE
mastercountercheck=0;

 for (int mastercounter=0;mastercounter<=50;mastercounter++)  //provides a ratio of AHRS reads/corrects to altitude and GPS reads/corrects
  {

    
rollval=0;  //Cleans roll data
pitchval=0;  //Cleans pitch data
yawval=0;  //Cleans yaw data

   
 char dataset[35]="";  //initiallizes the AHRS data storage string
 
 count=0;  //Zeros out the counter for reading in the AHRS data
 incoming=-1;  //Sets the incoming byte to a null value
    while (incoming!='X' && count<=30)  //Ends the Serialread function if an X is detected (end of data) or an overflow is imminent
    {
      incomingcheck++;
      Serial.println(incomingcheck);
      if (Serial1.available()>0)
      {
        incoming=Serial1.read();     // Read a byte of the serial port
        dataset[count]=incoming;  //add the incoming byte into dataset
        count++;  
        
      }
      else
      {
 Serial.println("Serial Unavailable");       
        
      }
    }
incomingcheck=0;
    chrcheck=5;  //Starts looking for data after the header
    commacheck=0;  //Zeros out the comma found trigger
    invaliddata=0;  //moves invalid data to the null position (data valid)
 
  if (dataset[0]=='!')  //looks for initial part of header
  {
    if (dataset[4]==':')  //Looks for trailing part of header
    {
      chrrecord=0;  //Sets the begining of the recieving string
      
      while(commacheck==0)  //runs until first commma is found
      {
      rollstring[chrrecord]=dataset[chrcheck];  //copies the data from dataset into rollstring
       chrcheck++;
       chrrecord++;
       
        if(dataset[chrcheck]==',')  //Check to see if a comma was found
        {
         commacheck=1;  //comma found 
        chrcheck++; 
        chrrecord=0;
        }
        
        if (chrrecord>12)  //if a comma cannot be found by this point then the data is invalid (THIS CONDITION ONLY WORKS FOR THE FIRST COMMA)
        {
          commacheck=1;  //uses the already existing trigger to exit the loop
          invaliddata=1;  //Activates the invalid data trigger
        }
      }
        commacheck=0;
        
        while(commacheck==0)  //runs until first commma is found
      {
      pitchstring[chrrecord]= dataset[chrcheck];
       chrcheck++;
       chrrecord++;
       
        if(dataset[chrcheck]==',')
        {
        
         commacheck=1;
        chrcheck++; 
        chrrecord=0;
        }
        if (chrrecord>20)  //if a comma cannot be found by this point then the data is invalid (THIS CONDITION ONLY WORKS FOR THE SECOND COMMA)
        {
          commacheck=1;  //uses the already existing trigger to exit the loop
          invaliddata=1;  //Activates the invalid data trigger
        }
        }
       commacheck=0;
         
        while(commacheck==0)
      {
       yawstring[chrrecord]=dataset[chrcheck];
       chrcheck++;
       chrrecord++;
       
        if(dataset[chrcheck]=='X')
        {
         commacheck=1;
       
        }
        
        if (chrrecord>28)  //if the X cannot be found by this point then the data is invalid (THIS CONDITION ONLY WORKS FOR THE END)
        {
          commacheck=1;  //uses the already existing trigger to exit the loop
          invaliddata=1;  //Activates the invalid data trigger
        }
        }
        }
         else
    {
      invaliddata=1;
      
    }
    }
    else
    {
      invaliddata=1;
      
    }
    
  


rollval=atof(rollstring);
yawval=atof(yawstring);
pitchval=atof(pitchstring);

 Serial.println(dataset);




Serial.print("Roll: ");
Serial.println(rollval);
Serial.print("Yaw: ");
Serial.println(yawval);
Serial.print("Pitch: ");
Serial.println(pitchval);
Serial.println(mastercounter);
if (invaliddata==1)

{
 Serial.println("Invalid Data"); 
}
//Serial.println(memavail);

//Serial.println(rollstring);


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

//AHRS DATA READ CODE

 if (invaliddata==0)  //Only runs the PID routine if the AHRS data is valid
 {
//PID CONTROL ALGORITHITHM (PITCH CONTROL)
  Input=pitchval;  //Input Value for Pitch 
  Setpoint=0;  //Desired Pitch Angle 
  myPID.Compute();  //Executes PID command
  PitchBias=Output;  //Transfers PID solution into the PITCH bias value
  PitchBias=PitchBias/100;  //Converts the bias to decimal value 
  spd1=spd1+(spd1*PitchBias);  //Sets motor1 Speed to include Bias
  spd3=spd3-(spd3*PitchBias);  //Sets motor3 Speed to include Bias
//PID CONTROL ALGORITHITHM>

//PID Control (Allows Re-use of PID) zeros all values to get a clean PID run
Input=0;
Setpoint=0;
Output=0;
//PID Control (Allows Re-use of PID) zeros all values to get a clean PID run



//PID CONTROL ALGORITHITHM (ROLL CONTROL)
  Input=rollval;  //Input Value for Roll 
  Setpoint=0;  //Desired Bank Angle 
  myPID.Compute();  //Executes PID command
  RollBias=Output;  //Transfers PID solution into the ROLL bias value
  RollBias=RollBias/100;  //Converts the bias to decimal value 
  spd2=spd2+(spd2*RollBias);   //Sets motor2 Speed to include Bias
  spd4=spd4+(spd4*RollBias);   //Sets motor4 Speed to include Bias
//PID CONTROL ALGORITHM


//Update roll, pitch, yaw values to the motors
   servoRoll.write(spd1);
   servoPitch.write(spd2);
   servoYaw.write(spd3);
   servoDan.write(spd4);
//Update roll, pitch, yaw values to the motors

 }
 Serial.println("Loop Completed");
mastercountercheck++;
  }  //End "MasterCounter" loop
  Serial.println("Loop Exit");

the part that seems to trip it up is the part in the mastercounter for loop... it will read successfully from the AHRS like 6 times and then reset....

I butchered the code to make it fit in the post but left the part failing in tact I believe.

Also currently the board is powered by USB, and the AHRS chip is powered by usb as well, on a separate usb port...

Ok so I did some checking and this definitely does not appear to be a hardware issue. Something in software having to do with reading serial data is causing this. if the AHRS chip does not transmit the arduino will not reset. it will just transmit serial unavailable until told to stop so it definitely seems that something having to do with reading in data is causing this... does anybody know what could do that?

There is likely a buffer overflow occurring. Not that I think this is the issue, but rollstring is 8 bytes long and your check chrrecord>12 permits you to write past its end if a comma is missing or corrupted in the input. If you could refactor the parsing of each the three strings into a function, it might make it clearer what is happening. As is, you're relying fairly heavily on the string appearing exactly as you expect.

Your parsing code needs a serious overhaul. There is a perfectly good function, strtok() that can be used to find tokens. It's been thoroughly tested under all kinds of conditions for more than 30 years. I'm pretty sure all of the bugs have been worked out of it. Can you say the same for your code?

You need to create functions for perform some of the task that you are now performing in loop(). In a program of any complexity, and this code certainly qualifies, loop() should be doing little more than calling a handful of functions.

Tools + Auto Format... would make it much easier to read your code.

Sorry about the formatting I didnt even know about the auto format. As for the chrrecord issue, the if statement should have been for chrcheck, because if it couldnt find a comma by the 12th character it was a garbage signal... I corrected that but the problem is still persisting I am trying to narrow where the problem occurs as paul mentioned it is most likely in the parsing section. But i was curious if when it opens the serial comm to talk back to my PC can that cause the reset that arduino does before an upload?

I'm betting it's the servos that are the cause. They love to do crazy things like suck all the power they can get. Not sure how you are powering this, but trying to run 4 servos at once from the Arduino directly probably won't work. When your setup code runs the servos start up in series with delays between, which shouldn't be an issue since only 1 is probably on at a time. When you get into the mastercontrol loop however you are trying to update them immediately without delay, which will result in them being all "on" at the same time. Depending on position and how far they have to move etc... could be the defining factor of how many loops you make it through before it dies.

Do a quick test and comment out the servo update statements:

//Update roll, pitch, yaw values to the motors
   servoRoll.write(spd1);
   servoPitch.write(spd2);
   servoYaw.write(spd3);
   servoDan.write(spd4);
//Update roll, pitch, yaw values to the motors

Or even just try running the code without the servo connected to the Arduino.

willnue

But i was curious if when it opens the serial comm to talk back to my PC can that cause the reset that arduino does before an upload?

When the Arduino opens the serial port, it does not reset. How could it? If it reset when it did the Serial.begin(), it would start setup() again, and call Serial.begin() again, which would cause a reset and start the process over again.

When the PC opens the serial connection, that DOES trigger a reset of the Arduino.

Well here was the deal. Paul pretty much called it, parsing=junk. I tracked the error to the data parsing section of my code, I read up on strtok() and rewrote it from scratch. That fixed the issue. Im not sure what was causing the restart in that area but it doesnt matter because the new code is quicker and more reliable thanks for the help everyone.

Dan