Funcionalidad de SPIFFS.

Funcionalidad de SPIFFS.

QUÉ ES SPIFFS.

Podemos decir que SPIFFS es un sistema de archivos destinado a dispositivos flash SPI NOR embebidos. Vamos a aprender en detalle cómo utilizar el SPIFFS (del inglés Serial Peripheral Interface Flash Fail System), como configurar nuestro IDE de Arduino y así, poder cargar archivos en el ESP8266, aunque el sistema de archivos flash SPIFFS se almacena en el mismo chip que el boceto, la programación de un nuevo boceto no modificará el contenido del sistema de archivos SPIFFS. Esto permite utilizar el sistema de archivos para almacenar datos del boceto, archivos de configuración o contenido para el servidor web.


Fig. 1

Lo que viene a decir es que el sistema flash SPI dispone como de un disco duro interno, y como tal se puede particionar el sistema, de modo que vamos a explicar como acceder a este disco interno, para leer/guardar, particionar y borrar datos en él. No iremos más allá del almacenamiento SPIFFS en este artículo.

Por supuesto, usted puede escribir un código para leer y escribir los datos de una manera más accesible, aunque es incómodo y propenso a errores. Especialmente si los datos almacenados tienen formatos diferentes, digamos que una parte es un objeto JSON y la siguiente es HTML, deberá crear una tabla de contenido (TOC) y realizar un seguimiento de los tamaños y puntos de inicio de estos bloques.


Fig. 2

De manera que los ESP8266 nos permiten actuar sobre dicho disco, cuyo tamaño varía de un modelo a otro (los modelos más antiguos, no ofrecen), se trata de un banco de memoria flash del sistema que podemos particionar y así usarlo para almacenar nuestro código como un sistema de archivos. El sistema, archiva datos que no cambian con frecuencia, como configuración de sensores, páginas web, configuración del boceto, etc.

Bueno, en algún sitio oí decir con cierta razón: «tampoco es bueno morder más de lo que puedas masticar«. Quiero decir que, estamos empezando y lo propio sería realizar una presentación y algún ejemplo que nos de un resultado y nos aliente a seguir entrando en el tema del SPIFFS. Así que, brevemente veremos cómo usar el SPIFFS, cuanto flash tiene un dispositivo y configuraremos el IDE de Arduino para cargar nuestros archivos en el ESP8266.

Necesitaremos un IDE Arduino 1.6.9 o mayor, ya vimos como configurar el IDE de Arduino también debería tener instalado en su sistema el python2.7. Escoja un ESP8266-01 y prepárese para realizar con un poco de paciencia, una práctica con la que reforzar los conocimientos que adquiera en este artículo.

En primer lugar, es conveniente y necesario saber cuánta memoria tiene nuestro flash SPI. Esto puede ser deducido en la hoja de datos del ESP8266-01. Conociendo esto, primero debemos decidir aproximadamente la cantidad del flash que deseamos darle a los SPIFFS.

Para cargar sus bocetos en el SPIFFS del ESP8266, es aconsejable seguir estos pasos:

  • Asegúrese de tener un subdirectorio dentro de su directorio de boceto llamado ‘data’,
  • Coloque los archivos que desea cargar en el directorio ‘data’
  • Vaya al menú ‘Herramientas’, seleccione el dispositivo ESP8266 correcto y elija el ‘Tamaño de Flash’ que necesita en el SPIFFS, es decir ‘2Mb (1Mb SPIFFS’). Vea la tabla 1.
  • Asegúrese de que el cuadro de diálogo del monitor serie esté cerrado.
  • Prepare el dispositivo ESP8266 (ESP8266-01) para cargar.
  • Mantenga pulsado ‘Flash’,
  • Pulso ‘Reset’
  • Lanzamiento ‘Flash’
  • Desde el menú Herramientas, seleccione ‘ESP8266 Sketch Data Upload’ Vea la foto 3 arriba de la imagen
  • Una vez finalizada la carga. La ventana del mensaje IDE de Arduino mostrará 100% de carga. Ver foto 3 abajo de la imagen.

Si usted utiliza las versiones ESP8266-01, ESP 05, ESP 07, etc. para su comodidad, puede utilizar la herramienta que se describe en este artículo.

