Общие сведения:
В этом проекте мы настроим Piranha ESP32 на подключение к существующей точке доступа WiFi, запустим Web-сервер ESP32, создадим файл во встроенной памяти при помощи файловой системы SPIFFS, а при подключении к локальному Web-сайту по имени piranha-logger.local можно будет скачать файл, в который с периодичностью в десять секунд записываются текущие millis().
Для работы данного скетча внутренняя память Piranha ESP32 должна быть отформатирована. Для этого либо воспользуйтесь утилитой загрузки файлов на Piranha ESP32, либо раскомментируйте строку SPIFFS.format() в функции setup().
- Процедуру форматирования необходимо выполнить только один раз.
- При использовании любого метода все файлы, загруженные вами или созданные скетчем ранее, будут удалены.
- Если процедуру форматирования не убрать из скетча и не загрузить новую версию скетча в плату, то память будет очищаться при каждом включении или перезагрузке микроконтроллера.
- Процедура
format()занимает относительно долгое время, будьте терпеливы.
Создание файлов
В этом примере файл перезаписывается каждый раз. Для записи с сохранением предыдущих показаний измените способ открытия файла с "w" на "a" (с SPIFFS.open("/logger.txt", "w") на SPIFFS.open("/logger.txt", "a")).
Данный подход, например, можно использовать для ведения журнала показаний датчиков за небольшой промежуток времени. Стоит помнить, что памяти, доступной для файловой системы, 1 МБ. Если нужно вести длительные наблюдения показаний, стоит воспользоваться записью файлов на внешний носитель (например на SD-карту).
Скачивание файлов
В данном примере создаётся локальный Web-сайт, доступ к которому можно получить по ссылке http://piranha-logger.local. Сайт генерируется кодом скетча и выводит список файлов, хранящихся во внутренней памяти, на указанный выше локальный сайт. Доступ по имени возможен благодаря серверу mDNS (Multicast DNS), библиотеку которого мы используем в скетче. Если по каким-то причинам mDNS не работает в локальной сети - то сайт может быть доступен по адресу, который выводится в последовательный порт сразу после подключения к точке WiFi.
Видео:
редактируется ...
Нам понадобится:
Подключение:

