Elektronicafundamenten voor robots: een leertraject
Voed een robot van stroom die onder belasting blijft draaien, zet meerdere sensoren op één I²C-bus en schrijf een lus die ze allemaal uitleest zonder ooit te blokkeren.
De meeste robotproblemen die op softwareproblemen lijken, zijn het niet. Het bord reset en de code krijgt de schuld; een sensor geeft onzin terug en de bibliotheek krijgt de schuld; de robot negeert zijn bumper en de logica krijgt de schuld. In elk geval zit de fout een laag lager, in dat deel van het systeem waar niemand een tutorial over schreef omdat het te basaal leek om er een nodig te hebben.
Dit leertraject is die laag. Het behandelt voeding — waarom de spanning van een accu inzakt als de motoren starten en wat je daaraan moet doen; de I²C-bus — wat die twee draden die alle sensoren delen werkelijk doen; en timing — waarom een lus die stopt om te wachten een robot is die niet kan reageren.
Niets ervan is moeilijk. Alles ervan wordt door elk ander leertraject op deze site verondersteld.
Voordat je begint
Je hebt een microcontroller nodig waar je al firmware in kunt flashen, en de bereidheid om een multimeter over een accu te zetten. Geen regeltheorie, geen wiskunde verder dan optellen en één keer delen. Heb je ooit iets gebouwd — zelfs een knipperende LED — dan ben je klaar.
Wat je hierna kunt
- Binnen een minuut een reset van een crash onderscheiden, en vóórdat je code opent weten welke van de twee je voor je hebt.
- Het stroomverbruik van een robot bij elkaar optellen en op basis van dat getal een accupakket kiezen, in plaats van op basis van wat er in de kit zat.
- Uitleggen waarom een 9 V-blokbatterij met de hoogste spanning op de plank het slechtste resultaat geeft onder belasting, en voorspellen hoe ver elk pakket zal inzakken.
- Meerdere sensoren op één I²C-bus aansluiten, ze met een scanner vinden, en een adresconflict op drie verschillende manieren oplossen.
- Een lus schrijven die sensoren uitleest, motoren aanstuurt en status meldt op drie verschillende snelheden zonder ooit te blokkeren — en de overloopvergelijking goed krijgen.
- Je eigen slechtste looptijd meten in plaats van hem aan te nemen.
Waar mensen vastlopen
“Het is niet gereset” opvatten als bewijs dat de voeding in orde is. De brown-out-detector van een Arduino staat op 2,7 V, maar een ATmega328P van 16 MHz heeft ongeveer 3,8 V nodig om binnen zijn nominale snelheid te blijven. In die band werkt de chip buiten spec en komt er niets tussen, en daar komen de vreemdste fouten op een robot voor — beschadigde variabelen, een servo die opspringt, een sensor die plausibele onzin teruggeeft.
Een condensator toevoegen en verwachten dat die een reset oplost. De rekenkunde zegt iets anders: een condensator van 1000 µF die een piek van 2 A gedurende 10 ms moet geleiden, zou 20 V laten zakken. Hij onderdrukt schakelrimpel en commutatiepieken, wat het waard is om te doen, maar alleen een stevigere accu kan de piek dragen.
Breakout-borden op één bus stapelen. Vrijwel elk bord heeft zijn eigen pull-upweerstanden, en die gaan parallel. Drie borden zitten op de grens en het vierde brengt de bus onder de stroom die enig apparaat kan sinken — dus drie sensoren werken en het vierde kapotmaakt ze allemaal, terwijl er niets kapot is.
Een 8-bits adres uit een datasheet aflezen. De datasheet van een MPU-6050 zegt 0xD0; de Arduino-bibliotheek
wil 0x68, dezelfde bits één keer naar rechts geschoven. Dit is de meest voorkomende I²C-fout, en hij ziet er
precies uit als een dood bord.
now >= last + interval schrijven. Het leest natuurlijker dan de aftrekvorm, en het klapt om bij de overloop
na 49,7 dagen: het vuurt dan continu in plaats van te wachten. Trek altijd af.
De luslogica de schuld geven voor een geblokkeerde lus. Interrupts blijven lopen tijdens delay(), dus de
encodertellingen blijven perfect correct terwijl de robot niet meer reageert — waardoor het symptoom lijkt op een bug
in de beslislogica in plaats van op timing.
Wat je nodig hebt
| Wat | Waarom dit leertraject het nodig heeft | Ruwe kosten |
|---|---|---|
| Een microcontroller die je kunt flashen | Elke meting hier wordt op een draaiend bord genomen, niet op papier | Arduino Uno, ~$8 kloon |
| Een multimeter | Het enige instrument dat dit leertraject niet kan missen — elke bewering die het maakt, controleer je zelf | ~$15 |
| Een accupakket onder belasting | Een pakket dat je meet zonder iets eraan hangt vertelt je niets; je hebt er een nodig dat iets aanstuurt | 4×AA-houder of 2S Li-ion |
| Twee I²C-breakoutborden | Eén bord laat je het pull-upprobleem nooit zien. Twee beginnen het te tonen. | MPU-6050 + iets anders, ~$5 |
| Een of twee motoren | De belasting die de rail doet inzakken — de fout die dit leertraject bestaat om te verklaren | Elke DC-reductiemotor |
Geen oscilloscoop nodig. Elke meting in dit leertraject is een gelijkstroommeting die een goedkope multimeter aankan.
Waarom dit leertraject in deze volgorde loopt
De volgorde is niet willekeurig — elke stap neemt een mogelijkheid weg waarmee de volgende je zou kunnen misleiden.
Timing komt vóór alles wat je meet. Een geblokkeerde lus maakt elke andere meting verdacht, omdat je niet meer kunt zeggen wanneer een meting is genomen. Zodra de lus niet-blokkerend is, kun je een tijdstempel vertrouwen, en pas dan is een meting het waard om vast te leggen.
Voeding komt vóór analoog. analogRead op een Arduino is ratiometrisch — het rapporteert de ingang als
fractie van zijn referentie, en de standaardreferentie is dezelfde 5 V-rail die de motoren naar beneden trekken. Meet
je een accu via een spanningsdeler op een inzakkende rail, dan stijgt de uitlezing terwijl de accu daalt. Een
spanning eerlijk uitlezen is onmogelijk zolang je niet weet wat je rail doet, dus de voedingsstap moet eerst komen.
I²C komt na de voeding, maar is onafhankelijk van analoog. De bus is een apart subsysteem en faalt op zijn eigen manier — via de rekenkunde van de pull-ups en adresconflicten, niet via het inzakken van de voeding. Ze hangt rechtstreeks onder de bordstap, en daarom vertakt de boom daar.
Het lab komt als laatste. De sensorsimulator laat je bewust ruis, bias en uitvallende metingen aan een schoon signaal toevoegen. Dat is pas leerzaam nadat je hebt gezien hoe je eigen hardware ze produceert en weet wat elk ervan veroorzaakt heeft.
Mijlpalen: hoe je ziet dat een stap is gelukt
Elk van deze is een werkbanktest, geen quiz. Kun je het getal niet produceren, dan is de stap niet af.
| Stap | De check | Hoe een geslaagde test eruitziet |
|---|---|---|
| Niet-blokkerende timing | Print de slechtste duur van je lus over 10 seconden | Een gemeten getal in microseconden, geen aangenomen getal — en het groeit niet als een sensor wordt losgekoppeld |
| Accu onder belasting | Meet de pakketspanning met de motoren uit en daarna met de motoren vastgelopen | Je kunt de inzakking in volt noemen en die delen door de stroom om de inwendige weerstand van het pakket te krijgen |
| Stroombudget | Tel op papier het stroomverbruik van elk apparaat op en meet daarna het totaal | Papier en meter komen binnen ongeveer 20% overeen; zo niet, dan heb je een apparaat gevonden dat meer trekt dan zijn datasheet opgeeft |
| Analoge ingang | Lees dezelfde accu via je spanningsdeler met de motoren uit en met de motoren draaiend | De uitlezing verandert niet als de motoren starten — doet ze dat wel, dan verandert je referentie |
| I²C-bus | Voer een busscanner uit en voeg elk bord één voor één toe | Elk adres verschijnt, en je kunt de totale pull-upweerstand op de bus noemen |
| Adresconflict | Zet de AD0-pin van de MPU-6050 met een jumper op hoog | De scanner meldt 0x69 in plaats van 0x68 — en je kunt uitleggen waarom de datasheet 0xD0 zegt |
Waar dit leertraject ophoudt
Dit leertraject stopt bewust op het punt waarop de elektronica je niet meer misleidt. Het behandelt geen motordrivers, regellussen of iets anders dat bepaalt waar een robot naartoe moet — dat zijn de leertrajecten motorregeling en PID-regeling, en die veronderstellen allebei alles hierboven.
Het stopt ook vóór drie dingen die het waard zijn te noemen zodat je weet dat ze bestaan. Het behandelt geen schakelende spanningsregelaars, waarmee je 5 V uit een 12 V-pakket haalt zonder het verschil als warmte in een lineaire regelaar te verbranden. Het behandelt geen niveaushifting tussen apparaten op 5 V en 3,3 V, die je nodig hebt zodra je een ESP32 en een 5 V-sensor op dezelfde bus zet. En het behandelt geen PCB-layout of solderen — alles hier gebeurt op een breadboard, wat prima is om te leren en op zichzelf een bron van steeds wisselende fouten zodra een robot gaat bewegen.
Leerroute
De route
Volg de knooppunten op volgorde – elk ontgrendelt het volgende zodra je het hebt afgerond. Je voortgang wordt op dit apparaat opgeslagen.
0 / 9 klaar
Veelgestelde vragen
Veelgestelde vragen
Welke elektronica moet ik kennen voordat ik een robot bouw?
Drie dingen, en geen ervan is geavanceerd. Je moet een voeding kunnen dimensioneren op basis van de stroom die je robot werkelijk trekt, zodat hij niet reset als de motoren starten. Je moet de I²C-bus goed genoeg begrijpen om meerdere sensoren op twee gedeelde draden te zetten zonder dat ze elkaar in de weg zitten. En je moet een regellus schrijven die nooit stopt om te wachten, zodat de robot kan reageren terwijl hij iets anders doet. Al het andere — regeltheorie, navigatie, kinematica — staat bovenop die drie.
Waarom reset mijn Arduino als de motoren starten?
De inwendige weerstand van de accu zet de inschakelstroom van de motoren om in een spanningsval, en de hele rail zakt daarmee mee. Een motor die via een pakket met 0,5 Ω inwendige weerstand een piek van 2 A trekt, trekt de rail een volle volt omlaag voordat er ook maar iets de spanningsregelaar bereikt. Als die dip het bord onder de brown-out-drempel brengt, herstart het. De oplossing is een stevigere accu en een aparte motorvoeding, niet een grotere condensator — een condensator van 1000 µF die 2 A gedurende 10 ms moet geleiden, zou 20 V laten zakken, en kan zo'n piek dus niet overbruggen.
Hoeveel I²C-sensoren kan ik aan één Arduino hangen?
De adresruimte biedt ruimte aan 112 apparaten, maar de elektrische grens komt daar lang voor. Vrijwel elk breakout-bord heeft zijn eigen pull-upweerstanden, meestal 4,7 kΩ, en borden op elkaar stapelen zet die weerstanden parallel. Vier borden leveren ongeveer 1,2 kΩ, wat bij 5 V meer dan 4 mA aan zinkstroom vraagt — voorbij de 3 mA die een I²C-apparaat moet kunnen afvoeren. Drie borden werken meestal, maar het vierde kapotmaakt de hele bus. Haal de pull-ups van alle borden behalve één weg en je kunt veel verder gaan.
Is delay() echt zo slecht in robotcode?
Voor een robot: ja. Terwijl de processor in delay() zit, leest hij geen sensoren en neemt hij geen beslissingen — een robot in delay(500) is een halve seconde blind, wat bij 0,3 m/s 15 cm rijbeweging is. Lastig te diagnosticeren is dat interrupts blijven lopen, waardoor de encodertellingen de hele tijd correct blijven. Het symptoom lijkt op gebroken beslislogica in plaats van op geblokkeerde timing. Vervang het door het millis()-patroon, en trek bij vergelijken af in plaats van op te tellen, anders klapt de vergelijking om bij de overloop na 49,7 dagen.
Heb ik een oscilloscoop nodig om dit leertraject door te werken?
Nee. Een multimeter volstaat voor alles hier — de spanning van een accu meten onder belasting, de uitgang van een spanningsdeler controleren, bevestigen dat een rail niet is gezakt. Een oscilloscoop maakt brown-outs en I²C-problemen een stuk makkelijker zichtbaar, en als je er een hebt moet je hem gebruiken, maar elke meting die dit leertraject vraagt is een gelijkstroommeting die een meter van £10 aankan.
Hoe lang duurt dit leertraject?
Ongeveer twee uur lezen over de vier tutorials, en realistisch een avond of twee aan de werkbank om de metingen ook echt te doen. De metingen zijn het punt — de getallen die dit leertraject je leert te vertrouwen zijn de inzakking van je eigen accu, de totale pull-up van je eigen bus en de slechtste looptijd van je eigen lus, en daar valt niets over op te zoeken.