сайт для палких паяльників

NodeMCU имеет собственную файловую систему. Можно не только хранить lua скрипты, но и использовать ее для работы со своими файлами. Файловая система простая, без директорий. То есть, все файлы хранятся в корне файловой системы. Однако допускается создание файлов с именами типа: myDir/test.txt, но это будет просто файл с таким именем. За работу с файлами отвечает модуль file.

Как и в обычных файловых системах, файлы можно открыть в нескольких режимах. Открывается функцией file.open(filename, mode). Функции передаются имя файла и нужный режим:

  • “r”: read mode (the default)
  • “w”: write mode
  • “a”: append mode
  • “r+”: update mode, all previous data is preserved
  • “w+”: update mode, all previous data is erased
  • “a+”: append update mode, previous data is preserved, writing is only allowed at the end of file

Пример:


-- rewrite file:
if file.open("test.txt", "w") then
  file.write("Line1")
  file.writeline("Line2")
  file.writeline("Line3")
  file.close()
end

-- append file:
if file.open("test.txt", "a+") then
  file.writeline("Line4")
  file.close()
end

-- read file:
if file.open("test.txt", "r") then
  print(file.read())
  file.close()
end

Этот пример открывает файл test.txt для записи. Если такого файла не существует, он будет автоматически создан. Если файл существует, его содержимое будет затерто. Если открытие файла было удачным, производится запись. Для записи в файл используются две функции, первая file.write записывает строку как есть. Другая команда, file.writeline, добавляет в конец строки символ перехода на новую строку. Затем файл закрывается. Следующий блок открывает уже существующий файл для дописывания строки в конец файла (режим a+). И наконец, записанный файл открывается для чтения, содержимое файла считывается и выводится в консоль.

Примечание: Иногда, после заливки на ESP8266 фреймворка NodeMCU файловая система не позволяет записать ни одного файла в том числе и скрипты. Надо отформатировать файловую систему командой file.format()

Робота с большими файлами

В предыдущем примере файл читался одним махом. Когда файл слишком большой, и не сможет поместиться в памяти ESP, могут возникнуть проблемы. Поэтому читать большие файлы лучше кусками. Если файл текстовый, его можно читать построчно. Пример:



-- read file:
fd = file.open("test.txt", "r")
if fd then
  line = file.readline()
  while line do
    print(line)
    line = file.readline()
  end
  file.close()
end

Или читать файл равными блоками:


-- read file:
fd = file.open("test.txt", "r")
if fd then
  line = file.read(5)
  while line do
    print(line)
    line = file.read(5)
  end
  file.close()
end

В этом примере чтение выполняется блоками по 5 байт. Чтение больших файлов слишком малыми кусками может занять много времени. Поэтому лучше это делать блоками примерно 1К.

SD карточка

Если Вам нужно хранить большие объемы данных и для этого не достаточно Flash памяти, к ESP8266 с NodeMCU можно подключить SD карточку. NodeMCU работает с SD карты так же как и с собственной файловой системой, используя модуль file. С одной стороны это упрощает работу с файлами, а с другой это накладывает такие же ограничения на работу с SD картой как и с собственной Flash памятью. А именно: нет поддержки вложенных папок, нет метки времени, не поддерживаются атрибуты файлов.

Схема подключения:

Важно чтобы адаптер SD карточки работал с уровнями сигналов 3.3В. Мой адаптер питается от 5В, но он работает с сигналами уровню 3.3В.

Для работы с SD карточкой надо собрать NodeMCU со следующими модулями: spi, file, и обязательно должна быть включена опция “FatFS support for reading from SD Cards“.

Напомню, что собрать NodeMCU с нужными модулями можно на сайте https://nodemcu-build.com/

Пример использования SD карточки:


-- initialize other spi slaves
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)

-- then mount the sd
-- note: the card initialization process during `file.mount()` will set spi divider temporarily to 200 (400 kHz)
-- it's reverted back to the current user setting before `file.mount()` finishes
vol = file.mount("/SD0", 8)   -- 2nd parameter is optional for non-standard SS/CS pin
if not vol then
  print("retry mounting")
  vol = file.mount("/SD0", 8)
  if not vol then
    error("mount failed")
  end
end

filename = "/SD0/somefile"

if file.open(filename, "a+") then
  file.write('Test Line')
  file.close()
end

if file.open(filename) then
  print(file.read())
  file.close()
end

В этом примере сначала выполняется инициализация интерфейса SPI, поскольку общение ESP и SD карты происходит именно по этому интерфейсу. Затем выполняется процесс инициализации, то есть монтирование. Монтирование выполняется функцией file.mount( “/SD0”, 8). Ей передается два параметра. Первый – имя устройства (/SD0, /SD1, и т.д.). Второй указывает номер пина, который используется в качестве SS/CS. Как видите, монтирование может происходит с двух попыток. Это делается на тот случай, когда во время первой попытки SD карта будет еще не готова.

