ESP8266 NodeMCU, file, SD-Card


24.05.2017

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МБ вона ніяк не хотіла монтуватися. Потім картку поміняв на нову 32Гб, і все відразу запрацювало. Якщо у Вас виникнуть подібні проблеми, майте на увазі, що проблема може бути у карті пам`яті.

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.."")
-- Execute hello.lc
print("LC file")
syscounter = tmr.now()
dofile("hello.lc")
print("time:"..tmr.now() - syscounter)
Бажаю успіхів.

Дивись також:

ESP8266
Коментарі:
Sandor говорить:
23.06.2017 11:14
Thanks!

Додати коментар
Code
* - обов'язкові поля

Архіви