4

我对 Arduino 世界很陌生。编写了以下代码 - 使用 DHT22 传感器。12 小时后,我温室的加热器在低于所需温度时没有打开。

关闭电源并重新打开后,一切恢复正常。我知道这段代码很乱——但它有内存泄漏吗?或者其他可能导致它停止工作的东西?

http://pastebin.com/CcdUN3jb

编辑 - 我发现一个开放的计数器每 2 秒增加 1。我无法想象就是这样,但我在这里改变了它:http: //pastebin.com/nuRjHJkR

4

2 回答 2

6

老军忠告:

如果你不能修复它,画它。

这些微控制器中存在看门狗定时器只是为了让您的植物保持活力,而不管您的代码如何。每次通过 loop(),你用一个简单的方法喂狗

wdt_reset();

如果您的程序挂起并停止喂狗,MCU 将重置。

您可以在 setup() 中配置看门狗的超时时间。出于您的目的,您可以使用 8 秒的大超时,这应该为最长的 loop() 执行时间提供巨大的余量。这些传感器读取需要多长时间?

有关简单描述,请参见 Arduino 页面中的链接: 看门狗

于 2013-01-15T06:28:33.343 回答
2

代码中明显的一个危险是 sprintf()。如果没有人再次使用它,世界将变得更美好。替换这个

void loop() {
  ...
  char buf[128];
  sprintf(buf, "Integer-only reading: Temperature %hi.%01hi C, Humidity %i.%01i %% RH",
               myDHT22.getTemperatureCInt()/10, abs(myDHT22.getTemperatureCInt()%10),
               myDHT22.getHumidityInt()/10, myDHT22.getHumidityInt()%10);
  //Serial.println(buf);

void loop() {
 ...
 const size_t sizeBuf = 128;
 char szBuf[128+1];

 snprintf(szBuf, sizeBuf, "Integer......", ... );
 szBuf[sizeBuf] = '\0';

所有字符串函数都存在“n”个版本,并且都提供了目标缓冲区大小的规范,以便您可以确保它们永远不会超出缓冲区。注意函数不保证零终止,所以要多出一行来保证。

因此,使用 snprintf,您可以放心,如果一百万个数据错误中的 1 个错误会导致一些意外的字符串转换,您的代码会继续运行。

沿着这条线,在循环内分配 char buf[] 并没有太多好处。由于程序所做的只是无休止地执行 loop(),因此您不会通过将其设为堆栈上的局部变量来节省内存资源。只有一个不使用堆栈内存的微观窗口。但是通过在堆栈上,如果你溢出 buf,溢出可以擦除返回地址,这肯定会导致程序崩溃。这一切都是危险,没有回报。

这样想

const size_t sizeBuf = 128;
char szBuf[128+1];

void loop() {
 ...

 snprintf(szBuf, sizeBuf, "Integer......", ... );
 szBuf[sizeBuf] = '\0';

在这种方法中,内存是静态分配的,您在编译时就知道程序需要多少内存。

于 2013-01-15T06:01:09.480 回答