ESP32. Урок 35. NVS. Запись и чтение через PC



Продолжаем работу с энергонезависимым хранилищем данных (Non-volatile storageNVS), с которым мы познакомились в уроке 33, и сегодня мы попробуем изменить в нём значение некоторых пар ключ-значение посредством интерфейса UART с компьютера. Так как на прошлом уроке мы уже поработали с UART на чтение, то сделать это нам сильного труда не составит.

Схема наша также будет состоять из платы с контроллером ESP32, подключенной к порту USB компьютера

 

 

Проект нашего урока будет сделан на основе проекта урока 33 с именем NVS01 и назван будет NVS01_WRITE_PC.

Откроем наш проект в Espressif IDE и в файле main.h подключим заголовочный файл для работы с UART и заголовочный файл для работы с логами

 

 

Добавим ещё библиотеку для работы со строками

 

 

В файле main.c объявим размер буфера для UART и номера ножек портов

 

 

Также добавим функции для инициализации UART и для задачи приёма пакетов, взяв её вместе с телом из проекта прошлого урока с именем UART_RX

 

 

Из тела функции app_main удалим код, отвечающий за запись данных в NVS

 

// Write
int8_t val01 = -108;
uint8_t val02 = 198;
int16_t val03 = -10135;
uint16_t val04 = 61145;
int32_t val05 = -101459;
uint32_t val06 = 3352582294;
int64_t val07 = -4047512760478312334;
uint64_t val08 = 7214561357951254753;

printf("Updating data in NVS ... ");
err = nvs_set_i8(my_handle, "dt01", val01);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_u8(my_handle, "dt02", val02);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_i16(my_handle, "dt03", val03);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_u16(my_handle, "dt04", val04);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_i32(my_handle, "dt05", val05);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_u32(my_handle, "dt06", val06);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_i64(my_handle, "dt07", val07);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_u64(my_handle, "dt08", val08);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");

err = nvs_set_str(my_handle, "MySSID", "MyLogin");
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
err = nvs_set_str(my_handle, "MyPASS", "123abc7890");
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
printf("Committing updates in NVS ... ");
err = nvs_commit(my_handle);

printf((err != ESP_OK) ? "Failed!\n" : "Done\n");

 

Также часть кода, которая отвечает за чтение целых чисел, тоже удалим

 

int8_t res01 = 0;
uint8_t res02 = 0;
int16_t res03 = 0;
uint16_t res04 = 0;
int32_t res05 = 0;
uint32_t res06 = 0;
int64_t res07 = 0;
uint64_t res08 = 0;

nvs_get_i8(my_handle, "dt01", &res01);
printf("dt01: %d\n", res01);
nvs_get_u8(my_handle, "dt02", &res02);
printf("dt02: %d\n", res02);
nvs_get_i16(my_handle, "dt03", &res03);
printf("dt03: %d\n", res03);
nvs_get_u16(my_handle, "dt04", &res04);
printf("dt04: %d\n", res04);
nvs_get_i32(my_handle, "dt05", &res05);
printf("dt05: %d\n", res05);
nvs_get_u32(my_handle, "dt06", &res06);
printf("dt06: %u\n", res06);
nvs_get_i64(my_handle, "dt07", &res07);
printf("dt07: %lld\n", res07);
nvs_get_u64(my_handle, "dt08", &res08);
printf("dt08: %llu\n", res08);

 

Строку с объявлением хендла также удалим

 

nvs_handle_t my_handle;

 

и выполним объявление данной переменной в глобальной секции

 

 

Вернёмся в функцию app_main и после небольшой задержки произведём инициализацию UART, а также создадим задачу для чтения пакетов UART

 

 

Если не будет задержки, то сразу пойдёт инициализация шины и мы не увидим часть сообщений в терминале из предыдущего кода.

 

 

Перейдём в функцию инициализации uart_init и в параметрах выделим буферную память также для передачи пакетов

 

uart_driver_install(UART_NUM_0, RX_BUF_SIZE * 2, RX_BUF_SIZE * 2, 0, NULL, 0);

 

В функции rx_task в бесконечном цикле из строки приёма пакета удалим объявление константы, а также уменьшим таймаут, так как от него зависит то время, когда мы дождёмся результата приёма ибо мы передаём в параметре максимально-возможное количество принятых байтов, а принимаем меньше

 

