Arduino上的意外程序停止

时间:2012-04-25 16:16:47

标签: c++ arduino microcontroller

我有一个问题,我的Arduino程序无缘无故地挂起。我运行我的程序,并在某个未确定的点,串行监视器停止打印输出。这是我到目前为止测试的内容:

  • 在我的“com.init_drone()”方法中,除了最后一行之外,我已经注释了所有内容,这表示该方法返回。当我这样做时,我的程序挂在其他地方,但它仍然没有达到无限循环。
  • 我一直在输出内存使用量,我得到的数字不低于450 - 这告诉我,我没有使用荒谬的内存量。
  • 我尝试删除Timer1实例化,中断连接/分离,对程序没有影响的bu。

我的.ino file(and Command) is located here适用于任何想要更全面照片并且不想滚动浏览所有这些代码的人,我将在下面发布。


到目前为止,这是我的日志输出。 请注意截断!


AT&F
AT+NMAC=00:1d:c9:10:39:6f
AT+WM=0
AT+NDHCP=1
AT+WA=ardrone_279440
AT+NCUDP=192.168.1.1,5556
S0AT*CONFIG=1,"general:navdata_demo","TRUE"
EAT*CONFIG=1,"general:navdata_demo","TRUE"

638
S0AT*CONFIG=2,"control:altitude_max","2000"
EAT*CONFIG=2,"control:altitude_max","2000"

638
S0AT*CONFIG=3,"control:euler_angle_max","0.35"
EAT*CONFIG=3,"control:euler_angle_max","0.35"

586
S0AT*CONFIG=4,"control:outdoor","FALSE"
EAT*CONFIG=4,"control:outdoor","FALSE"

635
S0AT*CONFIG=5,"control:flight_without_shell","FALSE"
EAT*CONFIG=5,"control:flight_without_shell","FALSE"

574
S0AT*CTRL=6,4,0
EAT*CTRL=6,4,0

629
S0AT*CTRL=7,0,0
EAT*CTRL=7,0,0

629
S0AT*CTRL=8,4,0
EAT*CTRL=8,4,0

629
S0AT*COMWDG=9
EAT*COMWDG=9

629
S0AT*COMWDG=10
EAT*COMWDG=10

629
S0AT*COMWDG=11
EAT*COMWDG=11

629
S0AT*COMWDG=12
EAT*COMWDG=12

629
S0AT*COMWDG=13
EAT*COMWDG=13

629
S0AT*FTRIM=14
EAT*FTRIM=14

629

这是我的.ino文件:

#include "Command.h"
#include "Streaming.h"

int debug = 1;
extern ring_buffer rx_buf;
extern resultint_ resultint;

Command com;
int sequenceNumber = 1;
String atcmd = "";

#include "TimerOne.h"
#define LEDpin 13



void setup()
{
  PCsrl.begin(9600);

  com.start_wifi_connection();

  com.drone_is_init = com.init_drone();

  Timer1.initialize(COMWDG_INTERVAL_USEC);
  Timer1.attachInterrupt(watchdog_timer);

}

void watchdog_timer() {
  com.sendwifi(com.makeComwdg());
}

void loop()
{  

  if (com.drone_is_init == 0) {
        if (debug) {
      // never use three ! together in arduino code
      PCsrl.println("Drone wasn't initlized before loop() was called. Initalizing now.\r\n");
    }

  } else {

    com.drone_takeoff();
    com.drone_takeoff();

    com.sendwifi(com.makePcmd(1,0,0,0,0));
    com.sendwifi(com.makePcmd(1,0,0,0,0));
    delay(5000);

    com.moveForward(1);
    com.moveRotate(180);
    com.moveForward(1);
    com.moveRotate(180);

    delay(500);

    com.drone_landing();
    com.drone_landing();

    delay(500);

    //end of program
    Timer1.detachInterrupt();
    PCsrl.println("Program finished");
    while (1){};

  }
}

我的Command.cpp

#ifndef GAINSPAN
#define GAINSPAN
#include "Command.h"

extern int sequenceNumber;
extern int debug;

ring_buffer rx_buf= {{0}, 0, 0};
resultint_ resultint;


Command::Command()
{
  at = "";
  command = "";
  s2ip_running = 0;
  drone_is_init = 0;
  drone_is_hover = 0;
  emergency = 0;
}


void Command::sendwifi(String s) {

    WIFIsrl.write(27); //esc
    WIFIsrl.print("S0"); //choose connection CID 0
    WIFIsrl.print(s);
    WIFIsrl.write(27);
    WIFIsrl.print("E");


    if(debug) PCsrl.println(s);

    WIFIsrl.println(memoryTest()); 
}