LIBRERÍAS.

La librería ESP8266FS es una herramienta que se debe integrar en el IDE de Arduino, con lo que se añadirá una opción en el menú Herramientas, con el que podremos cargar los archivos de la carpeta ‘data’ de nuestro boceto, en la partición SPIFFS del ESP8266.

Ahora tenemos que descargar la librería ESP8266FS desde:
https://github.com/esp8266/arduino-esp8266fs-plugin/releases/…  o desde
https://github.com/esp8266/arduino-esp8266fs-plugin/releases/…

Sigamos, descomprima el ZIP, vaya a C:\Program Files\Arduino\tools (en mi caso), y descargue la carpeta ESP8266FS o si lo prefiere, cree en la librería una carpeta con el nombre ESP8266FS y dentro otra carpeta con el nombre tool y dentro, descargue el archivo esp8266fs.jar, debe quedar algo así, C:\Program Files\Arduino\tools\ESP8266FS\tool\esp8266fs.jar.


Fig. 3

Hago hincapié, el software que debemos utilizar es el IDE Arduino 1.6.9 o superior. Ahora sólo tenemos que reiniciar el ID de Arduino e iremos al menú Herramientas y nos mostrará una ventana similar a esta:


Fig. 4

Los archivos que queremos transferir en el área SPIFFS desde el IDE de Arduino, los depositamos en la carpeta ‘data’ de nuestro proyecto es decir, por ej.:

Esta herramienta carga cualquier archivo que se encuentre dentro de una carpeta denominada «data«. La carpeta data debe estar dentro de la carpeta de su boceto, dentro de la cual estará el archivo filename.txt, si no existe dicho archivo, se creará.

Atención: La acción que vamos a realizar, borrará todo el contenido de SPIFFS del ESP8266 y cargará los datos contenidos en la carpeta data. No se conservan los archivos que hubiera originales / anteriores, por lo que si necesita dichos datos, debería hacer una copia antes de cargar los nuevos datos de la carpeta data, sin embargo no afectará al boceto.

FUNCIONES DE LA LIBRERÍA SPIFFS

Veamos cómo usar SPIFFS en nuestro programa con Arduino para ESP8266. Aquí, sólo veremos alguna de las funciones que se pueden utilizar con esta librería:

  • Nuestro boceto, debe incluir entre otras la librería «FS.h«. Ésta librería «FS.h» no se puede utilizar junto a la librería SD ya que actualmente son incompatibles.
  • Para iniciar el uso de SPIFFS deberemos incluir: SPIFFS.begin(); si funciona correctamente devolverá true.
  • De igual manera cuando queramos dejar de utilizarlo usaremos la función SPIFFS.end();.
  • Podemos formatear la unidad con: SPIFFS.format(); Si queremos guardar/borrar datos del programa. Esta función puede ser llamada antes o incluso después de begin().
  • También podemos hacer particiones. Para saber más sobre las particiones, lea
  • Para asegurarnos que existe un archivo usaremos: SPIFFS.exists(path);. Devolverá true si el archivo existe. Recordar que el path es el nombre completo, no un archivo dentro de una carpeta.
  • También hay un filtro que utiliza algo parecido a carpetas: SPIFFS.openDir(path, mode);. Abre un fichero, path debe ser un camino absoluto comenzando con un slash (p.ej. /dir/filename.txt), mode es una letra que especifica el modo de acceso. Puede ser una de las siguientes: rwar+w+a+, que se puede usar así:
  • La secuencia se coloca en el comienzo del archivo.

r -Abre un fichero de texto para leerlo.
r+ -Abre un fichero para lectura y escritura.
w Trunca en fichero con una longitud cero o crea un fichero
de texto para escritura.
w+ -Abre para lectura y escritura. El fichero si no existe, se
crea de lo contrario se trunca.
a -Abre el fichero para añadir (escribiendo al final del
fichero). El fichero si no existe, se crea.

a+ -Abre el fichero para añadir (escribiendo al final del
fichero). El fichero si no existe se crea.
La posición inicial para lectura es al comienzo del fichero,
pero la salida siempre se añade al final del fichero.

  • El objeto directorio Dir
    El propósito del objeto Dir es iterar sobre los ficheros dentro del directorio. Provee los métodos:

