ESP, IoT Загрузка файлов через COM-порт (ESP8266/ESP32)

VktrSansara

✩✩✩✩✩✩✩
1 Дек 2018
12
7
Новомосковск
Решил разобрать свою файловую помойку и наткнулся на программу, которая загружает файлы на esp8266 через COM-порт. Подумал, что это может быть полезно кому-то в их проектах.
Код был старый, корявый и костыльный, поэтому было решено его переделать.
- Ладно к делу...


LFSManager — легковесная библиотека для управления файловой системой LittleFS на ESP8266/ESP32 через UART (COM-порт) с помощью простого текстово-бинарного протокола.
Подойдет для загрузки файлов конфигураций, веб-страниц (HTML/JS/CSS) или картинок, lua скриптов во Flash-память микроконтроллера напрямую по USB-кабелю без использования Wi-Fi.
  • Загрузка файлов с ПК на Микроконтроллер (COM-порт UART)
  • Загрузка файлов с Микроконтроллера на ПК (COM-порт UART)
  • Доступ к файловой системе LittleFS для Загрузки, Удаления, Переименования файлов и Форматирования через LittleFS Desktop Manager
  • Никаких String - Библиотека использует исключительно C-строки.
  • Расчет контрольной суммы CRC32 "на лету". Файл сохраняется во временный буфер и заменяет оригинал только при 100% совпадении CRC32.
  • Работает с любым объектом Stream (Serial, Serial1, SoftwareSerial).
Ссылки:
Библиотека LFSManager
Софтина LittleFS Desktop Manager
Или exe с Яндекс.Диск

C++:
#include <Arduino.h>
#include "LFSManager.h"

// Передаем указатель на порт, через который будем общаться с ПК
LFSManager fileManager(&Serial);

// Использование с другим портом (HardwareSerial)
// RX:16, TX:17 для ESP32
// LFSManager fileManager(&Serial1);

void setup() {
    Serial.begin(115200);

    // Инициализация файловой системы внутри библиотеки
    fileManager.begin();

    // Ваш пользовательский код инициализации...
}

void loop() {
    // Вызов обработчика файлового менеджера
    fileManager.tick();

    // Ваш пользовательский код...
    // Избегайте использования delay(), используйте millis()
}
  • ❌ Чтение (Serial.read) - Вызывает конфликт.
    Библиотека непрерывно прослушивает входящие данные в функции tick(). Если в вашем цикле loop() вы тоже начнете вызывать Serial.read(), возникнет путаница в чтении данных и файл будет загружен с ошибкой.
  • ⚠ Запись (Serial.print) - Почти не мешает. Python-программа на ПК игнорирует любой текст, который не соответствует её протоколу.
    Вы можете выводить отладочную информацию (например, Serial.println("Temp: 25");).
    Избегайте сильного "спама" в порт во время загрузки/скачивания файлов, чтобы не переполнить буфер и не вызвать таймаут передачи.
Как правильно интегрировать библиотеку?

Вариант 1: Использование разных портов.

Если микроконтроллер поддерживает несколько аппаратных UART (ESP32) или вы используете SoftwareSerial (ESP8266), разделите потоки.
Оставьте основной Serial для вашей программы/отладки, а файловый менеджер повесьте на другой порт.
Конструктор библиотеки принимает любой объект класса Stream:
C++:
#include <Arduino.h>
#include "LFSManager.h"

// Файловый менеджер работает через Serial1 (ESP32: RX 16, TX 17)
LFSManager fileManager(&Serial1);

void setup() {
    Serial.begin(115200);  // Ваш порт (например, подключен к USB)
    Serial1.begin(115200); // Порт для связи с ПК (Файловый менеджер)
    fileManager.begin();
}

void loop() {
    fileManager.tick(); // Читает ТОЛЬКО Serial1

    // Вы спокойно работаете с основным Serial
    if (Serial.available()) {
        String msg = Serial.readString();
        Serial.println("Echo: " + msg);
    }
}
Вариант 2: Добавление пользовательских команд в библиотеку.
Если доступен только один USB-порт, и вы хотите управлять устройством по тому же кабелю, добавьте обработку своих команд напрямую в парсер библиотеки LFSManager.cpp (в метод processCommand):
C++:
void LFSManager::processCommand(char* cmdStr) {
    char* cmd = strtok(cmdStr, ":");
    if (!cmd) return;
    // --- СТАНДАРТНЫЕ КОМАНДЫ ФАЙЛОВОГО МЕНЕДЖЕРА ---
    if (strcmp(cmd, "PING") == 0) { ... }
    // ... остальной код библиотеки ...
    // --- ВАШИ ПОЛЬЗОВАТЕЛЬСКИЕ КОМАНДЫ ---
    else if (strcmp(cmd, "LED_ON") == 0) {
        digitalWrite(LED_BUILTIN, HIGH);
        _serial->println("LED_STATUS:ON");
    }
    else if (strcmp(cmd, "SET_TEMP") == 0) {
        char* valStr = strtok(NULL, ":"); // Читаем аргумент после двоеточия
        int temp = atoi(valStr);
        // Применяем температуру...
    }
}
Вариант 3: Режим "Сервисного обслуживания" (Переключатель)
Сделайте так, чтобы файловый менеджер и ваш код работали по очереди.
Переключение может происходить по удержанию физической кнопки (например, BOOT) или программному флагу.
C++:
#include <Arduino.h>
#include "LFSManager.h"
LFSManager fileManager(&Serial);
bool isFileManagerMode = false;
void setup() {
    Serial.begin(115200);
    fileManager.begin();
    pinMode(0, INPUT_PULLUP); // Кнопка BOOT на большинстве плат
}
void loop() {
    // Вход в режим Файлового менеджера по нажатию кнопки
    if (digitalRead(0) == LOW) {
        isFileManagerMode = true;
        Serial.println("ENTERED FILE MANAGER MODE");
        delay(500); // Антидребезг
    }
    if (isFileManagerMode) {
        // Режим 1: Работает только библиотека
        fileManager.tick();
    } else {
        // Режим 2: Работает ваш основной код
        if (Serial.available()) {
            char c = Serial.read();
            // Обработка ваших команд...
        }
    }
}
  • Нужно одновременное, независимое чтение — используйте Вариант 1.
  • Связь идет только через один кабель — используйте Вариант 2 или 3.
LittleFS Desktop Manager - Файловый менеджер на Python (Tkinter). Позволяет загружать, скачивать, удалять, переименовывать файлы и форматировать память LittleFS на микроконтроллерах (ESP8266/ESP32) прямо через COM-порт.

aStKS3jQN1uuqMXezGMb4Txu3XdwBqNvH0kpg0pWPr4e5Gy_X2gHOfjqRrkC7vMnducp7-EgduwVhBEy6Z_wbanu.jpg
  • Не рекомендую загружать файлы на МК большими пачками, это приведет к ошибкам и зависанию МК.
    Хотя до 30штук он может принять без ошибок.
  • Загрузка с МК нескольких файлов тоже приводит к ошибкам, но чаще всего это битые файлы.
  • Файлы более 100Кб уже лотерея.
  • Длинна провода
  • Скорость передачи (115200 оптимальная скорость)
  • Через HUB можно даже не пытаться (Хотя через мой хаб из Фикспрайса работало с переменным успехом).
 
Изменено: