我有一个问题,我的 Arduino 程序无缘无故挂起。我运行我的程序,在某个未确定的时间点,串行监视器停止打印输出。这是我到目前为止测试过的内容:
- 在我的“com.init_drone()”方法中,除了最后一行,我已将所有内容都注释掉,这表明该方法已返回。当我这样做时,我的程序挂在其他地方,但它仍然没有进入无限的 while 循环。
- 我一直在输出内存使用情况,我得到的数字不低于 450——这告诉我我没有使用荒谬的内存量。
- 我已经尝试删除对程序没有影响的 Timer1 实例化、中断附加/分离、bu。
我的.ino 文件(和命令)位于此处,供任何想要更全面的图片并且不想滚动浏览我将在下面发布的所有代码的人使用。
到目前为止,这是我的日志输出。注意截断!:
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 吃*CTRL=6,4,0 629 S0AT*CTRL=7,0,0 吃*CTRL=7,0,0 629 S0AT*CTRL=8,4,0 吃*CTRL=8,4,0 629 S0AT*COMWDG=9 吃*COMWDG=9 629 S0AT*COMWDG=10 吃*COMWDG=10 629 S0AT*COMWDG=11 吃*COMWDG=11 629 S0AT*COMWDG=12 吃*COMWDG=12 629 S0AT*COMWDG=13 吃*COMWDG=13 629 S0AT*FTRIM=14 吃*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