Enhet 3 / 9

Innebygde systemer og generering av mikrokontrollerkode

Gevinster:

  • Evne til å generere innebygd kode gitt register og maskinvarekontekst for Arduino/STM32/ESP32 med AI
  • Evne til å gjenkjenne og korrigere innebygde mønstre som avbrudd, tidtakere og ikke-blokkerende løkker i AI-utgang
  • Evne til å gjennomgå den genererte koden når det gjelder minne, sanntid og sikkerhet før du laster den opp til maskinvaren

I mekatronikk er mikrokontrolleren der ideer møter den fysiske verden. Kort som Arduino, STM32, ESP32; den leser sensorer, driver aktuatorer, kommuniserer og gjør alt dette under begrenset minne, begrenset prosessorkraft og strenge tidskrav. Kunstig intelligens er veldig nyttig i dette feltet: den kan trekke ut registerinnstillinger basert på en sensors dataark, kode en kommunikasjonsprotokoll, stille inn et timeravbrudd. Men innebygde systemer er et av områdene der AI produserer de mest "overbevisende usannheter"; fordi registeradresser, bitmasker og timing-atferd er spesifikke for brettet og en bitfeil forstyrrer hele oppførselen. I denne enheten dekker vi hvordan du får generert innebygd kode med AI og hvordan du vurderer den før du laster den inn i maskinvaren.

Forskjellen mellom innebygd kode fra Pure Software

Et skrivebordsprogram har rikelig med minne, operativsystem og enkel feilsøking. Innebygd kode mangler de fleste av disse:

Størrelse

skrivebord

innebygd system

minne

GB nivå

KB-nivå (f.eks. 2 KB RAM)

timing

Generelt fleksibel

Stram, sanntid

feilsøking

Enkel (debugger, logg)

Hard (JTAG, seriell, LED)

Feil resultat

Programmet krasjer

Aktuator/maskinvare kan være skadet

ressurstilgang

OS-sammendrag

Direkte tilgang til registeret

Disse forskjellene bestemmer kriteriene dine for å evaluere AI-utdata: minnebruk, sanntid (ikke-blokkerende) og maskinvareregisternøyaktighet er alltid øverst på sjekklisten.

Blokkering vs ikke-blokkerende kode

Den vanligste feilen som gjøres av nybegynnere (og ofte gjort av AI) er bruken av delay(). delay(1000) låser prosessoren i 1 sekund; I denne perioden kan ingen andre sensorer leses, ingen knapper kan kontrolleres. Dette er uakseptabelt i mekatronikk. I stedet brukes et millis()-basert ikke-blokkerende mønster.

// BAD: blocker -- prosessor kan ikke gjøre noe annet arbeid i 1 sekund void loop() { digitalWrite(LED, HIGH); forsinkelse(1000); // alt stopper digitalWrite(LED, LAV); forsinkelse(1000); // En nødknapp kan ikke leses på dette tidspunktet!}// GOOD: non-blocking -- the loop is not blocked, other tasks run if (nowMs - previousMs >= interval) { previousMs = nowMs; ledStatus = !ledStatus; digitalWrite(LED, ledStatus); } knappSjekk(); // kan kjøre i hver syklus sensorRead(); //kan kjøre i hvilken som helst sløyfe}

Det ikke-blokkerende mønsteret er grunnlaget for innebygd mekatronikk: kontrollsløyfen flyter kontinuerlig, ingen oppgave låser ut en annen. Å fortelle AI at "ikke bruk forsinkelse, skriv millisbasert ikke-blokkering" når du skriver kode, forbedrer kvaliteten på utdataene direkte.

