Печалби:
- Възможност за генериране на вграден код, даден регистър и хардуерен контекст за Arduino/STM32/ESP32 с AI
- Възможност за разпознаване и коригиране на вградени модели като прекъсвания, таймери и неблокиращи цикли в AI изхода
- Възможност за преглед на генерирания код по отношение на памет, реално време и сигурност, преди да го качите на хардуера
В мехатрониката микроконтролерът е мястото, където идеите се срещат с физическия свят. Карти като Arduino, STM32, ESP32; той чете сензори, задвижва задвижващи механизми, комуникира и прави всичко това при ограничена памет, ограничена процесорна мощност и строги изисквания за време. Изкуственият интелект е много полезен в тази област: той може да извлича настройките на регистъра въз основа на листа с данни на сензора, да кодира комуникационен протокол, да задава прекъсване на таймера. Но вградените системи са една от областите, в които AI произвежда най-много „убедителни лъжи“; тъй като адресите на регистъра, битовите маски и поведението на синхронизирането са специфични за платката и една битова грешка нарушава цялото поведение. В този раздел ние разглеждаме как да имате вграден код, генериран с AI и как да го прегледате, преди да го заредите в хардуера.
Разлика на вградения код от чистия софтуер
Програмата за настолен компютър има много памет, операционна система и лесно отстраняване на грешки. Във вградения код липсват повечето от тези:
Размер
работен плот
вградена система
памет
GB ниво
Ниво KB (напр. 2 KB RAM)
синхронизация
Като цяло гъвкав
Напрегнато, в реално време
отстраняване на грешки
Лесно (дебъгер, лог)
Твърд (JTAG, сериен, LED)
Резултат от грешка
Програмата се срива
Актуаторът/хардуерът може да е повреден
достъп до ресурси
Резюмета на OS
Директен достъп до регистъра
Тези разлики определят вашите критерии за оценка на AI изхода: използването на паметта, точността на регистрите в реално време (без блокиране) и хардуерните регистри винаги са в горната част на вашия контролен списък.
Блокиращ срещу неблокиращ код
Най-честата грешка, допускана от начинаещи (и често допускана от AI) е използването на 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(); //може да работи във всеки цикъл}
Неблокиращият модел е в основата на вградената мехатроника: управляващият контур протича непрекъснато, никоя задача не блокира друга. Казването на AI да „не използва забавяне, пиши на базата на милиси без блокиране“ при писане на код директно подобрява качеството на изхода.
Съвет: Потърсете delay( във вградения код от AI. Ако видите забавяне в главния контролен цикъл, най-често този код не е подходящ за система в реално време и трябва да бъде пренаписан.
Прекъсвания и таймери
Ние улавяме критични за времето събития (импулс на енкодер, бутон, периодично вземане на проби) с прекъсвания, вместо да чакаме в главния цикъл. Процедурата за прекъсване (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; прекъсва(); // извършвайте безопасна транзакция с брояча...}
Три критични точки в този пример са местата, където AI често пропуска: (1) споделеният encoderCounter трябва да е „нестабилен“ или оптимизацията на компилатора ще пропусне актуализации; (2) ISR трябва да е кратък; (3) При четене на многобайтова променлива в главния цикъл, прекъсванията за атомарно четене трябва да бъдат затворени за кратко време, в противен случай ISR може да се намеси по време на четене и може да се прочете половин/повредена стойност (състезание). Не забравяйте да проверите дали тези три присъстват в AI кода.
Регистрирайте точност и лист с данни
AI може достоверно да представи погрешно адреса на регистъра на сензор или конфигурационния бит на MCU. Например регистърът за управление на мощността на MPU6050 IMU е 0x6B; Ако AI даде това като 0x6A, кодът се компилира, изглежда работи, но сензорът не се събужда. Такива грешки се откриват само при сравнение с листа с данни.
// MPU6050 събуждане: според листа с данни PWR_MGMT_1 = 0x6B, стойност 0x00#define MPU_ADDR 0x68#define PWR_MGMT_1 0x6B // <-- ПРОВЕРКА от datasheetWire.beginTransmission(MPU_ADDR);Wire.write(PWR_MGMT_1);Wire.write(0x00); // събуждане от спящ режимWire.endTransmission(true);
Внимание: Проверете всеки адрес на регистъра, битова маска и I2C/SPI адрес, дадени от AI от листа с данни. Тези стойности са специфични за картата и чипа; Стойността, която AI "помни" може да е от друга ревизия на чип. Неправилният регистър тихо води до неправилно поведение.
Слаба подкана / Силна подкана
СЛАБ: „Прочетете температурен сензор на ESP32.“ (Кой сензор? Кой протокол? Кой щифт? Общ, вероятно грешен код.) СИЛЕН: „Прочетете температурен сензор DS18B20 на ESP32 (Arduino framework) от GPIO4 с OneWire. Пишете без блокиране, извадка на всяка 1 секунда (използвайки забавяне, базирано на милисекунди). Задайте флаг за грешка в случай на грешка при четене (фиксирана стойност -127 или 85). Моля, посочете всяка библиотека и пин връзка, която използвате в първия коментар, използвайте char буфер вместо String."
Мощна подсказка; Той дава чипа, рамката, сензора, протокола, щифта, шаблона за вземане на проби, състоянието на грешката и ограничението на паметта. По този начин резултатът е едновременно проверим и реалистичен.
Прегледайте контролния списък за вграден код
Преди да заредите AI изхода, прекарайте го през този списък:
- Блокиране: Има ли забавяне или дълго блокиране в главния цикъл?
- volatile: Променливите, споделени с ISR, летливи ли са?
- Атомен достъп: Безопасна ли е за четене многобайтова споделена променлива?
- Регистрирайте се: адресите и битовите маски съвместими ли са с листа с данни?
- Памет: Низ, големи масиви, рекурсията създава ли препълване на KB ниво?
- Обработване на грешки: Обработват ли се грешки при четене на сензора, прекъсване на комуникацията?
- Безопасен старт: Изходите на задвижващия механизъм поставени ли са в безопасно (пасивно) състояние при стартиране?
Мини калъф
Инженерът по вградени системи Баран кара AI да напише кода, който чете IMU за дрон. Кодът се компилира и изглежда работи, но стойностите на ъглите са безсмислени. Баран прилага контролния списък: сравнява адресите на регистъра с листа с данни и открива, че AI неправилно извежда регистъра за конфигурация на жироскопа (0x1A вместо 0x1B), така че скалата на чувствителността е грешна. Веднъж коригирани, стойностите се установяват. След това delay(10) забелязва в главния цикъл; преобразувайки това в милис-базирана структура, тъй като блокирането на веригата за управление на полета е неприемливо. Накрая вижда, че споделената променлива на брояча не е непостоянна и я добавя. AI даде скелета бързо; Но списъкът за преглед улови три отделни грешки: регистър, блокиране и летливи, а хардуерът изобщо не беше изложен на риск.
Често срещани грешки
- Убиване на отговора в реално време чрез използване на delay() в главния контролен цикъл.
- Избягвайте да правите променливата, споделена с ISR, непостоянна и да изпитвате безшумна повреда на данните.
- Четене на многобайтова споделена променлива неатомично и генериране на условие за състезание.
- Не се проверяват регистрите/битовите маски, дадени от AI с листа с данни.
- Създаване на препълване на паметта чрез използване на низове и големи масиви в ограничена RAM.
- Забравяне на първоначалното осигуряване на изходите на задвижването.
В обобщение
- Вграден код; Работи с ограничена памет, ограничено време и директен достъп до регистъра.
- В главния цикъл се използва базиран на милиси неблокиращ модел вместо забавяне.
- ISR се поддържа кратък; споделените променливи трябва да са непостоянни и с атомарен достъп.
- Адресите на регистъра и битовите маски винаги се проверяват спрямо листа с данни; AI може да греши.
- Винаги се проверяват паметта, обработката на грешки и състоянието на безопасно стартиране.
- Мощна подсказка; Той включва чип, рамка, сензор, протокол, щифт и ограничения.
Задача за приложение
Изберете сензор (напр. DS18B20, MPU6050 или HC-SR04) и микроконтролер (Arduino/ESP32/STM32). Накарайте AI да генерира неблокиращ код за четене с мощния шаблон за подкана в това устройство. След това следвайте седемте елемента от контролния списък за преглед един по един: сравнете поне една стойност на регистър/пин с листа с данни, проверете за забавяния на цикъла, проверете променливото състояние на споделените променливи. Колко елемента са "преминали" при първия опит и колко изискват корекция? Отбележете всеки открит проблем и неговото отстраняване.