Dir dir = SPIFFS.openDir(«/data»);
while (dir.next()) {
  Serial.print(dir.fileName()); // Nombre del archivo
  File f = dir.openFile(«r»); // Abrir archivo
  Serial.println(f.size()); // Tamaño, se vera más tarde.
  if (dir.fileSize()) {
  File f=dir.openFile(‘r’);
  Serial.println(f.size());
 }
}

  • Muestra información del sistema de archivos:

FSInfo fs_info;
SPIFFS.info(fs_info);

  • Si necesitamos eliminar un sólo fichero usaremos:

SPIFFS.remove(path);    Devuelve true si ha sido correctamente eliminado

  • Si queremos renombrar un fichero usaremos:

SPIFFS.rename(pathFrom, pathTo); Devuelve true si ha sido correctamente cambiado de nombre.
SPIFFS_rename        – Para renombrar archivos.
SPIFFS_clearerr       – Para borra el último error.
SPIFFS_info                – Devuelve información sobre bytes usados ​​y totales en fs.
SPIFFS_format          – Para formatear el sistema de archivos.
SPIFFS_mounted      – Comprueba si el sistema de archivos está montado.

  • Para obtener información del sistema de archivos usaremos:

FSInfo fs_info;
SPIFFS.info(fs_info);

Donde la estructura FSInfo es:

struct FSInfo {
size_t totalBytes; // Tamaño total utilizable en el sistema de archivos en bytes
size_t usedBytes; // Bytes usados en el sistema de archivos
size_t blockSize; // Tamaño del bloque, en bytes
size_t pageSize; // Tamaño de la página, en bytes
size_t maxOpenFiles; // Num. máximo de archivos simultáneamente abiertos.
size_t maxPathLength; // Tamaño máximo del path, incluyendo el ‘\0’ final. Normalmente debería ser 32.
};

Otra cualidad del flash ESP8266 es que también admite actualizaciones OTA, no obstante, en este artículo nos limitaremos a la funcionalidad de SPIFFS.

ESTRUCTURA DEL SISTEMA DE ARCHIVOS

Sólo a titulo de ejemplo: «En primer lugar, necesitamos saber cuánta memoria tiene el flash SPI, su tamaño de página o tamaño de página físico y su/s sector/es de bloque (es decir, tamaño de bloque físico). Esto puede ser deducido en la hoja de datos. Teniendo esto, primero se debe decidir aproximadamente la cantidad del flash SPI que deseamos darle a los SPIFFS.

Digamos que su flash tiene tamaños de bloque físico de 4kB, 16kB y 64kB. Entonces puede tener tamaños de bloque lógicos de n * 4kB, o n * 16kB, o n * 64kB, donde n es un número entero. La opción más común es establecer el tamaño del bloque lógico en la misma cantidad que un tamaño de bloque físico. El tamaño del sistema de archivos debe ser un múltiplo entero del tamaño de bloque lógico«.

Tabla 1 Flash

Como se puede apreciar hay materia que estudiar, por lo que si está interesado usted puede adquirir los conocimientos que estime siguiendo las referencias que se muestran más abajo.


Tabla 2

Para más información, consulte la wiki para configurar spiffsintegrar spiffsusar spiffs y optimizar spiffs.

El sistema de archivos tiene unas limitaciones que debemos tener en cuenta:

  • La longitud máxima de la ruta de archivos es 31 caracteres.
  • No admite directorios. Sin embargo, podemos usar «/» dentro del nombre de archivo («/proyecto/boceto1.txt» sería un nombre completo, no un archivo dentro de la carpeta «proyecto»).

Como vemos SPIFFS no soporta directorios, sólo almacena una lista ‘plana’ de ficheros. Por el contrario que un sistema de ficheros tradicional, el carácter (slash) ‘/’ está permitido en los nombres de ficheros, de modo que las funciones que se ocupan de listar directorios por ejemplo, openDir(«/website»), básicamente solo filtra los nombres de archivo y conserva los que comienzan con el prefijo solicitado ( /website/).