Tips: Se etter forsinkelse( i den innebygde koden fra AI. Hvis du ser en forsinkelse i hovedkontrollsløyfen, er den oftest ikke egnet for et sanntidssystem og bør skrives om.

Avbrudd og timere

Vi fanger opp tidskritiske hendelser (koderpuls, knapp, periodisk sampling) med avbrudd i stedet for å vente i hovedsløyfen. Avbruddsrutinen (ISR) bør skrives kort og nøye: ingen forsinkelser, Serial.print eller lange beregninger i den; Delte variabler er markert som flyktige.

volatile long encoderCounter = 0; // ISR og loop er delt -> volatile condition void enkoderISR() { // Short ISR: bare tell, gjør ikke noe annet arbeid 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() { lang teller; noInterrupts(); //short interrupts for atomic read counter = encoderCounter; avbryter(); //handle trygt med telleren...}

Tre kritiske punkter i dette eksemplet er hvor AI ofte går glipp av: (1) den delte encoderCounter må være "flyktig", ellers vil kompilatoroptimaliseringen gå glipp av oppdateringer; (2) ISR bør være kort; (3) Ved lesing av en multibyte-variabel i hovedsløyfen, må avbrudd for atomavlesning lukkes i kort tid, ellers kan ISR gripe inn under lesing og halv/korrupt verdi kan leses (rasetilstand). Sørg for å sjekke om disse tre er til stede i AI-koden.

Registrer nøyaktighet og datablad

AI kan på en troverdig måte feilrepresentere registeradressen til en sensor eller konfigurasjonsbiten til en MCU. For eksempel er strømstyringsregisteret til en MPU6050 IMU 0x6B; Hvis AI gir dette som 0x6A, er koden kompilert, det ser ut til å fungere, men sensoren våkner ikke. Slike feil oppdages bare sammenlignet med dataarket.

// MPU6050 vekking: i henhold til dataarket PWR_MGMT_1 = 0x6B, verdi 0x00#define MPU_ADDR 0x68#define PWR_MGMT_1 0x6B // <-- VERIFY from dataarkWire.beginTransmission(MPU_ADDR);Wire.write(PWR_MGMT_1);Wire.write(0x00); // våkne opp fra hvilemodusWire.endTransmission(true);

Oppmerksomhet: Bekreft hver registeradresse, bitmaske og I2C/SPI-adresse gitt av AI fra dataarket. Disse verdiene er kort- og brikkespesifikke; Verdien AI "husker" kan være fra en annen brikrevisjon. Feil register fører i det stille til feil oppførsel.

Svak forespørsel / sterk forespørsel

SVAK:"Les temperatursensor på ESP32."(Hvilken sensor? Hvilken protokoll? Hvilken pinne? Generisk, sannsynligvis feil kode.)STERK:"Les en DS18B20 temperatursensor på ESP32 (Arduino-rammeverk) fra GPIO4 med OneWire. Skriv ikke-blokkerende, sampling hvert 1. sekund (bruker forsinkelse, millis-fiks i tilfelle av feil eller sett feil17-verdi eller les feil17). spesifiser hvert bibliotek og pin-tilkobling du bruker i den første kommentaren Av minnegrunner, bruk tegnbuffer i stedet for streng."

Kraftig ledetekst; Det gir brikken, rammeverket, sensoren, protokollen, pinne, samplingsmønster, feilstatus og minnebegrensning. På denne måten er resultatet både verifiserbart og realistisk.

Se gjennom sjekkliste for innebygd kode

Før du laster inn AI-utgangen, send den gjennom denne listen:

  1. Blokkering: Er det en forsinkelse eller lang blokkering i hovedsløyfen?
  2. volatile: Er variabler delt med ISR volatile?
  3. Atomtilgang: Er multi-byte delt variabel trygt å lese?
  4. Registrer: Er adressene og bitmaskene kompatible med dataarket?
  5. Minne: String, store arrays, skaper rekursjon KB-nivåoverflyt?
  6. Feilhåndtering: Håndteres sensoravlesningsfeil, kommunikasjonstidsavbrudd?
  7. Sikker start: Er aktuatorutgangene plassert i sikker (passiv) tilstand ved oppstart?

Mini etui

Innebygde systemingeniør Baran får AI til å skrive koden som leser IMU for en drone. Koden kompileres og ser ut til å fungere, men vinkelverdiene er meningsløse. Baran bruker sjekklisten: sammenligner registeradressene med dataarket og finner ut at AI-en gir feil ut gyroskopkonfigurasjonsregisteret (0x1A i stedet for 0x1B), så følsomhetsskalaen er feil. Når de er korrigert, avgjøres verdiene. Deretter delay(10) merknader i hovedsløyfen; konvertere dette til en millis-basert struktur, fordi blokkering av flykontrollsløyfen er uakseptabelt. Til slutt ser den at den delte tellervariabelen ikke er volatil og legger den til. AI ga skjelettet raskt; Men gjennomgangslisten fanget tre separate feil: register, blokkering og flyktig, og maskinvaren var ikke i fare i det hele tatt.

Vanlige feil

  • Dreper sanntidsresponsen ved å bruke delay() i hovedkontrollsløyfen.
  • Unngå å gjøre variabelen som deles med ISR flyktig og opplever tause datakorrupsjon.
  • Lese en multi-byte delt variabel ikke-atomisk og generere en rasetilstand.
  • Ikke verifiserer register-/bitmaskene gitt av AI med dataarket.
  • Opprette en minneoverflyt ved å bruke strenger og store arrays i begrenset RAM.
  • Glemte først å sikre aktuatorutgangene.

Oppsummert

  • Innebygd kode; Den opererer med begrenset minne, stram timing og direkte registertilgang.
  • I hovedsløyfen brukes et millis-basert ikke-blokkerende mønster i stedet for forsinkelse.
  • ISR holdes kort; delte variabler må være flyktige og atomære tilgjengelige.
  • Registeradresser og bitmasker verifiseres alltid mot dataarket; AI kan ta feil.
  • Minne, feilhåndtering og sikker oppstartsstatus kontrolleres alltid.
  • Kraftig ledetekst; Den inkluderer brikken, rammeverket, sensoren, protokollen, pinne og begrensninger.

Søknadsoppgave

Velg en sensor (f.eks. DS18B20, MPU6050 eller HC-SR04) og en mikrokontroller (Arduino/ESP32/STM32). Få AI til å generere en ikke-blokkerende lesekode med den kraftige ledetekstmalen i denne enheten. Følg deretter de syv elementene i gjennomgangssjekklisten én etter én: sammenlign minst én register/pin-verdi med dataarket, se etter sløyfeforsinkelser, kontroller den flyktige statusen til delte variabler. Hvor mange elementer "bestod" ved første forsøk og hvor mange krevde korrigering? Noter hvert problem du finner og dets fiks.