const int rxBytes = uart_read_bytes(UART_NUM_0, data, RX_BUF_SIZE, 10 / portTICK_RATE_MS);

 

Из условия ниже удалим вот эти строки

 

data[rxBytes] = 0;
printf((char*)data);

 

Вместо них добавим ещё одно условие, в котором отследим команду начала пакета (такое условие программы, через которую мы будем передавать данные

 

 

Мы будем данные также и передавать на PC, поэтому в данном условии будут ещё два условия, которые будут разделять приём и передачу пакетов

 

 

Здесь всё наоборот. Read и Write относится не к пакетам, а к хранилищу, то есть Read — чтение из хранилища и передача на PC, а Write — приём из PC и запись в NVS.

При приёме и передаче пакетов мы будем менять уровень на ножке порта, к которой подключен синий светодиод. Для этого объявим локальную переменную

 

 

В условии, котором мы будем читать данные из NVS и передавать их на PC, применим уровень ножки и инвертируем состояние в переменной

 

 

Подготовим команду, чтобы программа на PC поняла, что мы начинаем передавать пакет

 

 

Объявим переменные для размера строк, откроем хранилище и узнаем размер строки с ключом MySSID, которая у нас хранится с прошлого урока

 

 

Запишем этот размер в массив для передачи

 

 

Прочитаем строку из NVS

 

 

 

Узнаем размер ключа MyPASS и также сохраним его в массив

 

 

Прочитаем строку и закроем хранилище

 

 

Передадим команду, размеры и строки в PC и очистим память, запрошенную под строки

 

 

Теперь работаем с приёмом данных строк из PC и записью их NVS.

Для этого в теле следующего условия объявим указатели на массивы для строк и узнаем их размер из пакета, который мы приняли из PC

 

 

Запросим память под наши массивы

 

 

Заберём строки из пакета

 

 

Запишем строки в NVS, освободим память, запрошенную под строки и переключим уровень ножки светодиода

 

 

Выйдем из всех наших условий (но не из цикла) и добавим задержку, иначе мы другим задачам с нашим огромным приоритетом вообще работать не дадим

 

 

Соберём код, прошьём контроллер, проверим в терминале наличие ключей, если у кого-то их нет, то прошейте проект прошлого урока

 

 

Запустим программ (ссылка внизу страницы) и настроим порт

 

 

Попробуем прочитать данные с помощью кнопки Read

 

 

Надеюсь, что многие поняли, почему не получилось. У меня был порт настроен заранее и данные настроек берутся из сохранённого конфига программы. А не получилось потому, что нужно остановить терминал, так как порт не может работать в несколько сессий. Если не остановить терминал, то порта даже не будет в выпадающем списке программы. После ошибки программа закроется. Остановим терминал, запустим программу и попробуем прочитать данные снова

Вот теперь всё получилось.

И теперь у нас кнопка чтения стала неактивной, а стала активной кнопка Write

Изменим данные строк и попробуем записать их в контроллер.

 

Нажмём кнопку Write и увидим запрос, так как вдруг мы нажали кнопку случайно

 

 

Увидим, что через некоторое время кнопка Write станет недоступной, а Read — доступной.

Можем сразу прочитать, но это неинтересно, так как ничего не изменится. Лучше закроем программу и прочитаем данные

 

 

Мы видим, что данные сохранились. Закроем программу, запустим терминал, контроллер перезагрузится и мы увидим наши данные также и в терминале.

 

 

Итак на данном уроке мы, используя шину UART, научились записывать и читать данные NVS, передавая их через UART на PC и обратно. Думаю, в дальнейшем нам это пригодится для изменения логина и пароля в целях подключения к точке доступа, а также других данных. Аналогичную программу вы можете и сами написать и не обязательно на чистом WinApi, как это делаю я.

Всем спасибо за внимание!

 

 

Предыдущий урок Программирование МК ESP32 Следующий урок

 

Исходный код

 

Программа для чтения и записи данных NVS

 

 

Недорогие отладочные платы ESP32 можно купить здесь:

На AliExpress Недорогие отладочные платы ESP32

На Яндекс.Маркет Недорогие отладочные платы ESP32

Логический анализатор 16 каналов можно приобрести (AliExpress) здесь

 

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

ESP32 Name

 

Смотреть ВИДЕОУРОК в Дзен (нажмите на картинку)

ESP32 Name

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*