int Command::start_wifi_connection()
{
  WIFIsrl.begin(9600);

  WIFIsrl.println("");
  WIFIsrl.println("AT&F");
  //WIFIsrl.println("ATE0"); //turn off echo
  WIFIsrl.print("AT+NMAC=00:1d:c9:10:39:6f\r"); //set MAC address
  WIFIsrl.println("AT+WM=0");

  WIFIsrl.println("AT+NDHCP=1");

  /* drone's network profile, change if needed*/
  WIFIsrl.println("AT+WA=ardrone_279440");
  WIFIsrl.println("AT+NCUDP=192.168.1.1,5556");
  readARsrl();

  delay(3000); //need 3 seconds for connection to establish
  return 0;
}  

String Command::makeComwdg()
{
  at = "AT*COMWDG=";
  command = at + getSequenceNumber() + "\r\n";
  return command;
}

void Command::sendComwdg_t(int msec)
{
  for (int i = 0; i < msec; i+=20) {
    sendwifi(makeComwdg());
    delay(20);
  }
}

void Command::sendFtrim()
{
  at = "AT*FTRIM=";
  command = at + getSequenceNumber() + "\r\n";
  sendwifi(command);
}

void Command::sendConfig(String option, String value)
{
  at = "AT*CONFIG=";
  command = at + getSequenceNumber() + ",\"" + option + "\",\"" + value + "\"\r\n";
  sendwifi(command);
}

void Command::sendRef(flying_status fs)
{
  at = "AT*REF=";
  if(fs == TAKEOFF){
    command = at + getSequenceNumber() + ",290718208\r\n"; //takeoff
  }
  else if(fs == LANDING){
    command = at + getSequenceNumber() + ",290717696\r\n"; //landing
  } else if (fs == EMERGENCY_TOGGLE){
    command = at + getSequenceNumber() + ",290717952\r\n"; //landing
  }

  // emergency -> 290717952
  sendwifi(command);
}

void Command::send_control_commands(){
    at = "AT*CTRL=";
    sendwifi(at+getSequenceNumber()+",4,0\r\n");
    sendwifi(at+getSequenceNumber()+",0,0\r\n");
    sendwifi(at+getSequenceNumber()+",4,0\r\n");
}

void Command::drone_emergency_reset()
{
  at = "AT*REF=";
  command = at + getSequenceNumber() + ",290717952\r\n";
  sendwifi(command);
}

/** Movement functions **/
int Command::moveForward(float distanceInMeters)
{
  float i = 0;
  String moveForward = makePcmd(1, 0, -.855, 0, 0);
  delay(1000*distanceInMeters);
  sendPcmd(moveForward);
  return 1;
}

int Command::moveRotate(float yawInDegrees)
{
  int i = 0;
  while (i < yawInDegrees) {
    String stayRotate = makePcmd(1, 0, 0, 0, 0.17);
    sendPcmd(stayRotate);
    delay(150);
    i += 8;
  }
  return 1;
}

String Command::makePcmd(int enable, float roll, float pitch, float gaz, float yaw)
{
  at = "AT*PCMD=";
  command = at + getSequenceNumber() + "," + enable + "," + fl2int(roll) + "," + fl2int(pitch) + "," + fl2int(gaz) + "," + fl2int(yaw) + "\r";
  return command;
}

void Command::sendPcmd(String command)
{
  previousCommand = command;
  sendwifi(command);
}

void Command::sendPcmd(int enable, float roll, float pitch, float gaz, float yaw)
{
  at = "AT*PCMD=";
  command = at + getSequenceNumber() + "," + enable + "," + fl2int(roll) + "," + fl2int(pitch) + "," + fl2int(gaz) + "," + fl2int(yaw) + "\r";
  sendwifi(command);
}

String Command::makeAnim(anim_mayday_t anim, int time)
{
  at = "AT*ANIM=";
  command = at + getSequenceNumber() + "," + anim + "," + time + "\r\n";
  return command;
}

void Command::doLEDAnim(int animseq, int duration)
{
  PCsrl << "calling LEDAnim" << endl;
  at = "AT*LED=";
  command = at + getSequenceNumber() + "," + animseq + ",1073741824," + duration + "\r\n";
  sendwifi(command);
}

int Command::start_s2ip()
{
  char temp;
  //delay(20000); //wait for drone to start

  readARsrl();

  if (debug) {
    PCsrl << "trying to start s2ip" << endl;
  }

  ARsrl.print("\r\n");
  delay(500);
  ARsrl.print("\r\n");
  delay(500);
  ARsrl << "cd ~" << endl;

  if (debug) {
    readARsrl();
  }

  delay(500);
  ARsrl << "cd data/video/apps/" << endl;
  delay(500);
  ARsrl << "./s2ip.arm" << endl; 
  while ((int) temp != 2) {
    temp = ARsrl.read();
    if (temp == 2) {
      PCsrl << "s2ip is running" << endl;
      ARsrl << "bullshit\r\n"; //to fix a delay bug
      break;
    }
    //PCsrl << "s2ip not running" << endl;
  }
  if (debug) {
    while (ARsrl.available()) {
      PCsrl.write(ARsrl.read());
    }
  }
  return 1;
}

