2013-01-14 74 views
4

我都是Arduino世界的新手。編寫以下代碼 - 使用DHT22傳感器。 12小時後,當溫度低於所需溫度時,我的溫室的加熱器未打開。Arduino'墜毀?' 12小時之後

在關閉電源並重新開啓後,所有事情都恢復正常。我知道這段代碼非常混亂 - 但它是否有任何內存泄漏?或者其他可能導致它停止工作的東西?

http://pastebin.com/CcdUN3jb

編輯 - 我發現了一個開放的計數器被增加1每2秒。我無法想象,就是這樣,但我在這裏改變了它:http://pastebin.com/nuRjHJkR

+0

可能是溢出錯誤。需要注意的是:您使用的數據類型是否足夠支持12小時後的值?完成後,你是否將變量(計數器等)重置爲初始值? – sachleen

回答

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'; 

在這種方法中,內存是靜態分配的,你知道在你的程序需要的內存編譯時間。

6

老軍建議:

如果你不能修復它,畫它。

看門狗定時器是存在於這些微控制器只是保持你的植物活不管你的代碼的目的。每一次通過循環(),你喂狗簡單

如果你的程序掛起並停止喂狗,MCU將重置。

您可以在setup()中配置看門狗的超時時間。出於您的目的,您可以使用8秒的大暫停,這將在最長的循環()執行時間上提供巨大的餘量。這些傳感器讀數需要多長時間?

請參閱Arduino頁面的鏈接進行簡單描述:watchdog