Мы еще с избыточной мощностью не разобрались. Наушники смеются с понятия "избыточной вычислительной мощности" У них самих там на полтора гигагерца набегает и при этом они так себе давят шум, и визжат от сильных звуков.
Не смешите мои наушники. В них стоят чипы с 8! процессорами в каждом! А они даже в интернет не выходят. Если сложить их пиковые токи, то ампера 2-3 наберется. А работают неделями.
А так да, RA8P1 не хватает audio DSP и это максимум что можно найти на публичном рынке. Дальше только дороже. ESP32 тут и рядом не лежат.
Ну с кем вы тягаетесь! ChatGPT потратил на этот исходник 3 секунды! На загадки про козу и капусту он больше тратит времени. Эти нейронки просто профи в создании таких операционок. Я еще попросил уложиться как можно короче. И не привлекал Claude, чтобы не загрязнять свой текущий чат. Просто хотел посоветовать открыть глаза. Революция уже произошла. Исходники в текстовой нотации ничего больше не значат. Нейронкам без разницы - автоматами писать или под RTOS или под bare metal. Дело только вкуса. Сейчас осталась гибридная графическая нотация, которая что-то значит, поскольку ИИ еще ее не осиливает. Пример:
Но написать такую диаграмму в примением вашей "библиотеки" я бы даже не пытался.
Тут идеально вписывается RA8P1. Для локального ML это наверно самый сейчас эффективный чип по потреблению и скорости. И такой дивайс должен иметь уже камеру. Детекция лиц там есть в демке. Микрофонную решетку тоже поддерживает. Для низкопотребляющего WiFi - SiWx917M Для глобального подключения как опция - nRF9151
Ну если вы не отрицаете аутентичность показанного API, то виден единственный примитив передачи управления другому потоку - задержка. Т.е. здесь имеем самую примитивную реализацию кооперативной OS.
Вот ChatGPT 5 написал вам свою более мощную реализацию такой операционки уже портированную под ESP32 SDK:
Открывать осторожно. Реально большой и сложный код
/*
* CoopOS-ESP32 — минимальная кооперативная ОС в одном файле (MIT)
* Надстройка над сервисами ESP-IDF: esp_timer (тик), FreeRTOS (один таск-раннер),
* ESP_LOG и GPIO для демо. Задачи "корутинные": сами уступают управление.
*
* Как использовать (ESP-IDF):
* - Добавь этот файл в компонент/проект.
* - По желанию выставь #define COOP_TICK_HZ и LED_GPIO ниже.
* - В app_main() создай свои задачи через os_task_create(...).
* - Вызови coopos_start(...), чтобы запустить кооперативный рантайм.
*
* Важно: Все "задачи" CoopOS исполняются последовательно внутри ОДНОГО FreeRTOS-таска.
* Очереди/семафоры внизу — для внутреннего использования задач CoopOS (SPSC best-effort).
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
/* ======== Настройки по умолчанию ======== */
#ifndef COOP_MAX_TASKS
# define COOP_MAX_TASKS 16
#endif
#ifndef COOP_TICK_HZ
# define COOP_TICK_HZ 1000u /* 1 ms тик */
#endif
#ifndef LED_GPIO
# define LED_GPIO 2 /* Пины зависят от платы; часто 2 или 8/19. Поменяй при необходимости. */
#endif
/* ======== ESP-IDF / FreeRTOS ======== */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "driver/gpio.h"
/* ======== Внутренние утилиты/критические секции ======== */
static const char *TAG = "CoopOS";
#if CONFIG_FREERTOS_UNICORE
# define COOP_CORE tskNO_AFFINITY
#else
# define COOP_CORE tskNO_AFFINITY
#endif
static portMUX_TYPE g_mux = portMUX_INITIALIZER_UNLOCKED;
static inline void os_crit_enter(void){ taskENTER_CRITICAL(&g_mux); }
static inline void os_crit_exit (void){ taskEXIT_CRITICAL (&g_mux); }
/* ======== Типы CoopOS ======== */
typedef uint32_t os_tick_t;
struct os_task;
typedef int (*os_thread_t)(struct os_task *self, void *arg);
typedef enum {
OS_TASK_READY = 0,
OS_TASK_RUNNING,
OS_TASK_BLOCKED_DELAY,
OS_TASK_BLOCKED_WAIT,
OS_TASK_SUSPENDED,
OS_TASK_DEAD
} os_task_state_t;
/* TCB без отдельного стека: локальный "континуэйшен" как в корутинах */
typedef struct os_task {
const char *name;
os_thread_t entry;
void *arg;
uint8_t prio; /* 0 — самый высокий */
uint8_t id;
volatile uint8_t state; /* os_task_state_t */
uint32_t lc; /* local continuation для макросов OS_* */
os_tick_t wake_deadline;/* для задержек/таймаутов */
void *wait_obj;
} os_task_t;
/* Счётный семафор (минимальный) и мьютекс на его основе */
typedef struct { volatile int32_t count; } os_sem_t;
typedef os_sem_t os_mutex_t;
/* Неблокирующая очередь указателей (SPSC, best-effort) */
typedef struct {
void **buf;
uint16_t capacity;
volatile uint16_t head; /* producer */
volatile uint16_t tail; /* consumer */
} os_queue_t;
/* ======== API CoopOS ======== */
static inline os_tick_t os_ms_to_ticks(uint32_t ms){ return (os_tick_t)((ms * (uint32_t)COOP_TICK_HZ) / 1000u); }
void os_init(void);
void os_run(void); /* Бесконечный цикл рантайма CoopOS (внутри FreeRTOS-таска) */
os_task_t* os_task_create(const char *name, os_thread_t entry, void *arg, uint8_t prio);
void os_task_kill(os_task_t *t);
os_tick_t os_now(void);
void os_task_sleep_until(os_task_t *self, os_tick_t until_tick);
void os_task_sleep_ms(os_task_t *self, uint32_t ms);
static inline void os_sem_init(os_sem_t *s, int32_t initial){ s->count = initial; }
bool os_sem_try_take(os_sem_t *s);
void os_sem_give(os_sem_t *s);
static inline void os_mutex_init(os_mutex_t *m){ os_sem_init(m, 1); }
static inline bool os_mutex_try_lock(os_mutex_t *m){ return os_sem_try_take(m); }
static inline void os_mutex_unlock(os_mutex_t *m){ os_sem_give(m); }
void os_queue_init(os_queue_t *q, void **storage, uint16_t capacity);
bool os_queue_try_send(os_queue_t *q, void *item);
bool os_queue_try_recv(os_queue_t *q, void **out_item);
/* Макросы корутин */
#define OS_BEGIN(self) switch ((self)->lc) { case 0:
#define OS_YIELD(self) do { (self)->lc = __LINE__; (self)->state = OS_TASK_READY; return 0; case __LINE__:; } while (0)
#define OS_WAIT_UNTIL(self, cond) do { while (!(cond)) { OS_YIELD(self); } } while (0)
#define OS_DELAY(self, ms) do { os_task_sleep_ms((self), (ms)); OS_YIELD(self); } while (0)
#define OS_END(self) } (self)->state = OS_TASK_DEAD; return 1
/* ======== Тик и idle поверх ESP-IDF ======== */
static volatile os_tick_t g_ticks = 0;
static esp_timer_handle_t s_tick_timer = NULL;
static void coop_tick_cb(void *arg){
(void)arg;
os_crit_enter();
g_ticks++;
os_crit_exit();
}
static inline bool time_reached(os_tick_t now, os_tick_t deadline){
return (int32_t)(now - deadline) >= 0; /* корректно при переполнении 32-бит */
}
static void os_hw_tick_init(void){
if (s_tick_timer) return;
const esp_timer_create_args_t args = {
.callback = &coop_tick_cb,
.arg = NULL,
.dispatch_method = ESP_TIMER_TASK,
.name = "coop_tick"
};
if (esp_timer_create(&args, &s_tick_timer) == ESP_OK){
/* Период в микросекундах */
uint64_t us = 1000000ULL / (uint64_t)COOP_TICK_HZ;
esp_timer_start_periodic(s_tick_timer, us);
} else {
ESP_LOGE(TAG, "esp_timer_create failed");
}
}
static inline void os_hw_idle_hook(void){
/* Когда нет готовых задач CoopOS — уступаем FreeRTOS на 1 тик */
vTaskDelay(1);
}
void os_tick_isr(void){ /* оставлено для совместимости; не используется напрямую */
os_crit_enter();
g_ticks++;
os_crit_exit();
}
/* ======== Реализация ядра CoopOS ======== */
static os_task_t g_tasks[COOP_MAX_TASKS];
static uint8_t g_task_count = 0;
os_tick_t os_now(void){ return g_ticks; }
void os_task_sleep_until(os_task_t *self, os_tick_t until_tick){
self->wake_deadline = until_tick;
self->state = OS_TASK_BLOCKED_DELAY;
}
void os_task_sleep_ms(os_task_t *self, uint32_t ms){
os_task_sleep_until(self, os_now() + os_ms_to_ticks(ms));
}
static inline void task_init(os_task_t *t, const char *name, os_thread_t entry, void *arg, uint8_t prio, uint8_t id){
t->name = name;
t->entry = entry;
t->arg = arg;
t->prio = prio;
t->id = id;
t->state = OS_TASK_READY;
t->lc = 0;
t->wake_deadline = 0;
t->wait_obj = NULL;
}
void os_init(void){
g_ticks = 0;
g_task_count = 0;
os_hw_tick_init();
}
os_task_t* os_task_create(const char *name, os_thread_t entry, void *arg, uint8_t prio){
if (!entry) return NULL;
os_crit_enter();
if (g_task_count >= COOP_MAX_TASKS){
os_crit_exit();
return NULL;
}
uint8_t id = g_task_count;
task_init(&g_tasks[id], name, entry, arg, prio, id);
g_task_count++;
os_crit_exit();
return &g_tasks[id];
}
void os_task_kill(os_task_t *t){
if (!t) return;
os_crit_enter();
t->state = OS_TASK_DEAD;
os_crit_exit();
}
/* Семафоры */
bool os_sem_try_take(os_sem_t *s){
bool ok = false;
os_crit_enter();
if (s->count > 0){ s->count--; ok = true; }
os_crit_exit();
return ok;
}
void os_sem_give(os_sem_t *s){
os_crit_enter();
s->count++;
os_crit_exit();
}
/* Очередь указателей (SPSC) */
static inline uint16_t wrap_inc(uint16_t v, uint16_t cap){ return (uint16_t)((v + 1u) % cap); }
void os_queue_init(os_queue_t *q, void **storage, uint16_t capacity){
q->buf = storage;
q->capacity = capacity;
q->head = 0;
q->tail = 0;
}
bool os_queue_try_send(os_queue_t *q, void *item){
uint16_t h = q->head;
uint16_t n = wrap_inc(h, q->capacity);
if (n == q->tail) return false; /* полна */
q->buf[h] = item;
q->head = n;
return true;
}
bool os_queue_try_recv(os_queue_t *q, void **out_item){
uint16_t t = q->tail;
if (t == q->head) return false; /* пуста */
*out_item = q->buf[t];
q->tail = wrap_inc(t, q->capacity);
return true;
}
/* Планировщик CoopOS внутри одного FreeRTOS-таска */
static int run_task_once(os_task_t *t){
t->state = OS_TASK_RUNNING;
int finished = t->entry(t, t->arg);
if (t->state == OS_TASK_RUNNING){
t->state = OS_TASK_READY; /* если задача сама не поменяла состояние */
}
return finished;
}
void os_run(void){
for (;;){
os_tick_t now = os_now();
/* Разбудить задачи с истекшей задержкой */
for (uint8_t i = 0; i < g_task_count; ++i){
os_task_t *t = &g_tasks[i];
if (t->state == OS_TASK_BLOCKED_DELAY && time_reached(now, t->wake_deadline)){
t->state = OS_TASK_READY;
}
}
/* Выполнить готовые задачи по возрастанию prio */
int ran_any = 0;
for (uint16_t pr = 0; pr <= 255; ++pr){
for (uint8_t i = 0; i < g_task_count; ++i){
os_task_t *t = &g_tasks[i];
if (t->state == OS_TASK_READY && t->prio == pr){
int done = run_task_once(t);
ran_any = 1;
if (done){ t->state = OS_TASK_DEAD; }
}
}
}
/* Удалить DEAD (уплотнить массив) */
for (uint8_t i = 0; i < g_task_count; ){
if (g_tasks[i].state == OS_TASK_DEAD){
g_task_count--;
if (i != g_task_count){
g_tasks[i] = g_tasks[g_task_count];
g_tasks[i].id = i;
}
} else {
++i;
}
}
if (!ran_any){
os_hw_idle_hook(); /* никого нет — уступить FreeRTOS */
}
}
}
/* ======== Запуск CoopOS как FreeRTOS-таска ======== */
static void coop_runner_task(void *arg){
(void)arg;
ESP_LOGI(TAG, "CoopOS runner started (tick=%u Hz)", (unsigned)COOP_TICK_HZ);
os_run(); /* не возвращается */
vTaskDelete(NULL);
}
/* Создать таск-раннер CoopOS
* prio — приоритет FreeRTOS таска-раннера (рекомендуется > tskIDLE_PRIORITY)
* stack — размер стека раннера (т.к. задачи без собственного стека, хватит 2..4К)
* core — ядро, либо tskNO_AFFINITY
*/
static TaskHandle_t s_coop_task = NULL;
static inline void coopos_start(UBaseType_t prio, uint32_t stack, BaseType_t core){
if (s_coop_task) return;
xTaskCreatePinnedToCore(coop_runner_task, "coop_runner", stack, NULL, prio, &s_coop_task, core);
}
/* ======== ДЕМО: мигание и prod/cons ======== */
static inline void board_led_init(void){
gpio_reset_pin(LED_GPIO);
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
}
static inline void board_led_toggle(void){
static int s = 0;
s ^= 1;
gpio_set_level(LED_GPIO, s);
}
static inline void board_log(const char *s){ ESP_LOGI(TAG, "%s", s); }
/* Задача: мигает раз в 500 мс */
static int task_blink(os_task_t *self, void *arg){
(void)arg;
OS_BEGIN(self);
board_led_init();
for (;;){
board_led_toggle();
OS_DELAY(self, 500);
}
OS_END(self);
}
/* Очередь сообщений */
static void *q_storage[8];
static os_queue_t q;
/* Продюсер: пишет "tick" каждые 300 мс */
static int task_producer(os_task_t *self, void *arg){
(void)arg;
OS_BEGIN(self);
for (;;){
const char *msg = "tick";
OS_WAIT_UNTIL(self, os_queue_try_send(&q, (void*)msg));
OS_DELAY(self, 300);
}
OS_END(self);
}
/* Консюмер: читает из очереди и логирует */
static int task_consumer(os_task_t *self, void *arg){
(void)arg;
OS_BEGIN(self);
for (;;){
void *msg = NULL;
OS_WAIT_UNTIL(self, os_queue_try_recv(&q, &msg));
board_log((const char*)msg);
OS_DELAY(self, 50);
}
OS_END(self);
}
/* ======== Точка входа ESP-IDF ======== */
void app_main(void){
os_init();
os_queue_init(&q, q_storage, (uint16_t)(sizeof(q_storage)/sizeof(q_storage[0])));
/* Создаём три кооперативные задачи (prio: 0 — самый высокий) */
os_task_create("producer", task_producer, NULL, 0);
os_task_create("blink", task_blink, NULL, 1);
os_task_create("consumer", task_consumer, NULL, 2);
/* Запускаем рантайм CoopOS в отдельном FreeRTOS-таске */
coopos_start(/*prio*/ tskIDLE_PRIORITY+2, /*stack*/ 4096, /*core*/ COOP_CORE);
}
Кроме датчиков уровня жидкости он содержит датчики температуры, влажности, освещенности, реле и т. д. и т. п. Все процессы реализованы как автоматы, которые работают в жестком реальном времени (дискретность такта 10 мсек). Проект поддерживает подключение по WiFi, MQTT, Home Assistant и имеет свою страничку управления. При этом нет нужды во FreeRTOS фактически от слова совсем.
Весть стек ESP32 построен на FreeRTOS. У ESP32 нет Non-OS SDK Пэтому утверждение выше вводит в заблуждение.
Да, однозначно модели улучшаются. GPT5 почти приблизился к Claude Sonnet. Сам Claude Sonnet еще недавно после редактирования больших сорсов на десятки тысяч строк на C++ гарантировано ошибался и переставлял кое-где строки невпопад. Спустя некоторое время он перестал так ошибаться. Теперь спокойно генерит 1000-2000 строк без единой ошибки. Или рефакторит 10000 строк без проблем. HTML или Python тоже генерит без ошибок. Если раньше приходилось вглядываться в каждую функцию чтобы не пропустить галюцинации, то теперь проще попросить пару раз исправить чем самому искать ошибки.
И вообще, использовать ИИ лучше в режиме агента, когда он сам генерит, сам компилит и сам исправляет. Тут даже смысла деградации не остается. Поскольку как бы они не деградировали они все равно будут вынуждены сделать правильно. Поскольку берут не за трафик, а за запрос, то смысла тому же Clade деградировать нету.
Но это в среднем. А в течении дня да, наблюдаются провалы, как будто ИИ подменили. Раньше казалось что это к вечеру происходит. Но теперь кажется что это происходит от каких-то хайповых ивентов в мире.
Про DMA неясно написано. Там буфер не кольцевой, а скорее переключаемый. DMA при отсутствии полных данных просто замрет и не выдаст прерывания. Чтобы забрать данные без прерывания придется организовать программный полинг. Автора спасает только то, что модули GPS выдают данные безостановочно. Но будут задержки в десятки миллисекунд на приеме. Для быстрых движущихся средств это уже будет проблемой. Метод приема в статье недоработан. Так лучше не делать.
Все эти сорсы тоже не несут смысла. Claude Sonnet отлично разбирается в NMEA, и за секунды напишет полный парсер, гораздо полнее чем в этой статье и еще добавит инерциальную навигацию сверху.
Ну чуть чуть приблизился к Claude Sonnet 4, не более. Все перечисленное в отношении программирования Claude Sonnet делал еще два месяца назад. Сегодня ChatGPT 5 появился в виде агента в VS Code GitHub Copilot. Ну так же фэйлит как и ChatGPT 4.1 Дольше думает чем Claude Sonnet 4 , меньше размышляет. Как всегда очень медленно рефрешит сорсы. Что-то не захотелось дальше пользоваться.
Статья самодостаточная. Написана автором для себя, чтобы не забыть как все настраивается. Автору спасибо за сам факт упоминания о OpenVela. Дальше дело техники узнать у ChatGPT что это за чудо .
Но чуда не случилось. OpenVela сидит на NuttX. А это такое старье, что на нем до сих пор Z80 поддерживается. Все беспроводные стеки - это просто ссылки на сторонние опенсорнсные стеки. Они в репозитарии так и сидят как ссылки. Т.е. ничего своего! Bluetooth взят просто из Zephyr OS. Все драйвера кроме там мелочи вроде gpio, uart и spi надо как-то прикручивать из вендорских SDK, которые ничего не знают ни о каких OS.
Самое смешное, что пртокола Xiaomi HyperConnect в репозитарии тоже нет. А это уже как бы совсем некрасиво...
Как хотите так и выставляете. Я начинал тестирование с 1 . Как хотите так и выставляете. Единицы однократной записи просто надо учитывать когда работает с Flash и выставляете соответственно макрос. Аналогичный макрос есть во всех файловых для Flash. И в STFs тоже есть.
Простоя я смотрю на надежность как на исследование. Традиционно параметр "надежность" подразумевает заданные условия. Традиционный производитель если увидит отклонение условий, то просто откажется от поддержки. У нас подход другой, мы не ставим жесткие условия, мы их исследуем и адаптируемся. Использование ПЛК в этом плане ограничивает гибкость. Поэтому я избегаю ПЛК. При этом наши решения для автоматических дверей раза в два дешевле импортных. Просто вы почему-то проецируете сложность фирмваре на цену устройств. Какой бы навороченный стек с RTOS, USB, CAN, Wi-Fi, Bluetooth или LoRa я бы не применил, он все равно в железе сложнее микрочипа и микро антенки на плате не станет. Дивайс не становится дороже даже на пару евро. Но вот когда любители старых добрых реле или ПЛК начинают делать, они сразу влетают в стоимость проводов, клемников, монтажа, боксов и проч. и лишаются элементов исследования. Вот там ад люди себе устраивают. Ардуинщики кстати тоже, поскольку залетают на избыточной модульности.
На то есть отраслевые стандарты. На те же лифты для инвалидов есть стандарт, который регламентриует все до мелочей. Какая шахта, какие размеры платформы, какие ручки, какие кнопки, сколько и каких тормозов и т.д. И имеет кучу ссылок на стандарты более мелкие. Там стандарты по электробезопасности, по цепям безопасности, по пожаробезопасности, по электромагнитной совместимости... туча их. Их так много, что какой-то ремонтник с улицы ни за что не будет это раскапывать, это и профессионалы не всё читают. Поэтому в двух словах никто и не пытается рассказать. Легче нанять аудитора из специального института. Он придет и все покажет. Либо тупо копировать уже кем-то сертифицированные решения.
Да, продавцы говорят то же самое. Но я думаю о своем будущем. Поэтому хочу сделать двери понятливыми и приветливыми. Чтобы понимали слова и отвечали, чтобы не прищемляли и не стучали. Чтобы стабильно стояли и не гудели и не скрипели. Чтобы не пускали и предупреждали о чужих. И без этих топорных планшетов с андроидами или линусками, и без этих ардуин. Сделали же из телефонов видеокамеры. Так вот из дверей можно сделать что-то типа привратников.
Что-то совершенно непонятное. Почему так много этапов? Кто их придумал? Сколько реально человек делало и что? Есть ли смысл в таких статьях без метрик?
Если все это чтобы добиться максимального качества, то "у семи нянек дитя без глазу" - так это выглядит на интуитивном уровне.
Эт зря вы так утверждаете. Я был как то в Германии, где стоят кварталы домов исключительно для престарелых, пятиэтажные. Обычно в таких домах лифтов не делают. Но в этих сделаны во всех подъездах. И именно безкабинные, как для инвалидов. Так там шуруют на них каждые пять минут. Аж двери не выдерживают. Двери не раздвижные как кабинных лифтах, а всегда распашные автоматические. Так там по два процессора в двери я ставлю, по процессору на створку. И еще ИИ планирую. Надежность систем управления - это постоянный головняк. Там 90% софта нужно только лишь для диагностики и сервисной поддержки.
В Минске в торговом центре такой лифт смотрел поставленный для людей с детьми в колясках. Так там нагрузка вообще нереальная. Частотники не выдерживают. Ресурс у частотников некоторых 2000 часов. Это китайских касается. Через год нужна смена частотника. Ну и конечно он потом стоит и не работает. И никто им "не пользуется"
Мы еще с избыточной мощностью не разобрались.
Наушники смеются с понятия "избыточной вычислительной мощности"
У них самих там на полтора гигагерца набегает и при этом они так себе давят шум, и визжат от сильных звуков.
Не смешите мои наушники.
В них стоят чипы с 8! процессорами в каждом! А они даже в интернет не выходят.
Если сложить их пиковые токи, то ампера 2-3 наберется.
А работают неделями.
А так да, RA8P1 не хватает audio DSP и это максимум что можно найти на публичном рынке. Дальше только дороже.
ESP32 тут и рядом не лежат.
Ну эт все равно что предложить делать телегу вместо машины, потому что колеса дешевле.
Ну с кем вы тягаетесь!
ChatGPT потратил на этот исходник 3 секунды!
На загадки про козу и капусту он больше тратит времени.
Эти нейронки просто профи в создании таких операционок.
Я еще попросил уложиться как можно короче. И не привлекал Claude, чтобы не загрязнять свой текущий чат.
Просто хотел посоветовать открыть глаза. Революция уже произошла. Исходники в текстовой нотации ничего больше не значат. Нейронкам без разницы - автоматами писать или под RTOS или под bare metal. Дело только вкуса.
Сейчас осталась гибридная графическая нотация, которая что-то значит, поскольку ИИ еще ее не осиливает.
Пример:
Но написать такую диаграмму в примением вашей "библиотеки" я бы даже не пытался.
Тут идеально вписывается RA8P1. Для локального ML это наверно самый сейчас эффективный чип по потреблению и скорости.
И такой дивайс должен иметь уже камеру. Детекция лиц там есть в демке.
Микрофонную решетку тоже поддерживает.
Для низкопотребляющего WiFi - SiWx917M
Для глобального подключения как опция - nRF9151
Ну если вы не отрицаете аутентичность показанного API, то виден единственный примитив передачи управления другому потоку - задержка.
Т.е. здесь имеем самую примитивную реализацию кооперативной OS.
Вот ChatGPT 5 написал вам свою более мощную реализацию такой операционки уже портированную под ESP32 SDK:
Открывать осторожно. Реально большой и сложный код
Claude Sonnet идентифицировал ваш проект как операционку с кооперативной многозадачностью. Вот её API:
Проверьте
Такие в своё время под 8-и битники писали все кому не лень.
Что заставило взяться за старое?
Вот эта цитата вызывает сомнения
Весть стек ESP32 построен на FreeRTOS. У ESP32 нет Non-OS SDK
Пэтому утверждение выше вводит в заблуждение.
Да, однозначно модели улучшаются. GPT5 почти приблизился к Claude Sonnet.
Сам Claude Sonnet еще недавно после редактирования больших сорсов на десятки тысяч строк на C++ гарантировано ошибался и переставлял кое-где строки невпопад.
Спустя некоторое время он перестал так ошибаться. Теперь спокойно генерит 1000-2000 строк без единой ошибки. Или рефакторит 10000 строк без проблем.
HTML или Python тоже генерит без ошибок.
Если раньше приходилось вглядываться в каждую функцию чтобы не пропустить галюцинации, то теперь проще попросить пару раз исправить чем самому искать ошибки.
И вообще, использовать ИИ лучше в режиме агента, когда он сам генерит, сам компилит и сам исправляет.
Тут даже смысла деградации не остается. Поскольку как бы они не деградировали они все равно будут вынуждены сделать правильно. Поскольку берут не за трафик, а за запрос, то смысла тому же Clade деградировать нету.
Но это в среднем.
А в течении дня да, наблюдаются провалы, как будто ИИ подменили.
Раньше казалось что это к вечеру происходит. Но теперь кажется что это происходит от каких-то хайповых ивентов в мире.
Откуда такая увереность в точности измерений?
Или это будет усреднение на больших интервалах в сотни миллисекунд?
Про DMA неясно написано.
Там буфер не кольцевой, а скорее переключаемый.
DMA при отсутствии полных данных просто замрет и не выдаст прерывания.
Чтобы забрать данные без прерывания придется организовать программный полинг.
Автора спасает только то, что модули GPS выдают данные безостановочно.
Но будут задержки в десятки миллисекунд на приеме.
Для быстрых движущихся средств это уже будет проблемой.
Метод приема в статье недоработан. Так лучше не делать.
Все эти сорсы тоже не несут смысла.
Claude Sonnet отлично разбирается в NMEA, и за секунды напишет полный парсер, гораздо полнее чем в этой статье и еще добавит инерциальную навигацию сверху.
Ну чуть чуть приблизился к Claude Sonnet 4, не более.
Все перечисленное в отношении программирования Claude Sonnet делал еще два месяца назад.
Сегодня ChatGPT 5 появился в виде агента в VS Code GitHub Copilot.
Ну так же фэйлит как и ChatGPT 4.1
Дольше думает чем Claude Sonnet 4 , меньше размышляет. Как всегда очень медленно рефрешит сорсы.
Что-то не захотелось дальше пользоваться.
Статья самодостаточная. Написана автором для себя, чтобы не забыть как все настраивается.
Автору спасибо за сам факт упоминания о OpenVela.
Дальше дело техники узнать у ChatGPT что это за чудо .
Но чуда не случилось. OpenVela сидит на NuttX. А это такое старье, что на нем до сих пор Z80 поддерживается.
Все беспроводные стеки - это просто ссылки на сторонние опенсорнсные стеки. Они в репозитарии так и сидят как ссылки. Т.е. ничего своего! Bluetooth взят просто из Zephyr OS.
Все драйвера кроме там мелочи вроде gpio, uart и spi надо как-то прикручивать из вендорских SDK, которые ничего не знают ни о каких OS.
Самое смешное, что пртокола Xiaomi HyperConnect в репозитарии тоже нет. А это уже как бы совсем некрасиво...
Посмотрите на этот макрос
#define LITTLEFS_PROG_SIZE 64 // Minimum program size (optimized for OSPI flash)
Как хотите так и выставляете. Я начинал тестирование с 1 . Как хотите так и выставляете.
Единицы однократной записи просто надо учитывать когда работает с Flash и выставляете соответственно макрос. Аналогичный макрос есть во всех файловых для Flash. И в STFs тоже есть.
Все есть на схеме. Проект открыт.
Простоя я смотрю на надежность как на исследование. Традиционно параметр "надежность" подразумевает заданные условия.
Традиционный производитель если увидит отклонение условий, то просто откажется от поддержки. У нас подход другой, мы не ставим жесткие условия, мы их исследуем и адаптируемся. Использование ПЛК в этом плане ограничивает гибкость. Поэтому я избегаю ПЛК.
При этом наши решения для автоматических дверей раза в два дешевле импортных.
Просто вы почему-то проецируете сложность фирмваре на цену устройств. Какой бы навороченный стек с RTOS, USB, CAN, Wi-Fi, Bluetooth или LoRa я бы не применил, он все равно в железе сложнее микрочипа и микро антенки на плате не станет. Дивайс не становится дороже даже на пару евро.
Но вот когда любители старых добрых реле или ПЛК начинают делать, они сразу влетают в стоимость проводов, клемников, монтажа, боксов и проч. и лишаются элементов исследования. Вот там ад люди себе устраивают. Ардуинщики кстати тоже, поскольку залетают на избыточной модульности.
На то есть отраслевые стандарты.
На те же лифты для инвалидов есть стандарт, который регламентриует все до мелочей. Какая шахта, какие размеры платформы, какие ручки, какие кнопки, сколько и каких тормозов и т.д. И имеет кучу ссылок на стандарты более мелкие. Там стандарты по электробезопасности, по цепям безопасности, по пожаробезопасности, по электромагнитной совместимости... туча их.
Их так много, что какой-то ремонтник с улицы ни за что не будет это раскапывать, это и профессионалы не всё читают. Поэтому в двух словах никто и не пытается рассказать.
Легче нанять аудитора из специального института. Он придет и все покажет.
Либо тупо копировать уже кем-то сертифицированные решения.
Да, продавцы говорят то же самое.
Но я думаю о своем будущем. Поэтому хочу сделать двери понятливыми и приветливыми. Чтобы понимали слова и отвечали, чтобы не прищемляли и не стучали. Чтобы стабильно стояли и не гудели и не скрипели. Чтобы не пускали и предупреждали о чужих. И без этих топорных планшетов с андроидами или линусками, и без этих ардуин.
Сделали же из телефонов видеокамеры. Так вот из дверей можно сделать что-то типа привратников.
Что-то совершенно непонятное.
Почему так много этапов? Кто их придумал?
Сколько реально человек делало и что?
Есть ли смысл в таких статьях без метрик?
Если все это чтобы добиться максимального качества, то "у семи нянек дитя без глазу" - так это выглядит на интуитивном уровне.
Эт зря вы так утверждаете.
Я был как то в Германии, где стоят кварталы домов исключительно для престарелых, пятиэтажные. Обычно в таких домах лифтов не делают.
Но в этих сделаны во всех подъездах. И именно безкабинные, как для инвалидов. Так там шуруют на них каждые пять минут. Аж двери не выдерживают. Двери не раздвижные как кабинных лифтах, а всегда распашные автоматические.
Так там по два процессора в двери я ставлю, по процессору на створку. И еще ИИ планирую. Надежность систем управления - это постоянный головняк. Там 90% софта нужно только лишь для диагностики и сервисной поддержки.
В Минске в торговом центре такой лифт смотрел поставленный для людей с детьми в колясках. Так там нагрузка вообще нереальная. Частотники не выдерживают. Ресурс у частотников некоторых 2000 часов. Это китайских касается. Через год нужна смена частотника. Ну и конечно он потом стоит и не работает. И никто им "не пользуется"