void Command::quit_s2ip()
{
  ARsrl.println("EXIT");
  while (ARsrl.available()) {
    PCsrl.write(ARsrl.read()); 
  }
}

int Command::init_drone()
{
  sendConfig("general:navdata_demo","TRUE");
  sendConfig("control:altitude_max","2000");
  sendConfig("control:euler_angle_max","0.35");
  sendConfig("control:outdoor","FALSE");
  sendConfig("control:flight_without_shell","FALSE");
  send_control_commands();
  sendComwdg_t(90);
  sendFtrim();

  drone_emergency_reset(); //clear emergency flag

  return 1;
}

int Command::drone_takeoff()
{
  sendRef(TAKEOFF);
  int i = 0;
  return 1;
}

int Command::drone_hover(int msec)
{
  int i = 0;
  while (i < msec) {
    sendwifi(makePcmd(1, 0, 0, 0, 0));
    delay(100);
    i += 100;
  }
  return 1;
}

int Command::drone_landing()
{
  sendRef(LANDING);
  return 1;
}

int Command::drone_move_up(int centimeter)
{
  int i = 0;
  while (i < centimeter) {
    ARsrl << makePcmd(1, 0, 0, 0.6, 0);
    delay(100);
    i += 10;
  }
  return 1;
}

int Command::drone_move_down(int centimeter)
{
  int i = 0;
  while (i < centimeter) {
    sendwifi(makePcmd(1, 0, 0, -0.5, 0));
    delay(100);
    i += 10;
  }
  return 1;
}

long Command::fl2int(float value)
{
  resultint.i = 0;
  if (value < -1 || value > 1) {
    resultint.f = 1;
  } else {
    resultint.f=value;
  }

  return resultint.i;
}

void Command::readARsrl()
{
  while (ARsrl.available()) {
    if (debug) {
      PCsrl.write(ARsrl.read());
    }
  }
}


//Memory test code from : http://www.faludi.com/2007/04/18/arduino-available-memory-test/
int Command::memoryTest() {
  int byteCounter = 0; // initialize a counter
  byte *byteArray; // create a pointer to a byte array
  // More on pointers here: http://en.wikipedia.org/wiki/Pointer#C_pointers

  // use the malloc function to repeatedly attempt
  // allocating a certain number of bytes to memory
  // More on malloc here: http://en.wikipedia.org/wiki/Malloc
  while ( (byteArray = (byte*) malloc (byteCounter * sizeof(byte))) != NULL ) {
    byteCounter++; // if allocation was successful, then up the count for the next try
    free(byteArray); // free memory after allocating it
  }

  free(byteArray); // also free memory after the function finishes
  return byteCounter; // send back the highest number of bytes successfully allocated
}

int Command::getSequenceNumber(){
  return sequenceNumber++;
}

// Volatile, since it is modified in an ISR.
volatile boolean inService = false;

void SrlRead()
{
  if (inService) {
    PCsrl.println("timer kicked too fast");
    return;
  }
  interrupts();
  inService = true;
  while(ARsrl.available()) {
    unsigned char k = ARsrl.read();
    store_char(k, &rx_buf);
  }
  inService = false;
}

void read_rx_buf()
{
  while (rx_buf.tail != rx_buf.head) {
    if (debug) {
      PCsrl.write(rx_buf.buffer[rx_buf.tail]);
    }
    rx_buf.tail = (unsigned int) (rx_buf.tail+ 1) % SERIAL_BUFFER_SIZE;
  }
}

inline void store_char(unsigned char c, ring_buffer *buffer)
{
  int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != buffer->tail) {
    buffer->buffer[buffer->head] = c;
    buffer->head = i;
  }
  else {
    Serial.println("ring buffer is too small");
  }
}

#endif

3 个答案:

答案 0 :(得分:2)

我知道这听起来很奇怪但是,有时这种情况发生在arduino没有获得足够的电力供应时。尝试将arduino连接到与USB不同的电源。

答案 1 :(得分:1)

当我开始将内容放入prog内存时,我的程序就开始清理它的打嗝。这似乎是一个记忆问题。

答案 2 :(得分:0)

我遇到了同样的问题,但问题出在Timer1.initialize()上。试试这个:

  com.drone_is_init = com.init_drone();

  Serial.println("One");
  Serial.println("Two");
  Serial.println("Three");

  Timer1.initialize(COMWDG_INTERVAL_USEC);
  Timer1.attachInterrupt(watchdog_timer);

打开串口监视器并看到......它将显示为“Two”,然后Arduino将挂起。

问题是我调用了LiquidCrystal_I2C库的一些函数,这些函数需要中断例程。检查您的定时器ISR是否正在使用某些中断。如果是这样,您应该将此代码移动到项目中的其他位置。