2017-04-05 36 views
0

我一直在研究Arduino(ATMega328p)原型,它必須在某些事件中記錄數據。 LSM6DS33傳感器用於以104 Hz的採樣率生成6個值(每個2個字節)。這些數據需要記錄500-20000ms。如何防止在記錄期間SD卡創建寫入延遲?

在我的代碼中,我使用Timer1每1/104秒產生一箇中斷。發生此中斷時,將從傳感器讀取數據,進行校準,然後寫入SD卡。通常情況下,這不是問題。從傳感器讀取數據需要約3350us,校準〜5us並寫入〜550us。這意味着整個循環需要約4000us,而9615us可用。

爲了節省電力,我希望降低電壓到3.3V。根據atmel數據表,這也意味着時鐘頻率應該降至8MHz。假設一切都會慢兩倍,測量週期仍然是可能的,因爲〜8000us < 9615us。

然而,經過一些測試(仍然是5V @ 16MHz)後,我發現寫一個週期需要約1880us而不是約550us。我正在使用庫SdFat編寫和測試SD卡(RawWrite示例)。以下結果出來時,我測試的卡:

開始原始寫入的100000 KB
目標速率:100 KB /秒
目標時間:100秒
閔塊寫入時間:1244百萬分之一
最大塊寫時間:12324萬分之一
平均塊寫入時間:1247萬分之一

正如所看到的,寫的平均時間是相當一致的,但有時10倍平均峯值時間發生!根據庫的作者,這是因爲SD卡在x個寫入週期之間需要一些擦除週期。這會導致寫入延遲(src:post#18&#22)。然而,這種延遲將週期從可用的9615us支架中抽出所需的時間,因爲總的測量週期將是10672us。

我想寫的數據,使用的sprintf首次投入一個字符串:

char buf[20] = ""; 
sprintf(buf,"%li\t%li\t%li\t%li\t%li\t%li",rawData[0],rawData[1],rawData[2],rawData[3],rawData[4],rawData[5]); 
myLog.println(buf); 

這將數據寫入到一個txt文件。但以我的速度,只有21 * 104 = 2184 B/s就足夠了。將RawWrite示例的速度降低至6 KB/s,會導致SD卡寫入而不會延長寫入延遲。然而我的代碼仍然有它們,即使寫入的數據較少。

我的問題是:如何防止發生延遲(如果可能)?如果不可能,我該如何解決它?如果我明白爲什麼發生延遲,這將有所幫助,因爲間隔不總是相同的(每10-15次寫入)。

一些附加信息:
草圖當前使用變量的69%的RAM(2kB)。創建兩個512字節緩衝區 - 就像在同一個論壇中建議的那樣 - 對我來說是不可能的。
最初,我使用了兩個字符串。將它們合併爲一個並不影響寫入速度,具有任何意義。

+1

擦除延遲是SD卡固有的。如果已滿,您可能會預計更長的延遲。另外,如果細胞老化,他們需要花更長的時間來擦寫。雖然你的問題太廣泛了(我們不是諮詢網站),但緩衝可能會有所幫助,但正如你所說你的RAM處於邊緣,也許Arduino(至少基於ATmega的)不適合你的項目。最後:Arduino是**不** **。不要垃圾標籤。 – Olaf

+0

如果性能很重要,爲什麼要將值轉換爲字符串並寫入文本?這需要更多的空間和更多的時間。 –

+0

@AndrewHenle:雖然我同意在如此小的平臺上使用'printf'等是一個好主意,但它似乎並不是主要問題。它不會避開SD卡攤位。 – Olaf

回答

0

我不知道如何解決延遲,但我遇到一個更穩定和更快的寫入時間,如果我寫的二進制文件,而不是一個名爲「.csv」或.txt」文件。

以下鏈接提供了一個很好的腳本來將數據作爲二進制結構寫入SD卡。(在他的例子中有一些小的錯字,它很容易修復) https://hackingmajenkoblog.wordpress.com/2016/03/25/fast-efficient-data-storage-on-an-arduino/

這不會幫助你的時間變化,但它可能會減少寫入時間,從而忽略了時間問題。