Единица 3 / 9

Встроенные системы и генерация кода микроконтроллера

Прибыль:

  • Возможность генерировать встроенный код с учетом регистра и аппаратного контекста для Arduino/STM32/ESP32 с искусственным интеллектом.
  • Способность распознавать и исправлять встроенные шаблоны, такие как прерывания, таймеры и неблокирующие циклы, в выходных данных AI.
  • Возможность проверки сгенерированного кода с точки зрения памяти, режима реального времени и безопасности перед загрузкой его на оборудование.

В мехатронике микроконтроллер — это место, где идеи встречаются с физическим миром. Карты, такие как Arduino, STM32, ESP32; он считывает данные датчиков, управляет исполнительными механизмами, осуществляет связь и делает все это в условиях ограниченной памяти, ограниченной вычислительной мощности и строгих требований по времени. Искусственный интеллект очень полезен в этой области: он может извлекать настройки регистров на основе таблицы данных датчика, кодировать протокол связи, устанавливать прерывание по таймеру. Но встроенные системы — одна из областей, где ИИ производит наиболее «убедительную ложь»; поскольку адреса регистров, битовые маски и поведение синхронизации специфичны для платы, и одна битовая ошибка нарушает все поведение. В этом модуле мы расскажем, как сгенерировать встроенный код с помощью ИИ и как просмотреть его перед загрузкой в ​​оборудование.

Отличие встроенного кода от чистого программного обеспечения

Настольная программа имеет много памяти, операционную систему и простоту отладки. Во встроенном коде отсутствует большинство из них:

Размер

рабочий стол

встроенная система

память

уровень ГБ

Уровень КБ (например, 2 КБ ОЗУ)

время

В целом гибкий

Плотно, в реальном времени

отладка

Легко (отладчик, журнал)

Жесткий (JTAG, последовательный, светодиодный)

Результат ошибки

Программа выходит из строя

Привод/оборудование может быть повреждено.

доступ к ресурсам

Тезисы ОС

Прямой доступ к реестру

Эти различия определяют ваши критерии оценки выходных данных ИИ: использование памяти, точность работы в режиме реального времени (неблокируемая) и аппаратные регистры всегда находятся в верхней части вашего контрольного списка.

Блокирующий и неблокирующий код

Самая распространенная ошибка, которую допускают новички (и часто допускают ИИ), — это использование задержки(). задержка(1000) блокирует процессор на 1 секунду; В этот период невозможно считывать показания других датчиков, управлять никакими кнопками. Это недопустимо в мехатронике. Вместо этого используется неблокирующий шаблон на основе millis().

// ПЛОХО: блокировщик — процессор не может выполнять какую-либо другую работу в течение 1 секунды void Loop() { digitalWrite(LED, HIGH); задержка(1000); // все останавливается digitalWrite(LED, LOW); задержка(1000); // В данный момент экстренная кнопка не может быть прочитана!}// ХОРОШО: неблокируется — цикл не блокируется, другие задачи выполняются if (nowMs - previousMs >= интервал) { previousMs = nowMs; светодиодный статус = !ledStatus; digitalWrite(LED,ledStatus); } КнопкаПроверка(); // может выполняться в каждом цикле SensorRead(); //может работать в любом цикле}

Неблокирующая схема лежит в основе встроенной мехатроники: контур управления протекает непрерывно, ни одна задача не блокирует другую. Указание ИИ «не использовать задержку, писать неблокируемую информацию на основе миллис» при написании кода напрямую улучшает качество вывода.

