Enhed 3 / 9

Indlejrede systemer og generering af mikrocontrollerkode

Gevinster:

  • Evne til at generere indlejret kode givet register og hardwarekontekst til Arduino/STM32/ESP32 med AI
  • Evne til at genkende og korrigere indlejrede mønstre såsom interrupts, timere og ikke-blokerende loops i AI-output
  • Evne til at gennemgå den genererede kode med hensyn til hukommelse, realtid og sikkerhed, før den uploades til hardwaren

I mekatronik er mikrocontrolleren, hvor ideer møder den fysiske verden. Kort som Arduino, STM32, ESP32; den læser sensorer, driver aktuatorer, kommunikerer og gør alt dette under begrænset hukommelse, begrænset processorkraft og strenge tidskrav. Kunstig intelligens er meget nyttig i dette felt: den kan udtrække registerindstillinger baseret på en sensors datablad, kode en kommunikationsprotokol, indstille en timer-afbrydelse. Men indlejrede systemer er et af de områder, hvor AI producerer de mest "overbevisende løgne"; fordi registeradresser, bitmasker og timingadfærd er specifikke for boardet, og en bitfejl forstyrrer hele adfærden. I denne enhed dækker vi, hvordan man får indlejret kode genereret med AI, og hvordan man gennemgår den, før den indlæses i hardware.

Forskellen mellem indlejret kode fra Pure Software

Et desktop-program har masser af hukommelse, operativsystem og nem fejlfinding. Indlejret kode mangler de fleste af disse:

Størrelse

skrivebord

indlejret system

hukommelse

GB niveau

KB-niveau (f.eks. 2 KB RAM)

timing

Generelt fleksibel

Stram, realtid

fejlretning

Nem (debugger, log)

Hård (JTAG, seriel, LED)

Fejl resultat

Programmet går ned

Aktuator/hardware kan være beskadiget

ressourceadgang

OS abstrakter

Direkte adgang til registret

Disse forskelle bestemmer dine kriterier for evaluering af AI-output: Hukommelsesbrug, realtid (ikke-blokerende) og hardwareregisterets nøjagtighed er altid øverst på din tjekliste.

Blokering vs ikke-blokerende kode

Den mest almindelige fejl begået af begyndere (og ofte lavet af AI) er brugen af delay(). delay(1000) låser processoren i 1 sekund; I denne periode kan ingen andre sensorer aflæses, ingen knapper kan styres. Dette er uacceptabelt inden for mekatronik. I stedet bruges et millis()-baseret ikke-blokerende mønster.

// BAD: blocker -- processor kan ikke udføre andet arbejde i 1 sekund void loop() { digitalWrite(LED, HIGH); forsinkelse(1000); // alt stopper digitalWrite(LED, LOW); forsinkelse(1000); // En nødsituationsknap kan ikke læses på nuværende tidspunkt!}// GOD: ikke-blokerende -- sløjfen er ikke blokeret, andre opgaver køres if (nowMs - previousMs >= interval) { previousMs = nowMs; ledStatus = !ledStatus; digitalWrite(LED, ledStatus); } knapCheck(); // kan køre i hver cyklus sensorRead(); //kan køre i enhver løkke}

Det ikke-blokerende mønster er grundlaget for indlejret mekatronik: kontrolsløjfen flyder kontinuerligt, ingen opgave udelukker en anden. At fortælle AI'en om at "brug ikke forsinkelse, skriv millis-baseret ikke-blokering", når du skriver kode, forbedrer kvaliteten af ​​outputtet direkte.