La longitud máxima de la ruta de archivos es 31 caracteres, este límite se alcanza fácilmente y si se ignora, los problemas podrían pasar desapercibidos porque no aparecerá ningún mensaje de error en la compilación ni en el tiempo de ejecución. Se recomienda mantener los nombres de archivo cortos y no usar directorios anidados profundamente. Por ejemplo, el nombre de archivo /website/images/bird_thumbnail.jpg, tiene 34 caracteres y causará problemas si se utiliza, por ejemplo en exists()

CUÁNTA FLASH TIENE MI ESP8266.

Es tanta la variedad de suministradores de los dispositivos ESP8266, a parte que no están disponibles los datos de estos productos y por tanto no son claros ni concisos. He estado leyendo que hay que averiguar qué tamaño tiene nuestro flash y que existe un método bastante fiable y rápido consistente en cargar el dispositivo con el boceto CheckFlashConfig.ino y revisar la salida del monitor serie como se muestra en la imagen de la figura 8.

El código CheckFlashConfig.ino es un ejemplo que viene en la librería que nos permitirá conocer los valores del ID flash realtamaño del Flash ide, la velocidad Flash ideFlash ide mode y si la Configuración del chip flash ok. Abra el monitor serie para ver los valores que tiene su ESP.

Al compilar el boceto CheckFlashConfig.ino, puede que obtenga usted algún error, si es así, observe la siguiente figura.


Fig. 5

Revise en el Menú/Herramientas/Placa… la versión de la tarjeta, debe ser la versión 2.6.0 (no la 2.5.0).


Fig. 6

Modifique su tarjeta elegida y compile, esta vez sin error.


Fig. 7

Ahora, ya puede subir su boceto CheckFlashConfig.ino y abra su monitor serie, para comprobar el tamaño de su SPIFFS.


Fig. 8

Para alcanzar un conocimiento optimo, siga la regla: prueba, ensayo error y prueba.

PONER EN USO.

  • Abra un boceto (o cree uno nuevo y guárdelo).
  • Vaya al directorio de bocetos (elija Boceto> Mostrar carpeta de bocetos).
  • Cree un directorio con el nombre data con los archivos que desee en el sistema.
  • Asegúrese de haber seleccionado una placa, un puerto y el monitor serie cerrado.
  • Seleccione Herramientas> ESP8266 Elemento de menú Cargar datos de croquis .
    Ya debería comenzar a cargar los archivos en el sistema de archivos flash ESP8266.
    Cuando haya terminado, la barra de estado IDE mostrará el mensaje de carga de
    imagen SPIFFS. Puede tardar unos minutos para tamaños de sistema de archivos
    grandes.

VEAMOS UNOS EJEMPLOS.

Como ya se ha dicho deberemos incluir un archivo por ejemplo file.txt con los datos que necesitemos subir, dentro de una carpeta con el nombre data.

Aunque los ejemplos que se describen en este artículo hacen referencia al ESP8266-01, funcionan igualmente con los ESP-07, ESP8266-12, ESP8266-12E, ESP8266-13, etc.

Ejemplo de utilidad SPIFFS.

Leer y escribir en un archivo.

El siguiente es otro ejemplo más elaborado que, muestra como leer y escribir en un archivo.

Ejemplo de lectura y escritura de archivos SPIFFS.

El siguiente boceto nos muestra un caso en el que nos hemos visto alguna vez, cuando hemos perdido la conexión del suministro eléctrico, perdiendo el último estado o valor de una función o un simple pulsador. En este caso, se recuperará el estado en que ha quedado un LED en el momento de perder por algún motivo la energía.

Ejemplo práctico de utilidad SPIFFS.

Muestra como recuperar el último estado de un LED, después del reinicio.

En el boceto, lo primero es incluir la librería FS.h y en este caso asignar los pines que vamos a utilizar como son:

Considero que está bastante documentado y es bastante explicito el código. Se comprende que tenemos que subir el código una primera vez descomentada, la línea:

Para que se guarde el estado ‘off’ en la memoria flash. De modo que la segunda vez que subamos el código, dicha línea la debemos comentar.