Совет: Ищите задержку( во встроенном коде ИИ. Если вы видите задержку в основном контуре управления, чаще всего этот код не подходит для системы реального времени и его следует переписать.

Прерывания и таймеры

Мы фиксируем критичные ко времени события (импульс энкодера, кнопка, периодическая выборка) с помощью прерываний вместо ожидания в основном цикле. Подпрограмму прерывания (ISR) следует писать коротко и аккуратно: никаких задержек, Serial.print или длинных вычислений в ней; Общие переменные помечены как изменчивые.

энергозависимый длинный encoderCounter = 0; // ISR и цикл являются общими -> изменчивое условие void энкодерИСР() { // Короткий ISR: просто считайте, никакой другой работы if (digitalRead(ENC_B)) энкодерCounter++; еще encoderCounter--;}void setup() { pinMode(ENC_A, INPUT_PULLUP); pinMode (ENC_B, INPUT_PULLUP); AttachInterrupt (digitalPinToInterrupt (ENC_A), энкодерISR, RISING);} void Loop () { длинный счетчик; нетПрерывания(); //короткие прерывания для атомарного чтения counter = encoderCounter; прерывания(); //безопасно провести транзакцию со счетчиком...}

В этом примере есть три критических момента, в которых ИИ часто пропускает: (1) общий encoderCounter должен быть «изменчивым», иначе оптимизация компилятора будет пропускать обновления; (2) ISR должен быть коротким; (3) При чтении многобайтовой переменной в основном цикле прерывания для атомарного чтения должны быть закрыты на короткое время, иначе ISR может вмешаться во время чтения и может быть прочитано половинное/поврежденное значение (состояние гонки). Обязательно проверьте, присутствуют ли эти три в коде AI.

Точность регистрации и таблица данных

ИИ может достоверно искажать адрес регистра датчика или бит конфигурации микроконтроллера. Например, регистр управления питанием IMU MPU6050 — 0x6B; Если ИИ выдает это как 0x6A, код компилируется, вроде работает, но сенсор не просыпается. Такие ошибки выявляются только при сравнении с даташитом.

// Пробуждение MPU6050: согласно таблице данных PWR_MGMT_1 = 0x6B, значение 0x00#define MPU_ADDR 0x68#define PWR_MGMT_1 0x6B // <-- VERIFY из таблицыWire.beginTransmission(MPU_ADDR);Wire.write(PWR_MGMT_1);Wire.write(0x00); // выход из режима сна modeWire.endTransmission(true);

Внимание: проверьте каждый адрес регистра, битовую маску и адрес I2C/SPI, предоставленные AI из таблицы данных. Эти значения зависят от карты и чипа; Значение, которое «запоминает» ИИ, может быть из другой ревизии чипа. Неправильный регистр незаметно приводит к некорректному поведению.

Слабая подсказка/Сильная подсказка

СЛАБЫЙ: «Чтение датчика температуры на ESP32». (Какой датчик? Какой протокол? Какой контакт? Общий, возможно, неправильный код.) СИЛЬНЫЙ: «Читать датчик температуры DS18B20 на ESP32 (платформа Arduino) из GPIO4 с помощью OneWire. Запись неблокируемая, выборка каждые 1 секунду (с использованием задержки, в миллисекундах). Установите флаг ошибки в случае ошибки чтения (фиксированное значение -127 или 85). Укажите каждую библиотеку. и контактное соединение, которое вы используете в первом комментарии. Из соображений памяти используйте буфер символов вместо строки».

Мощная подсказка; Он дает данные о чипе, структуре, датчике, протоколе, выводе, шаблоне выборки, статусе ошибки и ограничении памяти. Таким образом, результат будет проверяемым и реалистичным.

Контрольный список проверки встроенного кода

Перед загрузкой вывода AI пропустите его через этот список:

  1. Блокировка: есть ли задержка или длительная блокировка в основном цикле?
  2. изменчивость: являются ли переменные, используемые совместно с ISR, изменчивыми?
  3. Атомарный доступ: безопасно ли читать многобайтовую общую переменную?
  4. Зарегистрируйтесь: совместимы ли адреса и битовые маски с таблицей данных?
  5. Память: строка, большие массивы, создает ли рекурсия переполнение уровня КБ?
  6. Обработка ошибок: обрабатываются ли ошибки чтения датчиков, тайм-ауты связи?
  7. Безопасный пуск: переведены ли выходы привода в безопасное (пассивное) состояние при запуске?

Мини-кейс

Инженер по встраиваемым системам Бэран поручил ИИ написать код, который считывает IMU дрона. Код компилируется и работает, но значения углов не имеют смысла. Бэран применяет чек-лист: сравнивает адреса регистров с даташитом и обнаруживает, что AI неправильно выводит регистр конфигурации гироскопа (0x1A вместо 0x1B), поэтому шкала чувствительности неправильная. После исправления значения стабилизируются. Затем задержка(10) замечает в основном цикле; преобразование этого в структуру на основе миллис, поскольку блокировка контура управления полетом недопустима. Наконец, он видит, что общая переменная счетчика не является изменчивой, и добавляет ее. ИИ дал скелет быстро; Но в списке проверки были обнаружены три отдельные ошибки: регистрация, блокировка и энергозависимость, а оборудование вообще не подвергалось риску.

Распространенные ошибки

  • Уничтожение ответа в реальном времени с помощью задержки() в основном цикле управления.
  • Избегайте создания нестабильной переменной, используемой совместно с ISR, и не допускайте скрытого повреждения данных.
  • Чтение многобайтовой общей переменной неатомарно и создание состояния гонки.
  • Не сверка регистровых/битовых масок, заданных AI, с таблицей данных.
  • Создание переполнения памяти с помощью строк и больших массивов в ограниченной оперативной памяти.
  • Забыли изначально закрепить выходы привода.

В заключение

  • Встроенный код; Он работает с ограниченной памятью, жестким таймингом и прямым доступом к регистру.
  • В основном цикле вместо задержки используется неблокирующий шаблон в миллисах.
  • ISR остается коротким; общие переменные должны быть изменчивыми и иметь атомарный доступ.
  • Адреса регистров и битовые маски всегда сверяются с таблицей данных; ИИ может ошибаться.
  • Всегда проверяются память, обработка ошибок и состояние безопасного запуска.
  • Мощная подсказка; Он включает в себя чип, структуру, датчик, протокол, вывод и ограничения.

Задача приложения

Выберите датчик (например, DS18B20, MPU6050 или HC-SR04) и микроконтроллер (Arduino/ESP32/STM32). Попросите ИИ сгенерировать неблокирующий код чтения с помощью мощного шаблона подсказки в этом модуле. Затем последовательно выполните семь пунктов контрольного списка проверки: сравните хотя бы одно значение регистра/вывода с таблицей данных, проверьте наличие задержек в контуре, проверьте изменчивый статус общих переменных. Сколько заданий «сдалось» с первого раза и сколько потребовало исправления? Записывайте каждую обнаруженную проблему и способы ее устранения.