// ============================================================
// ЕДИНЫЙ СКЕТЧ ДЛЯ ДВУХ ПРОШИВОК
// Компилируем 1 раз, прошиваем 1 раз — работает как две программы
// ============================================================
#include <esp_partition.h>
#include <esp_ota_ops.h>
#define LED_PIN 2
// Таймер для первой прошивки (10 секунд до переключения)
#define SWITCH_DELAY_MS 10000
// Пин для кнопки возврата к первой прошивке (опционально)
#define RESET_PIN 0 // GPIO0 (кнопка BOOT на многих платах)
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(RESET_PIN, INPUT_PULLUP);
// Определяем, с какого раздела мы запустились
const esp_partition_t* running = esp_ota_get_running_partition();
const char* running_partition = running->label;
Serial.println("\n========================================");
Serial.printf("Запущен раздел: %s\n", running_partition);
Serial.println("========================================\n");
// -----------------------------------------------------------------
// ЛОГИКА ДЛЯ ПЕРВОЙ ПРОШИВКИ (раздел ota_0)
// -----------------------------------------------------------------
if (strcmp(running_partition, "ota_0") == 0) {
Serial.println("Первая прошивка: мигаю LED 10 секунд...");
// Мигаем LED 10 секунд
for (int i = 0; i < 20; i++) {
digitalWrite(LED_PIN, HIGH);
delay(250);
digitalWrite(LED_PIN, LOW);
delay(250);
if (i % 4 == 0 && i > 0) {
Serial.printf(" прошло %d сек\n", i/2);
}
}
Serial.println("\n10 секунд прошло! Переключаюсь на вторую прошивку...");
// Находим раздел ota_1
const esp_partition_t* target = esp_partition_find_first(
ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_OTA_1,
NULL
);
if (target == NULL) {
Serial.println("ОШИБКА: раздел ota_1 не найден!");
return;
}
// Устанавливаем ota_1 как загрузочный
esp_err_t err = esp_ota_set_boot_partition(target);
if (err != ESP_OK) {
Serial.println("ОШИБКА: не удалось переключить раздел!");
return;
}
Serial.println("OK! Перезагрузка через 1 секунду...");
delay(1000);
esp_restart();
}
// -----------------------------------------------------------------
// ЛОГИКА ДЛЯ ВТОРОЙ ПРОШИВКИ (раздел ota_1)
// -----------------------------------------------------------------
else if (strcmp(running_partition, "ota_1") == 0) {
Serial.println("Вторая прошивка: работаю постоянно!");
Serial.println("(можно добавить логику возврата на первую прошивку)\n");
// Бесконечное мигание
while (true) {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED включен");
delay(1000);
digitalWrite(LED_PIN, LOW);
Serial.println("LED выключен");
delay(1000);
// Опционально: если нажата кнопка — возвращаемся к первой прошивке
if (digitalRead(RESET_PIN) == LOW) {
Serial.println("\nКнопка нажата! Возвращаюсь к первой прошивке...");
const esp_partition_t* target = esp_partition_find_first(
ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_OTA_0,
NULL
);
if (target) {
esp_ota_set_boot_partition(target);
delay(500);
esp_restart();
}
}
}
}
}
void loop() {
// Для второй прошивки loop не нужен (уже в while)
// Для первой сюда не доходит — перезагрузились раньше
delay(1000);
}
вроде делал это как то, и забыл))) ради интереса решил сейчас попытаться загрузить это вывод такой
Запущен раздел: ota_0
========================================
Первая прошивка: мигаю LED 10 секунд...
прошло 2 сек
прошло 4 сек
прошло 6 сек
прошло 8 сек
10 секунд прошло! Переключаюсь на вторую прошивку...
E (10018) esp_image: image at 0x200000 has invalid magic byte (nothing flashed here?)
ОШИБКА: не удалось переключить раздел!
файл .csv по пути C:\Users\User\Desktop\FLProg\ideV8\portable\packages\esp32\hardware\esp32\2.0.17\tools\partitions был заменен на это
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
ota_0, app, ota_0, 0x10000, 0x1F0000,
ota_1, app, ota_1, 0x200000, 0x200000,
наверное надо как то код разместить еще и в ota_1 … может будет кому то интересно… держу в курсе, и продолжаю вести наблюдение!)))