Tip: Se efter forsinkelse( i den indlejrede kode fra AI. Hvis du ser en forsinkelse i hovedkontrolsløjfen, er den kode oftest ikke egnet til et realtidssystem og bør omskrives.

Afbrydelser og timere

Vi fanger tidskritiske hændelser (encoder puls, knap, periodisk sampling) med interrupts i stedet for at vente i hovedsløjfen. Interrupt-rutinen (ISR) bør skrives kort og omhyggeligt: ingen forsinkelser, Serial.print eller lange beregninger i den; Delte variable er markeret som flygtige.

flygtig lang encoderTæller = 0; // ISR og loop er delt -> volatile condition void enkoderISR() { // Short ISR: tæl bare, gør intet andet arbejde, hvis (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() { long counter; noInterrupts(); //short interrupts for atomlæsningstæller = encoderCounter; afbryder(); //handle sikkert med tælleren...}

Tre kritiske punkter i dette eksempel er, hvor AI'en ofte går glip af: (1) den delte encoderCounter skal være 'flygtig', ellers vil compileroptimeringen gå glip af opdateringer; (2) ISR skal være kort; (3) Ved læsning af en multi-byte variabel i hovedsløjfen skal interrupts for atomlæsning lukkes i kort tid, ellers kan ISR gribe ind under læsning og halv/korrupt værdi kan aflæses (racetilstand). Sørg for at tjekke, om disse tre er til stede i AI-koden.

Registrer nøjagtighed og datablad

AI kan troværdigt misrepræsentere registeradressen på en sensor eller konfigurationsbitten på en MCU. For eksempel er strømstyringsregisteret for en MPU6050 IMU 0x6B; Hvis AI giver dette som 0x6A, er koden kompileret, det ser ud til at virke, men sensoren vågner ikke. Sådanne fejl opdages kun sammenlignet med dataarket.

// MPU6050 wake-up: ifølge datablad PWR_MGMT_1 = 0x6B, værdi 0x00#define MPU_ADDR 0x68#define PWR_MGMT_1 0x6B // <-- VERIFY from datasheetWire.beginTransmission(MPU_ADDR);Wire.write(PWR_MGMT_1);Wire.write(0x00); // vågne op fra dvaletilstandWire.endTransmission(true);

Bemærk: Bekræft hver registeradresse, bitmaske og I2C/SPI-adresse givet af AI fra dataarket. Disse værdier er kort- og chipspecifikke; Værdien AI "husker" kan være fra en anden chiprevision. Forkert register fører lydløst til forkert adfærd.

Svag prompt / stærk prompt

SVAG:"Læs temperatursensor på ESP32."(Hvilken sensor? Hvilken protokol? Hvilken pin? Generisk, sandsynligvis forkert kode.)STÆRK:"Læs en DS18B20 temperatursensor på ESP32 (Arduino framework) fra GPIO4 med OneWire. Skriv ikke-blokerende, sample hvert 1. sekund (ved hjælp af forsinkelse, millisfixet værdi i tilfælde af millisfix eller 52-flag). Læs venligst fejl (17). Angiv hvert bibliotek og hver pinforbindelse, du bruger, i den første kommentar Brug char buffer i stedet for String.

Kraftig prompt; Det giver chippen, rammen, sensoren, protokol, pin, samplingmønster, fejlstatus og hukommelsesbegrænsning. På denne måde er output både verificerbart og realistisk.

Gennemgå tjekliste for indlejret kode

Før du indlæser AI-outputtet, skal du sende det gennem denne liste:

  1. Blokering: Er der en forsinkelse eller lang blokering i hovedsløjfen?
  2. volatile: Er variabler delt med ISR flygtige?
  3. Atomadgang: Er multi-byte delt variabel sikker at læse?
  4. Registrer: Er adresserne og bitmaskerne kompatible med dataarket?
  5. Hukommelse: String, store arrays, skaber rekursion KB-niveauoverløb?
  6. Fejlhåndtering: Håndteres sensoraflæsningsfejl, kommunikationstimeouts?
  7. Sikker start: Er aktuatorudgangene placeret i sikker (passiv) tilstand ved opstart?

Mini etui

Embedded systems ingeniør Baran får AI til at skrive koden, der læser IMU for en drone. Koden kompilerer og ser ud til at virke, men vinkelværdierne er meningsløse. Baran anvender tjeklisten: sammenligner registeradresserne med dataarket og finder ud af, at AI'en udsender gyroskopkonfigurationsregisteret forkert (0x1A i stedet for 0x1B), så følsomhedsskalaen er forkert. Når de er rettet, falder værdierne. Derefter delay(10) meddelelser i hovedsløjfen; konvertere dette til en millis-baseret struktur, fordi blokering af flykontrolsløjfen er uacceptabel. Endelig ser den, at den delte tællervariabel ikke er flygtig og tilføjer den. AI gav skelettet hurtigt; Men gennemgangslisten fangede tre separate fejl: register, blokering og flygtig, og hardwaren var slet ikke i fare.

Almindelige fejl

  • Dræber realtidssvaret ved at bruge delay() i hovedkontrolsløjfen.
  • Undgå at gøre variablen, der deles med ISR, flygtig og at opleve tavse datakorruption.
  • Læsning af en multi-byte delt variabel ikke-atomisk og generering af en racetilstand.
  • Ikke verificering af register-/bitmaskerne givet af AI med dataarket.
  • Oprettelse af et hukommelsesoverløb ved at bruge strenge og store arrays i begrænset RAM.
  • Glemte først at sikre aktuatorudgange.

Sammenfattende

  • Indlejret kode; Den fungerer med begrænset hukommelse, stram timing og direkte registeradgang.
  • I hovedsløjfen bruges et millis-baseret ikke-blokerende mønster i stedet for forsinkelse.
  • ISR holdes kort; delte variabler skal være flygtige og atomare tilgængelige.
  • Registeradresser og bitmasker verificeres altid mod dataarket; AI kan være forkert.
  • Hukommelse, fejlhåndtering og sikker opstartsstatus kontrolleres altid.
  • Kraftig prompt; Det inkluderer chip, ramme, sensor, protokol, pin og begrænsninger.

Ansøgningsopgave

Vælg en sensor (f.eks. DS18B20, MPU6050 eller HC-SR04) og en mikrocontroller (Arduino/ESP32/STM32). Få AI til at generere en ikke-blokerende læsekode med den kraftfulde promptskabelon i denne enhed. Følg derefter de syv punkter i gennemgangstjeklisten én efter én: sammenlign mindst én register/pin-værdi med dataarket, kontroller for sløjfeforsinkelser, kontroller den flygtige status for delte variabler. Hvor mange elementer "bestod" ved første forsøg, og hvor mange krævede rettelser? Noter hvert problem, du finder, og dets løsning.