Прибуток:
- Можливість генерувати вбудований код із заданим реєстром і апаратним контекстом для Arduino/STM32/ESP32 за допомогою AI
- Можливість розпізнавати та виправляти вбудовані шаблони, такі як переривання, таймери та неблокуючі цикли у виводі AI
- Можливість перегляду згенерованого коду з точки зору пам’яті, реального часу та безпеки перед завантаженням його на апаратне забезпечення
У мехатроніці мікроконтролер є місцем, де ідеї зустрічаються з фізичним світом. Такі карти, як Arduino, STM32, ESP32; він зчитує датчики, керує виконавчими механізмами, спілкується та робить усе це в умовах обмеженої пам’яті, обмеженої потужності обробки та суворих вимог до часу. Штучний інтелект дуже корисний у цій сфері: він може витягувати налаштування реєстру на основі таблиці даних датчика, кодувати протокол зв’язку, установлювати переривання таймера. Але вбудовані системи є однією зі сфер, де штучний інтелект виробляє найбільш «переконливу неправду»; оскільки адреси регістрів, бітові маски та поведінка синхронізації є специфічними для плати, і одна помилка біта порушує всю поведінку. У цьому розділі ми розповідаємо про те, як створити вбудований код за допомогою штучного інтелекту та як перевірити його перед завантаженням в апаратне забезпечення.
Відмінність вбудованого коду від чистого програмного забезпечення
Програма для настільного ПК має багато пам’яті, операційну систему та легкість налагодження. У вбудованому коді відсутні більшість із них:
Розмір
робочий стіл
вбудована система
пам'ять
Рівень ГБ
Рівень КБ (наприклад, 2 КБ оперативної пам’яті)
терміни
Загалом гнучкий
Тісний, реальний час
налагодження
Легко (налагоджувач, журнал)
Жорсткий (JTAG, послідовний, світлодіодний)
Результат помилки
Програма вилітає
Привід/обладнання можуть бути пошкоджені
доступ до ресурсу
ОС конспектів
Прямий доступ до Реєстру
Ці відмінності визначають ваші критерії для оцінки результатів штучного інтелекту: використання пам’яті, режим реального часу (без блокування) і точність апаратних реєстрів завжди знаходяться у верхній частині вашого контрольного списку.
Блокуючий проти неблокуючого коду
Найпоширенішою помилкою початківців (і часто припускається ШІ) є використання delay(). delay(1000) блокує процесор на 1 секунду; Протягом цього періоду не можна зчитувати інші датчики, не можна керувати жодними кнопками. Це неприпустимо в мехатроніці. Замість цього використовується неблокуючий шаблон на основі millis().
// ПОГАНО: блокувальник -- процесор не може виконувати іншу роботу протягом 1 секунди void loop() { digitalWrite(LED, HIGH); затримка (1000); // все зупиняється digitalWrite(LED, LOW); затримка (1000); // Наразі неможливо прочитати екстрену кнопку!}// ДОБРЕ: не блокується -- цикл не заблоковано, інші завдання виконуються, якщо (nowMs - previousMs >= інтервал) { previousMs = nowMs; ledStatus = !ledStatus; digitalWrite(LED, ledStatus); } buttonCheck(); // може працювати в кожному циклі sensorRead(); //може працювати в будь-якому циклі}
Неблокуючий шаблон є основою вбудованої мехатроніки: контур керування протікає безперервно, жодне завдання не блокує інше. Вказівка штучному інтелекту «не використовувати затримку, писати без блокування на основі мілілі» під час безпосереднього написання коду покращує якість результату.
Порада. Шукайте затримку( у вбудованому коді штучного інтелекту. Якщо ви бачите затримку в основному контурі керування, найчастіше цей код не підходить для системи реального часу, і його слід переписати.
Переривання та таймери
Ми фіксуємо критичні за часом події (імпульс кодера, кнопка, періодична вибірка) за допомогою переривань замість очікування в основному циклі. Процедура переривання (ISR) повинна бути написана коротко і ретельно: без затримок, Serial.print або довгих обчислень у ній; Спільні змінні позначені як мінливі.
volatile long encoderCounter = 0; // ISR і цикл є спільними -> мінлива умова void enkoderISR() { // Короткий ISR: просто підраховуйте, нічого іншого не робіть if (digitalRead(ENC_B)) enkoderCounter++; else encoderCounter--;}void setup() { pinMode(ENC_A, INPUT_PULLUP); pinMode(ENC_B, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(ENC_A), enkoderISR, RISING);}void loop() { довгий лічильник; noInterrupts(); //короткі переривання для атомарного читання counter = encoderCounter; переривання(); // безпечно здійснювати транзакції за допомогою лічильника...}
У цьому прикладі ШІ часто пропускає три критичні моменти: (1) спільний лічильник кодувальників має бути «непостійним», інакше оптимізація компілятора пропускатиме оновлення; (2) ISR має бути коротким; (3) Під час читання багатобайтової змінної в основному циклі переривання для атомарного читання повинні бути закриті на короткий час, інакше ISR може втрутитися під час читання та може бути прочитано половинне/пошкоджене значення (стан змагання). Обов'язково перевірте, чи присутні ці три в коді AI.
Точність реєстрації та таблиця даних
ШІ може достовірно спотворити адресу реєстру датчика або біт конфігурації MCU. Наприклад, регістр керування живленням MPU6050 IMU становить 0x6B; Якщо AI видає це як 0x6A, код скомпільовано, він начебто працює, але датчик не прокидається. Такі помилки виявляються тільки при порівнянні з даташитом.
// Пробудження MPU6050: відповідно до таблиці даних PWR_MGMT_1 = 0x6B, значення 0x00#define MPU_ADDR 0x68#define PWR_MGMT_1 0x6B // <-- ПЕРЕВІРИТИ з таблиця данихWire.beginTransmission(MPU_ADDR);Wire.write(PWR_MGMT_1);Wire.write(0x00); // вихід із сплячого режимуWire.endTransmission(true);
Увага: перевірте кожну адресу регістра, бітову маску та адресу I2C/SPI, надані ШІ з таблиці даних. Ці значення залежать від карти та чіпа; Значення, яке "пам'ятає" AI, може бути з іншої версії чіпа. Неправильний реєстр мовчки призводить до неправильної поведінки.
Слабка підказка / Сильна підказка
СЛАБКО: «Зчитування датчика температури на ESP32». (Який датчик? Який протокол? Який контакт? Загальний, можливо, неправильний код.) СИЛЬНЕ: «Зчитування датчика температури DS18B20 на ESP32 (Arduino framework) з GPIO4 за допомогою OneWire. Запис без блокування, вибірка кожні 1 секунду (з використанням затримки, на основі мілісекунд). Встановіть позначку помилки у випадку помилки читання (фіксоване значення). -127 або 85). Будь ласка, вкажіть кожну бібліотеку та pin-з'єднання в першому коментарі, використовуйте char buffer замість String.
Потужна підказка; Він надає чіп, структуру, датчик, протокол, PIN-код, шаблон вибірки, статус помилки та обмеження пам’яті. Таким чином результат є перевіреним і реалістичним.
Перегляньте контрольний список для вбудованого коду
Перш ніж завантажувати вихід AI, пропустіть його через цей список:
- Блокування: чи є затримка або тривале блокування в основному циклі?
- volatile: чи є змінні, якими спільно користується ISR, мінливі?
- Атомарний доступ: чи безпечно читати багатобайтову спільну змінну?
- Реєстрація: чи сумісні адреси та бітові маски з таблицею даних?
- Пам'ять: Рядок, великі масиви, чи створює рекурсія переповнення рівня КБ?
- Обробка помилок: чи обробляються помилки зчитування датчика, час очікування зв’язку?
- Безпечний запуск: чи переведені виходи приводу в безпечний (пасивний) стан під час запуску?
Міні-чохол
Інженер із вбудованих систем Баран доручає штучному інтелекту написати код, який зчитує IMU для дрона. Код компілюється і, здається, працює, але значення кутів не мають сенсу. Баран застосовує контрольний список: порівнює адреси реєстрів з таблицею даних і виявляє, що AI неправильно виводить регістр конфігурації гіроскопа (0x1A замість 0x1B), тому шкала чутливості неправильна. Після виправлення значення встановлюються. Потім delay(10) помічає в основному циклі; перетворюючи це на структуру на основі мілісекунд, оскільки блокування контуру керування польотом є неприйнятним. Нарешті, він бачить, що змінна спільного лічильника не є мінливою, і додає її. ШІ дав скелет швидко; Але в списку перевірки були виявлені три окремі помилки: реєстрація, блокування та нестабільність, і апаратне забезпечення взагалі не було під загрозою.
Поширені помилки
- Знищення відповіді в реальному часі за допомогою delay() в основному циклі керування.
- Уникайте того, щоб змінна, яка надається спільно з ISR, стала нестабільною та не спотворювала дані.
- Читання багатобайтової спільної змінної неатомарно та генерування умови змагання.
- Не перевіряються регістри/бітові маски, надані ШІ з таблицею даних.
- Створення переповнення пам’яті за допомогою рядків і великих масивів в обмеженій пам’яті.
- Ви забули спочатку закріпити виходи приводу.
Підсумовуючи
- Вбудований код; Він працює з обмеженою пам’яттю, обмеженим часом і прямим доступом до реєстру.
- У основному циклі замість затримки використовується неблокуючий шаблон на основі мілісекунд.
- ISR залишається коротким; спільні змінні повинні мати непостійний і атомарний доступ.
- Адреси реєстрів і бітові маски завжди звіряються з даними; ШІ може помилятися.
- Пам'ять, обробка помилок і статус безпечного запуску завжди перевіряються.
- Потужна підказка; Він включає чіп, структуру, датчик, протокол, PIN-код і обмеження.
Аплікаційне завдання
Виберіть датчик (наприклад, DS18B20, MPU6050 або HC-SR04) і мікроконтролер (Arduino/ESP32/STM32). Нехай штучний інтелект згенерує неблокуючий код читання за допомогою потужного шаблону запиту в цьому пристрої. Потім дотримуйтеся семи пунктів контрольного списку перегляду один за одним: порівняйте принаймні одне значення регістра/виводу з таблицею даних, перевірте наявність затримок циклу, перевірте нестабільний статус спільних змінних. Скільки пунктів «здано» з першої спроби і скільки потребує виправлення? Занотуйте кожну знайдену проблему та її вирішення.