Si todo ha ido bien y así lo espero, ya podemos comprobar el efecto que hemos subido con este código. Primero, podemos presionar el pulsador y en cada pulsación se enciende o apaga el LED, al pulsar de nuevo se encenderá, desconectemos la energía quitando el cable USB o batería, con lo cual se apagará el LED y si volvemos a conectar el cable USB o la alimentación, veremos que el LED vuelve a encenderse, que es el estado que tenía al quitar la energía.


Vídeo

En el vídeo se aprecia lo descrito, en esta práctica he guardado el estado del LED encendido, por que se aprecia mejor que se ha guardado, ya que al volver a darle energía el LED aparecerá encendido, usted puede guardar otra información que se adapte a sus necesidades como datos de sensores, datos para una base de datos, hojas excel, etc.

Esto es todo, por este simple tutorial, espero sus preguntas. No haga malas prácticas, sin insultos ni faltas de respeto, sea positivo.

Referencias:

6 thoughts on “Funcionalidad de SPIFFS.”

  1. Muy buenos días. He encontrado muy ilustrativo el documento. Querría hacerle una pregunta: Así como se graba en la flash los archivos, se pueden recuperar de algún modo tras haberlos completado con los datos de los sensores, que haya puesto? La forma que se me ocurre es exponiéndolos en html y ya en un explorador exportar la pantalla como texto. Habría la forma de sacar el fichero con todos los datos directamente de la memoria flash?
    Gracias y un saludo, Lorenzo

    1. Hola Lorenzo Barrio.
      Tu consulta tiene dos versiones:

      1) en el caso de querer recuperar los datos de un programa almacenados en la memoria flash, en cuyo caso deberías servirte de un programa dedicado para ese menester, cosa que no es sencillo ya que es necesario tener conocimientos y experiencia en programación.

      2) El caso de generar un programa que luego de subido a la memoria flash quieras recuperar (creo que es el caso que buscas), en ese caso es medianamente más sencillo ya que al programar tienes que pensar en incluir rutinas que te permitan recuperar de algún modo el propio programa y sus datos cosechados. Algo parecido a los datos que puedes ver en los ejemplos para tener una idea aproximada de lo que quiero decir, he comentado algunas ideas en ellos.

      Puedes ver algún ejemplo en los enlaces que tienes en el artículo, como en:
      https://www.esploradores.com/uso-memoria-flash-para-almacenamiento-de-datos/

      Supongo que no es lo que querías leer, pero… el caso es bastante complejo y no todos están en condiciones de dar una respuesta sencilla y eficaz. Siento la decepción que puedas experimentar.

      Saludos y cuídate.
      Reedito:
      Lee el artículo: https://www.esploradores.com/uso-memoria-flash-para-almacenamiento-de-datos/
      y especial atención a la consulta y respuesta que tiene al final.

  2. Buena tarde, tengo una pregunta
    Durante una interrupción por hardware se puede leer o escribir un archivo?
    Estoy en la parte de la rutina de interrupción y quiero leer un archivo (leeInfo(«/f.txt»);) o escribir guardaInfo(«/f.txt», Precios); y me sale el error:
    abort() was called at PC 0x400848cd on core 1

    Backtrace: 0x400888bc:0x3ffc08f0 0x40088abf:0x3ffc0910 0x400848cd:0x3ffc0930 0x400849f9:0x3ffc0960 0x4000be35:0x3ffc0980 0x40001e0e:0x3ffc09a0 0x40001e93:0x3ffc09c0 0x400d52ab:0x3ffc09e0 0x400d5348:0x3ffc0a10 0x400d153e:0x3ffc0a30 0x400d186f:0x3ffc0a60 0x400d1ad1:0x3ffc0aa0 0x400d11d3:0x3ffc0b20 0x400d11f2:0x3ffc0b50 0x400d0e4b:0x3ffc0b70 0x40081189:0x3ffc0bb0 0x40081309:0x3ffc0bf0 0x40081a9d:0x3ffc0c10 0x400eea5b:0x00000000

    Hay alguna solución?

    1. Hola Arturo Bernal.
      Naturalmente que puedes leer/escribir un archivo.
      En cuanto al error que me comentas es la primera noticia y no se porque ha ocurrido. Intenta entrar en un foro sobre el tema.

      Lo siento, no tengo una respuesta.

      Saludos.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.