Arduino Mega 2560 - 成功执行多次后在 while 循环中停止代码执行
Posted
技术标签:
【中文标题】Arduino Mega 2560 - 成功执行多次后在 while 循环中停止代码执行【英文标题】:Arduino Mega 2560 - stops code execution in while loop after successfully executing several times 【发布时间】:2022-01-16 14:28:02 【问题描述】:我目前正在使用 arduino Mega 2560、duinotech 3 向磁力计(5883L 仿制)和带有板载 ariel 的 duinotech gps 接收器完成一个自动 gps 漫游者项目。所有组件在 arduino 上运行良好,并且在主循环中执行没有问题。
...
void loop()
bluetooth();
delay(10); // Run the Bluetooth procedure to see if there is any data being sent via BT
getGPS();
delay(10); // Update the GPS location
getCompass();
// Serial.println(compass_heading);
delay(10);
// Update the Compass Heading
...
但是,一旦我设置了一些航点并启用了自动驾驶功能,程序就会执行 4 次循环然后失败。
有问题的函数
...
void goWaypoint()
Serial.println(F("Go to Waypoint"));
ac=ac-1;
while (true)
// Start of Go_Home procedure
// bluetooth(); // Run the Bluetooth procedure to see if there is any data being sent via BT
// if (blueToothVal == 4)
//
// Serial.println("Bluetooth Break");
// break;
// // If a 'Stop' Bluetooth command is received then break from the Loop
if (ac==-1)
break;
Serial.println(F("Checking Compass"));
getCompass();
delay(80);// Update Compass heading
Serial.println(F("Checking GPS"));
getGPS();
delay(20);
// Tiny GPS function that retrieves GPS data - update GPS location// delay time changed from 100 to 10
if (millis() > 5000 && gps.charsProcessed() < 10)
// If no Data from GPS within 5 seconds then send error
Serial.println(F("No GPS data: check wiring"));
Serial.println(F("Calculating"));
Distance_To_Home = TinyGPSPlus::distanceBetween(gps.location.lat(),gps.location .lng(),Home_LATarray[ac], Home_LONarray[ac]); //Query Tiny GPS for Distance to Destination
GPS_Course = TinyGPSPlus::courseTo(gps.location.lat(),gps.location.lng(),Home_LATarray[ac],Home_LONarray[ac]); //Query Tiny GPS for Course to Destination
Serial.println(F("The Distance to waypoint: "));
Serial.println(Distance_To_Home);
Serial.println(F("The GPS Course Needed: "));
Serial.println(GPS_Course);
if (Distance_To_Home <= 1.5) // If the Vehicle has reached it's Destination, then Stop
StopCar(); // Stop the robot after each waypoint is reached
Serial.println(F("You have arrived!")); // Print to Bluetooth device - "You have arrived"
ac--; // increment counter for next waypoint
if (ac==-1)
break;
// Break from Go_Home procedure and send control back to the Void Loop // go to next waypoin
else if ( abs(GPS_Course - compass_heading) <= 30) // If GPS Course and the Compass Heading are within x degrees of each other then go Forward
// otherwise find the shortest turn radius and turn left or right
Forward(); // Go Forward
else
int x = (GPS_Course - 360); // x = the GPS desired heading - 360
int y = (compass_heading - (x)); // y = the Compass heading - x
int z = (y - 360); // z = y - 360
if ((z <= 180) && (z >= 0)) // if z is less than 180 and not a negative value then turn left otherwise turn right
Serial.println(F("Turning Left:"));
SlowLeftTurn();
else
Serial.println(F("Turning Right"));
SlowRightTurn();
// End of While Loop
// End of Go_Home procedure
...
最后是连接到仪器的两个函数
void getGPS() // Get Latest GPS coordinates
while (Serial2.available() > 0)
gps.encode(Serial2.read());
delay(60);
void getCompass() // get latest compass value
Vector norm = compass.readNormalize();
float declinationAngle = (21.5 + (26.0 / 60.0)) / (180 / M_PI);
// Calculate heading
float heading = atan2(norm.YAxis, norm.XAxis);
heading += declinationAngle;
// heading = heading-0.4;
if(heading < 0)
heading += 2 * M_PI;
compass_heading = (int)(heading * 180/M_PI);
delay(100); // assign compass calculation to variable (compass_heading) and convert to integer to remove decimal places
上面提到的代码开始运行然后失败,只是在第四次通过 getCompass() 调用之后(大部分延迟和输出是在我的调试尝试中添加的)。我怀疑可能是内存泄漏????任何建议/帮助将不胜感激。
冻结的图片 code halted
编辑:在 getCompass() 中添加了更多打印 ...
void getCompass() // get latest compass value
Serial.println(F("In getCompass"));
Vector norm = compass.readNormalize();
float declinationAngle = 0.418;
// Calculate heading
Serial.println(F("Before Atan"));
float heading = atan2(norm.YAxis, norm.XAxis);
heading += declinationAngle;
// heading = heading-0.4;
Serial.println(F("Positive Balance"));
if(heading < 0)
heading += 2 * M_PI;
Serial.println(F("Radians to degrees"));
compass_heading = (int)(heading * 180/M_PI);
delay(100); // assign compass calculation to variable (compass_heading) and convert to integer to remove decimal places
Serial.println(F("Get Compass Finished"));
... 结果是调用在“In compass”打印后冻结,因此问题可能是 compass.normalise 函数。
我是 arduino 和低级编码的初学者,所以不确定现在如何进行,为什么在主循环中调用时它可以正常工作,但在这个 while 循环中占用代码?
更新的执行屏幕 Error Screen
我正在使用的指南针库https://github.com/jarzebski/Arduino-HMC5883L
编辑 2:在 getCompass() 中进一步弄乱我设法通过注释使代码正常工作。
float declinationAngle = 0.418;
heading += declinationAngle;
我现在完全迷失了,为什么这会导致代码冻结,以及在不使用浮点数的情况下消除偏角以计算方向的最佳方法是什么。
编辑 3:添加以包括指南针设置。
void setup()
Serial.begin(115200); // Serial 0 is for communication with the computer and magnometer.
Serial.println("In Setup");
// Serial1.begin(11520); // Serial 1 is for Bluetooth communication - DO NOT MODIFY - JY-MCU HC-010 v1.40
Serial2.begin(9600); // Serial 2 is for GPS communication at 9600 baud - DO NOT MODIFY - Ublox Neo 6m
// Motors
pinMode(leftMotor, OUTPUT);
pinMode(rightMotor, OUTPUT);
// bluetooth buffer
indx = 0;
// Compass
Serial.println("Compass setup");
while (!compass.begin())
Wire.begin(); // Join I2C bus used for the HMC5883L compass
Serial.println("Bus OK");
compass.begin(); // initialize the compass (HMC5883L)
Serial.println("Compass Object Created");
compass.setRange(HMC5883L_RANGE_1_3GA); // Set measurement range
compass.setMeasurementMode(HMC5883L_CONTINOUS); // Set measurement mode
compass.setDataRate(HMC5883L_DATARATE_15HZ); // Set data rate
compass.setSamples(HMC5883L_SAMPLES_8); // Set number of samp5les averaged
compass.setOffset(65,-290); // Set calibration offset
Serial.println("Calibrated Compass");
Serial.println("Setup Complete");
Startup(); // Run the Startup procedure on power-up one time
startup() 函数作为设置的一部分:
void Startup()
for (int i=5; i >= 1; i--) // Count down for X seconds
Serial.print("Pause for Startup... ");
Serial.print(i);
delay(1000); // Delay for X seconds
Serial.println("Searching for Satellites ");
while (Number_of_SATS < 4) // Wait until x number of satellites are acquired before starting main loop
Serial.println("Small delay for home co-ordinates to be recieved");
delay(10);
getGPS(); // Update gps data
Serial.print("Number of Sats: ");
Serial.println(int(gps.satellites.value()));
Number_of_SATS = (int)(gps.satellites.value()); // Query Tiny GPS for the number of Satellites Acquired
bluetooth(); // Check to see if there are any bluetooth commands being received
Serial.println("Looping for SATS");
// set intial waypoint to current location
wpCount = 0; // zero waypoint counter
ac = 0; // zero array counter
Serial.print(Number_of_SATS);
Serial.print(" Satellites Acquired");
Serial.println(" Start-up Complete");
【问题讨论】:
在getCompass()
中,您调用readNormalize()
和atan2()
,这两个可能的罪魁祸首。您是否添加了更多打印以查看执行停止的位置?
完成。最后更新了原始问题中的编辑。似乎是 readNormalize() 你有什么建议为什么会导致这种情况以及解决它的最佳方法?
在原始问题中添加了进一步的发现
您正在使用的 readNormalize()
函数调用 readRegister16()
通过 i2c 读取几个 HMC5883L 寄存器。库函数readRegister16()
会阻塞等待 i2c 回复:while(!Wire.available()) ;
因此,如果磁力计没有回复,您将永远被卡住。您的设置是否有足够的功率?电动移动装置的电流消耗会非常不均匀,因此电流峰值可能与电压下降(可能是电池电量不足)同时出现。所有的线都连接牢固了吗?
电源很稳定,但是接线是……有点狡猾,主要是因为我在这个项目上学习焊接。然而,这些线路通过万用表的连接测试。在昨天进一步弄乱它时,我发现可以通过取出 getCompass() 函数中的浮点减法并将其作为常量浮点数与其余的变量减法来消除冻结。但是,我不知道为什么或如何消除冻结。
【参考方案1】:
所以我设法通过从 getCompass() 函数中取出 float 声明并将其声明为全局 const float 来解决问题。为什么这会导致错误以及为什么在作为 goWaypoint() 函数的一部分运行时会发生错误我不知道,所以如果有人知道原因,请随时添加到这个问题中。同时,我将把这个答案留在这里,以防其他用户遇到类似问题。
更新:这在 24 小时内仍然没有解决,无人机的代码没有任何变化,回到了代码在 getCompass() 函数中被占用的相同情况,唯一的区别是现在它正在占用矢量范数 = compass.normalize() 线。我尝试将函数中的所有变量设置为全局变量而不是局部变量,但这没有任何效果。我开始怀疑这是否可能是主板的硬件问题。
【讨论】:
看看here 测量空闲 RAM 的方法,因为您怀疑 堆栈溢出。您发布的代码不完整,所以我可以'不知道有多少 RAM 用于其他事情 谢谢,该链接最有帮助。完整的程序在上传时占用 6% 的程序内存空间,16% 的动态内存和变量。将局部变量移到全局变量已经解决了这个问题,因为我现在有时间运行一些冗长的测试,所以我猜测在本地声明它时肯定会发生一些内存分配恶作剧。 对我来说这听起来像是堆栈损坏,而不是内存泄漏。您如何声明 Vector 数据类型和定义+初始化的指南针?你的setup()
里有什么?
在主帖中进行了一些编辑以显示包含指南针初始化的设置。该向量来自我使用的指南针库github.com/jarzebski/Arduino-HMC5883L,我相信它又使用了来自 hmc588L 库的它。它很有可能不是内存泄漏,这更像是我在黑暗中未受过教育的刺伤。
今天对车辆的测试遇到了失败,请参阅上面的编辑。以上是关于Arduino Mega 2560 - 成功执行多次后在 while 循环中停止代码执行的主要内容,如果未能解决你的问题,请参考以下文章
arduino UNO r3和arduino mega2560 用esp8266 01的WiFi模块可以接入百度天工物联网平台吗?
Python 没有接收到来自 Arduino Mega 2560 的第一行串行数据,而是接收到所有后续数据,为啥会发生这种情况?