有没有办法在Nodemcu ESP8266上提高LUA中的SD卡写入速度



我能达到的最大写入速度是2.4 KB/s。有办法增加这个吗?

在NodeMCU上使用LUA ESP8266和User_Modules.h中的SPI模块。#define BUILD_FATFS也在User_config.h中启用。

我有一个数据记录器,它一次采样920SPS或~1.1ms/样本10小时。1.1毫秒应该有很多时间将两个字节写入SD卡或样本之间xxx字节的缓冲区,但我看到的最大写入速度是498毫秒写入1200字节或7毫秒写入3字节。这与12.5MB/s的SD 0级标准还有很长的路要走。当我向卡转储1200 B时,记录器最终丢失了~450个样本。


local adc1 = nil
local t_tbl={}
local n=1
function adcReady(_,_,c)

_,_, adctbl[n], _ = adc1:read()
n=n+1
if n>400 then

t_tbl[1]=tmr.now()

file.open("/SD0/sddata.txt","a")
for k,v in ipairs(adctbl) do 
file.write(v..",")
adctbl[k]=nil
end
file.close()

t_tbl[2]=tmr.now()

print(t_tbl[2] - t_tbl[1])
n=1

end
end
do
local adc = {
ADC1_ID             =   0,
ADC1_ADDRESS        =   ads1115.ADDR_GND, 
GAIN                =   ads1115.GAIN_4_096V, 
SAMPLES             =   ads1115.DR_920SPS, 
CHANNEL             =   ads1115.SINGLE_0,       
MODE                =   ads1115.CONTINUOUS, 
CONV_READY          =   ads1115.CONV_RDY_1, 
}
i2c.setup(i2c0.id, i2c0.sda, i2c0.scl, i2c0.speed)
ads1115.reset()
adc1 = ads1115.ads1015(adc.ADC1_ID, adc.ADC1_ADDRESS)   
adc1:setting(adc.GAIN, adc.SAMPLES, adc.CHANNEL, adc.MODE, adc.CONV_READY)  

spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 2, spi.HALFDUPLEX)
vol = file.mount("/SD0", 8)   -- 2nd parameter is optional for non-standard SS/CS pin
file.open("/SD0/sddata.txt","w+")
file.close()

tmr.create():alarm(1000,tmr.ALARM_SINGLE,function()
gpio.mode(i2c0.conv_rdy,gpio.INT) 
gpio.trig(i2c0.conv_rdy,'up', adcReady) --enable interrupt, active low rising edge==conv ready  
end)
end

您可以通过准备2K字节对齐的文本块来加速文件写入
adcReady替换为:

local log_text = ""
local chunk_size = 2*1024
function adcReady(_,_,c)
_, _, adctbl[n], _ = adc1:read()
n = n + 1
if n > 400 then

t_tbl[1] = tmr.now()

log_text = log_text..table.concat(adctbl, ",", 1, n-1)..","
local size = #log_text - #log_text % chunk_size
local log_text_to_save = log_text:sub(1, size)
log_text = log_text:sub(size + 1)

t_tbl[2] = tmr.now()

if size ~= 0 then 
file.open("/SD0/sddata.txt","a")
file.write(log_text_to_save)
file.close()
end

t_tbl[3] = tmr.now()

print(t_tbl[2] - t_tbl[1], t_tbl[3] - t_tbl[2])  -- for strings and GC, for File operations
n = 1

end
end

它比498毫秒快吗?


更新:

带有缓存tostring((的新版本

local num2str = {}
function adcReady(_,_,c)
_, _, adctbl[n], _ = adc1:read()
n = n + 1
if n > 400 then
t_tbl[1] = tmr.now()
for i = 1, n - 1 do
local v = adctbl[i]
local s = num2str[v]
if not s then
s = v..","
num2str[v] = s
end
adctbl[i] = s
end
local log_text_to_save = table.concat(adctbl, "", 1, n-1)
t_tbl[2] = tmr.now()
file.open("/SD0/sddata.txt","a")
file.write(log_text_to_save)
file.close()
t_tbl[3] = tmr.now()
print(t_tbl[2] - t_tbl[1], t_tbl[3] - t_tbl[2])  -- for strings and GC, for File operations
n = 1
end
end

它比以前的版本快吗?


更新2:

local chr = string.char
function adcReady(_,_,c)
_, _, adctbl[n], _ = adc1:read()
n = n + 1
if n > 400 then
t_tbl[1] = tmr.now()
for i = 1, n - 1 do
local v = adctbl[i]
-- 0<=v<=4095
local s
if v < 10 then
s = chr(v + 48, 44)
else
local m10 = v % 10
if v < 100 then
s = chr((v - m10)/10 + 48, m10 + 48, 44)
else
local m100 = v % 100
if v < 1000 then
s = chr((v - m100)/10 + 48, (m100 - m10)/10 + 48, m10 + 48, 44)
else
local m1000 = v % 1000
s = chr((v - m1000)/1000 + 48, (m1000 - m100)/100 + 48, (m100 - m10)/10 + 48, m10 + 48, 44)
end
end
end
adctbl[i] = s
end
local log_text_to_save = table.concat(adctbl, "", 1, n-1)
t_tbl[2] = tmr.now()
file.open("/SD0/sddata.txt","a")
file.write(log_text_to_save)
file.close()
t_tbl[3] = tmr.now()
print(t_tbl[2] - t_tbl[1], t_tbl[3] - t_tbl[2])  -- for strings and GC, for File operations
n = 1
end
end

更新3:

对于日志中的Lua 5.3和十六进制数字:

-- log output is in hex
local high = {} -- [1] = "", [2] = "1", ..., [256] = "FF"
local low = {}  -- [1] = "0,", [2] = "1,", ..., [16] = "F,"
for x = 0, 255 do  -- replace 255 with 127 (to save memory) if ADC generates only positive values 0x0000-0x7FF0
high[x+1] = string.format("%X", x*16):sub(1, -2)
if x < 16 then
low[x+1] = string.format("%X,", x)
end
end
-- in case of out-of-memory error reduce measures count (400) to 256
local measures = 400   -- recommended values are powers of 2
local measures_2 = measures*2
-- adctbl[] is not used anymore, text_buffer[] is used instead
local text_buffer = {}  -- array of (2*measures) elements
for x = 1, measures_2 do
text_buffer[x] = ""
end
function adcReady(_,_,c)
local _, _, v = adc1:read()
-- 0x0000<=v<=0xFFF0
text_buffer[n] = high[(v>>8)+1]
text_buffer[n+1] = low[((v>>4)&15)+1]
n = n + 2
if n > measures_2 then
t_tbl[1] = tmr.now()
local log_text_to_save = table.concat(text_buffer, "", 1, n-1)
t_tbl[2] = tmr.now()
file.open("/SD0/sddata.txt","a")
file.write(log_text_to_save)
file.close()
t_tbl[3] = tmr.now()
print(t_tbl[2] - t_tbl[1], t_tbl[3] - t_tbl[2])  -- for strings and GC, for File operations
n = 1
end
end

最新更新