Скетчи проекта:
Скетч с перезаписью файла. В скетче необходимо указать Ваши данные для Вашей точки доступа WiFi.
Копировать123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183`// Подключаем библиотеки #include <WiFi.h> #include <WebServer.h> #include <ESPmDNS.h> #include <SPIFFS.h>
// Определяем интервал записи в файл const unsigned long INTERVAL = 10000; unsigned long write_millis = 0;
// Определяем название и пароль точки доступа const char ssid = "название_WiFi"; // Это поле нужно заполнить необходимыми данными const char password = "пароль_WiFi"; // Это поле нужно заполнить необходимыми данными
// Определяем имя сервера в сети const char* host = "piranha-logger";
// Создаём объект Веб-сервера WebServer server(80);
// Функция обработки клиента void handleClient() { // Выводим содержимое корневого каталога как Веб-страницу listRootToHtml(); }
// Функция чтения файла bool handleFileRead(String path) { // Открываем файл для чтения по указанному пути File file = SPIFFS.open(path, "r");
// Если файл не удалось открыть if (!file) { Serial.println("Ошибка. Файл не существует.");
// Отвечаем клиенту ошибкой server.send(404, "text/plain", "FileNotFound");
// Возвращаемся из функции return false; }
// Отдаём клиенту содержимое файла server.streamFile(file, "text/html"); // Закрываем файл file.close(); // Возвращаемся из функции return true; }
// Функция вывода списка файлов в HTML страницу void listRootToHtml() { // Открываем корневой файл File root = SPIFFS.open("/");
// Если не получилось открыть if (!root) { // Выводим ошибку Serial.println("error"); // Возвращаемся из функции return; }
// Создаём строку для конкатенации String html = "<html><meta charset=\"UTF-8\"><body>";
// Если корневой файл - каталог if (root.isDirectory()) {
// Открываем следующий файл File file = root.openNextFile();
// Входим в цикл, если файл существует / После прохода данного цикла должна получиться страница вида: <html><meta charset="UTF-8"><body> <p><a href="имя_первого_файла download="имя_первого_файла"> имя_первого_файла</a></p> <p><a href="имя_второго_файла download="имя_второго_файла"> имя_второго_файла</a></p> ..... <p><a href="имя_N-фала download="имя_N-файла"> имя_N-файла</a></p> </body></html> / while (file) {
// Записываем имя файла String name = file.name();
// Удаляем первый символ ("/"); name.remove(0, 1);
// Конкатенируем строку html += "<p><a href=\""; html += name; html += (String)"\" download=\""; html += name +"\">"; html += name; html += "</a></p>";
// Открываем следующий файл file = root.openNextFile(); } html += "</body></html>"; }
// Отравляем страницу клиенту server.send(200, "text/html", html); }
void setup() {
// Форматируем внутренную память (нужно выполнить только один раз) // SPIFFS.format();
// Инициируем объект файловой системы SPIFFS.begin();
Serial.begin(115200); Serial.println(); Serial.println("Подключаемся к WiFi");
// Инициируем точку доступа WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { Serial.print('.'); delay(100); } // Записываем IP-адрес IPAddress myIP = WiFi.localIP();
// Инициируем Multicast DNS MDNS.begin(host);
// Выводим IP-адрес Веб-сервера Serial.print("IP-адрес: "); Serial.println(myIP);
// Функция, выполняемая при подключении к клиента корневому каталогу server.on("/", HTTP_GET, handleClient); // Функция, которая будет выполнена, если файл не найден server.onNotFound([]() { // Если по указанному пути файл не найден... if (!handleFileRead(server.uri())) { // Отвечаем клиенту ошибкой 404 server.send(404, "text/plain", "FILE NOT FOUND"); } });
// Инициируем сервер server.begin(); Serial.println("Сервер запущен."); }
void loop() { // Библиотечная функция обработки клиента server.handleClient();
// Если прошёл интервал ожидания if (millis() - write_millis > INTERVAL) { // Записываем текущие millis write_millis = millis(); // Создаём файл с абсолютным путём File file = SPIFFS.open("/logger.txt", "w");
// Если файл не получилось создать if (!file) // Выводим сообщение Serial.println("error creating file"); // Иначе else // Выводим текущие millis в файл file.println(write_millis); file.flush(); file.close(); } // Даём процессору переключиться на другие задачи delay(2); }`
Скетч с добавлением в файл и записью показаний с текущим реальным временем
Копировать123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197`// Подключаем библиотеки #include <WiFi.h> #include <WebServer.h> #include <ESPmDNS.h> #include <SPIFFS.h> #include "time.h"
// Определяем интервал записи в файл const unsigned long INTERVAL = 10000; unsigned long write_millis = 0;
// Определяем название и пароль точки доступа const char ssid = "название_WiFi"; // Это поле нужно заполнить необходимыми данными const char password = "пароль_WiFi"; // Это поле нужно заполнить необходимыми данными
// Определяем сервер времени const char* ntpServer = "pool.ntp.org";
// Определяем имя сервера в сети const char* host = "piranha-logger";
// Создаём объект Веб-сервера WebServer server(80);
// Функция обработки клиента void handleClient() { // Выводим содержимое корневого каталога как Веб-страницу listRootToHtml(); }
// Функция чтения файла bool handleFileRead(String path) { // Открываем файл для чтения по указанному пути File file = SPIFFS.open(path, "r");
// Если файл не удалось открыть if (!file) { Serial.println("Ошибка. Файл не существует.");
// Отвечаем клиенту ошибкой server.send(404, "text/plain", "FileNotFound");
// Возвращаемся из функции return false; }
// Отдаём клиенту содержимое файла server.streamFile(file, "text/html"); // Закрываем файл file.close(); // Возвращаемся из функции return true; }
// Функция вывода списка файлов в HTML страницу void listRootToHtml() { // Открываем корневой файл File root = SPIFFS.open("/");
// Если не получилось открыть if (!root) { // Выводим ошибку Serial.println("error"); // Возвращаемся из функции return; }
// Создаём строку для конкатенации String html = "<html><meta charset=\"UTF-8\"><body>";
// Если корневой файл - каталог if (root.isDirectory()) {
// Открываем следующий файл File file = root.openNextFile();
// Входим в цикл, если файл существует / После прохода данного цикла должна получиться страница вида: <html><meta charset="UTF-8"><body> <p><a href="имя_первого_файла download="имя_первого_файла"> имя_первого_файла</a></p> <p><a href="имя_второго_файла download="имя_второго_файла"> имя_второго_файла</a></p> ..... <p><a href="имя_N-фала download="имя_N-файла"> имя_N-файла</a></p> </body></html> / while (file) {
// Записываем имя файла String name = file.name();
// Удаляем первый символ ("/"); name.remove(0, 1);
// Конкатенируем строку html += "<p><a href=\""; html += name; html += (String)"\" download=\""; html += name +"\">"; html += name; html += "</a></p>";
// Открываем следующий файл file = root.openNextFile(); } html += "</body></html>"; }
// Отравляем страницу клиенту server.send(200, "text/html", html); }
void setup() {
// Форматируем внутренную память (нужно выполнить только один раз) // SPIFFS.format();
// Инициируем объект файловой системы SPIFFS.begin();
Serial.begin(115200); Serial.println(); Serial.println("Подключаемся к WiFi");
// Инициируем точку доступа WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { Serial.print('.'); delay(100); } // Записываем IP-адрес IPAddress myIP = WiFi.localIP();
// Инициируем Multicast DNS MDNS.begin(host);
// Выводим IP-адрес Веб-сервера Serial.print("IP-адрес: "); Serial.println(myIP);
// Конфигурируем время configTime(3600*3, 0, ntpServer);
// Функция, выполняемая при подключении к клиента корневому каталогу server.on("/", HTTP_GET, handleClient); // Функция, которая будет выполнена, если файл не найден server.onNotFound([]() { // Если по указанному пути файл не найден... if (!handleFileRead(server.uri())) { // Отвечаем клиенту ошибкой 404 server.send(404, "text/plain", "FILE NOT FOUND"); } });
// Инициируем сервер server.begin(); Serial.println("Сервер запущен."); }
void loop() { // Библиотечная функция обработки клиента server.handleClient();
// Если прошёл интервал ожидания if (millis() - write_millis > INTERVAL) { // Записываем текушее время struct tm timeinfo; getLocalTime(&timeinfo);
// Записываем текущие millis write_millis = millis(); // Создаём файл с абсолютным путём File file = SPIFFS.open("/logger.txt", "a");
// Если файл не получилось создать if (!file) // Выводим сообщение Serial.println("error creating file"); // Иначе else // Выводим текущее время в файл file.print(&timeinfo, "%B %d %Y %H:%M:%S,");
// Выводим текущие millis в файл file.println(write_millis); file.flush(); file.close(); } // Даём процессору переключиться на другие задачи delay(2); }`
Ссылки
Комплект для повторения проекта
Что понадобится
Это быстрый ориентир по основным модулям и деталям. Полный список для повторения проекта смотрите в самой статье.
2 позиции