Работа с файлами, которые находятся на внешнем носителе не отличается от работы с файлами расположенными на собственной файловой системе NodeMCU. Конечно, ничем кроме имени файла.

Примечание: Когда я пытался использовать старую, небольшую SD-карту на 128МБ она никак не хотела монтироваться. Проблема решилась заменой карточки на новую, более быструю. Если у Вас возникнут подобные проблемы, имейте в виду, что проблема может быть в карте памяти.

file.chdir

В модуле file есть функция file.chdir(). Эта функция изменяет текущее устройство (/FLASH, /SD0, /SD1, …). /FLASH – это собственная файловая система. То есть, к файлам, расположенным на собственной файловой системе, можно обращаться указывая имя устройства. Например, можно открыть файл указав только имя, как мы это делали раньше:


file.open("test.txt", "w")

Или указать полный путь к файлу:


file.open("/FLASH/test.txt", "w")

Пример использования file.chdir:


-- initialize other spi slaves
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)

-- then mount the sd
-- note: the card initialization process during `file.mount()` will set spi divider temporarily to 200 (400 kHz)
-- it's reverted back to the current user setting before `file.mount()` finishes
vol = file.mount("/SD0", 8)   -- 2nd parameter is optional for non-standard SS/CS pin
if not vol then
  print("retry mounting")
  vol = file.mount("/SD0", 8)
  if not vol then
    error("mount failed")
  end
end

-- Create a test.txt file on the /FLASH
file.open("/FLASH/test.txt","w+")
file.writeline("This is a file on the FLASH")
file.close()

-- Create a test.txt file on the /SD0
file.open("/SD0/test.txt","w+")
file.writeline("This is a file on the SD0")
file.close()


-- read file:
if file.open("/FLASH/test.txt", "r") then
  print(file.read())
  file.close()
end

-- read file:
if file.open("/SD0/test.txt", "r") then
  print(file.read())
  file.close()
end

file.chdir("/FLASH")
if file.open("test.txt", "r") then
  print(file.read())
  file.close()
end

file.chdir("/SD0")
if file.open("test.txt", "r") then
  print(file.read())
  file.close()
end

Запуск скриптов с SD-карты

NodeMCU работает с SD-картой так же, как и с собственной FLASH памятью. Вы можете записать на SD карту LUA скрипты и выполнять их как и обычные. В некоторых проектах это может понадобится, например, для обновления программ, или выполнения каких-то нестандартных, разовых операций обслуживания или диагностики.

Следующий пример создает тестовый скрипт на SD Сard и выполняет его.


-- initialize other spi slaves
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)

-- then mount the sd
-- note: the card initialization process during `file.mount()` will set spi divider temporarily to 200 (400 kHz)
-- it's reverted back to the current user setting before `file.mount()` finishes
vol = file.mount("/SD0", 8)   -- 2nd parameter is optional for non-standard SS/CS pin
if not vol then
  print("retry mounting")
  vol = file.mount("/SD0", 8)
  if not vol then
    error("mount failed")
  end
end

-- create script on SD-Card:
if file.open("/SD0/test.lua", "w") then
  file.writeline("print(\"This LUA-script was runned from the SD-Card\")")
  file.close()
end

dofile("/SD0/test.lua")

file.chdir("/SD0")
dofile("test.lua")

file.chdir("/FLASH")

Компиляция файлов

Еще одна операция, которую можно сделать с Вашими LUA скриптами – это их компиляция и использование скомпилированных версий. Скрипты LUA компилируются командой node.compile и сохраняются с таким же именем только с расширением . Скомпилированные версии можно запускать как и обычные скрипты с помощью dofile().

Следующий пример создает скрипт hello.lua, компилирует его и затем последовательно запускает hello.lua и его скомпилированную версию hello.lс. С помощью этого скрипта можно сравнить скорость выполнения обеих версий.


-- Create a hello.lua file
file.open("hello.lua","w+")
file.writeline([[print("hello nodemcu")]])
file.writeline([[print("heap:"..node.heap())]])
file.close()

-- Compile hello.lua to hello.lc
node.compile("hello.lua")

-- Execute hello.lua
print("LUA file")
syscounter = tmr.now()
dofile("hello.lua")
print("time:"..tmr.now() - syscounter.."\n")

-- Execute hello.lc
print("LC file")
syscounter = tmr.now()
dofile("hello.lc")
print("time:"..tmr.now() - syscounter)

Желаю успехов.

Смотри также:

2 комментария: ESP8266 NodeMCU. Файловая система + SD карточка

  • Максим говорить:

    Компиляция файлов ускоряет их выполнение или для чего необходима данная процедура?

    • andre говорить:

      Скомпилированные скрипты требуют меньше ресурсов при выполнении и работают заметно быстрее.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

 
Translate
Архіви

© 2011-2017 Андрій Корягін, Кременчук - Київ, Україна