问题描述
我能达到的最大写入速度是 2.4 KB/s。有没有办法增加这个?
在 NodeMCU ESP8266 和 User_Modules.h 中的 SPI 模块上使用 LUA。 #define BUILD_FATFS 也在 user_config.h 中启用。
我有一个数据记录器,每次采样 920SPS 或 ~1.1ms/Sample 10 小时。 1.1 毫秒应该是很多时间将两个字节写入 SD 卡或样本之间的 xxx 字节缓冲区,但是我看到的最大写入速度是 498 毫秒写入 1200 字节或 7 毫秒写入 3 字节。这与 12.5MB/s 的 SD class 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
解决方法
您可以通过准备 2KB 对齐的文本块来加速文件写入。
将您的 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(_,_ = 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,"",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],for File operations
n = 1
end
end
它比以前的版本快吗?
更新 2:
local chr = string.char
function adcReady(_,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,44)
else
local m1000 = v % 1000
s = chr((v - m1000)/1000 + 48,(m1000 - m100)/100 + 48,44)
end
end
end
adctbl[i] = s
end
local log_text_to_save = table.concat(adctbl,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,for File operations
n = 1
end
end