XMOS startKIT:een XMOS en Raspberry Pi Robot XMP-1 bouwen
Inleiding
De XMOS startKIT van Farnell (of Newark) is een zeer goedkoop (£ 12 inclusief btw) processorplatform dat goed werkt met de Raspberry Pi. Samen is het mogelijk om robotica-toepassingen te bouwen zonder dat soldeerwerk nodig is.
De XMOS startKIT is een bord ter grootte van een creditcard met daarop een XMOS-chip met meerdere 'XMOS-cores' die kunnen worden geprogrammeerd in C. XMOS-technologie zorgt ervoor dat dingen op hoge snelheid parallel kunnen lopen met weinig jitter. Dit zijn precies de kenmerken die ideaal zouden kunnen zijn voor robotica-toepassingen.
Samen met wat code om op het XMOS startKIT-bord en op de Raspberry Pi (RPI) te draaien, worden de borden gebruikt om een eenvoudig compact mobiel platform te bouwen (vanaf nu noem ik het XMP, XMOS Mobile Platform in plaats van een robot in de XMOS-geest van alles voorafgaan met 'X').
Hoewel de XMP-1 niet echt een robot is totdat hij enkele sensoren en meer programmering heeft, zou hij in de toekomst kunnen worden uitgebreid voor robotica-experimenten. De XMP-1 gebruikt goedkope standaard hardware en geen exotisch gereedschap behalve schroevendraaiers, draadknippers en tangen.
Dit bericht behandelt de communicatie tussen het RPI- en XMOS-bord met behulp van een seriële perifere interface (SPI) -interface en hoe de XMP-1 te bouwen en te bedienen vanuit een webbrowser.
De video hier laat zien dat XMP-1 een route leert; de eerste poging om het te gebruiken! Het zou baat hebben bij een betere gebruikersinterface. XMP-1 kan vrij snel bewegen, maar ik deed het hier rustig aan op een lage snelheid. Aan de rechterkant is de browserbesturing en onderaan is de console-uitvoer, die alleen wat keep-alive- en statusberichten genereert om te zien wat er gebeurt.
De volgende video hieronder toont de XMP-1 die probeert de route af te spelen en onderweg lijden en pijn veroorzaakt. Mijn goedkope continu-rotatieservo's (die worden gebruikt om de wielen aan te drijven) waren niet erg goed, en XMP-1 heeft nog geen sensoren.
Een beetje meer detail
Dit bericht is eigenlijk deel 2 van enkele XMOS startKIT-experimenten. Deel 1 bevat de XMOS-introductie, terminologie, architectuur en een snelstartgids met voorbeeldprogramma's. Als je geïnteresseerd bent in de technologie, kan het helpen om eerst deel 1 te volgen, zodat dit deel 2 logischer wordt. Dit deel 2 is bedoeld om een eenvoudig raamwerk te bouwen voor snelle communicatie tussen de Raspberry Pi en het XMOS startKIT-bord. Het raamwerk moet algemeen genoeg zijn om voor veel projecten te kunnen gebruiken (robotica was niet mijn bedoeling). De XMP-1 is eigenlijk slechts een bijproduct, in de wens om de Raspberry Pi naar XMOS-bordcommunicatie te testen. Het wordt hier vastgelegd voor het geval het nuttig is. (Let op, er is ook een deel 3 getiteld XMOS startKIT:XMOS en Raspberry Pi Oscilloscope XAE 1000 die de SPI-mogelijkheid hergebruikt die in dit bericht wordt besproken, en introduceert hoe de analoog naar digitaal omzetter (ADC) die aanwezig is in de XMOS-chip te gebruiken , en hoe u realtime afbeeldingen in een webbrowser kunt uitvoeren).
Als je alleen geïnteresseerd bent in het construeren en gebruiken van XMP-1, dan kun je gewoon de code onderaan het bericht nemen, compileren en opslaan in Flash (zoals beschreven in deel 1) op het XMOS startKIT-bord en de Raspberry Pi, en volg gewoon de secties die de XMP-1 hardware-assemblage beschrijven en sla hier alle andere inhoud over. Als u geïnteresseerd bent in het besturen van hardware met behulp van de Raspberry Pi en een webbrowser, kan een deel van de code hier opnieuw worden gebruikt. Maar om het meeste uit de Raspberry Pi en XMOS startKIT-combinatie te halen, kan de overige informatie hier handig zijn als de startKIT nieuw voor u is.
Oplossingsoverzicht – hardware en software
Hier is een foto van de voltooide XMP-1 die wordt opgeladen. Voor gebruik buitenshuis heb ik een apparaat van het type 802.11-hotspot (MiFi) gebruikt, met de browser op een mobiele telefoon.
Het onderstaande diagram toont bij benadering de lay-out van de stukjes en beetjes, gezien vanaf de achterkant van de XMP-1. Je kunt zien dat het vrij eenvoudig is - XMP-1 was slechts een snel experiment.
De Raspberry Pi (RPI) wordt gebruikt om alle netwerkactiviteiten af te handelen. Het draait een kleine webserver en de meeste code is geschreven in JavaScript op een Node.js-platform. De RPI communiceert motorbesturingssnelheden (eigenlijk werden servo's met continue rotatie gebruikt voor XMP-1) via een seriële interface (SPI) naar het XMOS startKIT-bord. De XMOS startKIT is verantwoordelijk voor het toevoeren van pulsbreedtemodulatie (PWM)-signalen naar de motoren.
De RPI is verbonden met het netwerk via een 802.11 WiFi USB-adapter.
Het volledige bedradingsschema wordt hier getoond. De hardware en constructie wordt later beschreven.
Het onderstaande schema toont de software die zal worden geïmplementeerd op de RPI en op de startKIT. Het ziet er veel uit, maar is het niet en kan worden opgesplitst in kleine onderdelen die hieronder worden beschreven. Zoals vermeld staat de volledige broncode onderaan dit bericht, zodat deze desgewenst zonder enige wijziging kan worden gebruikt.
Kortom, het groene blok zorgt voor de webinteractie en bepaalt op basis van de gebruikersinvoer de snelheid en richting van de motoren. Het groene blok biedt de gebruiker een webpagina (index.html) waarin de gebruikersinterface is opgenomen. Het xmos_servo-programma is een klein stukje software geschreven in C dat de gewenste snelheid/richting vertaalt in seriële perifere interface-bytes aan gegevens die naar de startKIT worden verzonden. De startKIT-software is verdeeld in drie delen die tegelijkertijd op afzonderlijke XMOS-kernen draaien. Het spi_process zet de SPI-signalen om in gegevens die in een array worden opgeslagen. De data_handler-code inspecteert de array om te beslissen wat te doen (de enige conclusie die het vandaag maakt, is het manipuleren van de servo's). Het servo_handler-proces voert een pulsstroom uit naar de servo's, zodat ze met de gewenste snelheid kunnen draaien. Al deze blokken worden hieronder in meer detail uitgelegd.
Seriële perifere interface (SPI)
SPI vertrouwt op vier draden die bekend staan als SS, SCLK, MISO en MOSI en een toewijzing van master en slave voor de twee apparaten die bij de communicatie betrokken zijn. In het geval van de RPI- en XMOS-kaart is de RPI het masterapparaat en is het verantwoordelijk voor het genereren van het kloksignaal. De RPI verzendt gegevens op de MOSI-draad en ontvangt gegevens op de MISO-draad. Dit betekent dat de SPI-interface tegelijkertijd gegevens in twee richtingen kan overbrengen. Als in de praktijk eenrichtingsgegevens vereist zijn, kan het MOSI- of het MISO-signaal worden genegeerd, afhankelijk van de richting waarin u geïnteresseerd bent.
Het screenshot van de oscilloscoop hier (individuele signalen en de geautomatiseerde SPI-decodering van een Tektronix MSO2024B-oscilloscoop) toont een voorbeeld van SPI-communicatie met behulp van de Raspberry Pi. SPI kan op een paar manieren worden geconfigureerd; u kunt in dit voorbeeld zien dat drie bytes aan gegevens zijn overgedragen van de master (RPI) naar de slave (XMOS-kaart) en dat ze 0x02, 0x00 en 0x10 waren, en dat er ofwel geen gegevens of 0x00, 0x00, 0x00 werden overgedragen van de slaaf tegelijkertijd naar de master.
De SS-draad is een chip-select-signaal (actief laag). De RPI heeft twee pinnen op zijn 26-polige connector die voor SS kan worden gebruikt; ze worden in het onderstaande diagram blauw omcirkeld weergegeven, gemarkeerd met CE0 en CE1. Dit betekent dat de RPI desgewenst met twee SPI-slave-apparaten kan praten. In dit geval werd slechts één van de CE-pinnen gebruikt - ik koos CE1.
Hobby servomotoren besturen
Hobby-servomotoren genereren een beweging op basis van een ingangssignaal. Ze draaien meestal minder dan één volledige omwenteling. Gewoonlijk zal een hobbyservo binnen een bereik van ongeveer 180 graden draaien. De uitgaande as kan worden aangesloten op (bijvoorbeeld) koppelingen om wielen volledig naar links of helemaal naar rechts (of iets daartussenin) te laten draaien op basis van het ingangssignaal.
Het onderstaande diagram toont de binnenkant van een typische hobbyservo (overgenomen van deze site). Links (in blauw) staat een conventionele DC-motor. Het is veel teruggesteld en de laatste as is rechts te zien die is verbonden met een blauwe arm die bijvoorbeeld kan worden verbonden met een stuurmechanisme. Onder de eindschacht zit een potentiometer, die feedback geeft over de exacte positie van de eindschacht. Een hobbyservo is daarom een gesloten-lussysteem en kan zichzelf corrigeren als de arm per ongeluk van de gewenste positie wordt weggeslagen.
Hobby-servo's hebben meestal drie aansluitingen; 0V, 5V en Signaal. De signaaldraad is een digitale ingang naar de servo en vereist een PWM-signaal. De grootte van de pulsbreedte bepaalt de hoek waarin de as zal bewegen. Het PWM-signaal moet elke 20 msec worden herhaald en een pulsbreedte van 1,5 msec zal ertoe leiden dat de as naar een gecentreerde positie beweegt. Een breedte van 1 msec zal de servo volledig in de ene richting bewegen, en een breedte van 2 msec zal de servo volledig in de andere richting bewegen (verder beneden zullen er enkele oscilloscoopsporen van servobesturing zijn).
Er is een soort gemodificeerde servo die bekend staat als een 'continue rotatie'-servo. Het is een gemodificeerde servo waarbij de potentiometer samen met eventuele eindstops wordt verwijderd en het circuit wordt overgehaald om te denken dat de servo zich nog steeds in de gecentreerde positie bevindt. Als u PWM verzendt met een andere pulsbreedte dan 1,5 msec, zal het mechanisme met de klok mee of tegen de klok in draaien met een snelheid die afhangt van de pulsbreedte. De XMP-1 gebruikt twee hobbyservo's met continue rotatie, één voor elk wiel. Ze zijn geen optimale manier om gecontroleerde beweging te verkrijgen (XMP-2 gebruikt geborstelde gelijkstroommotoren) omdat ze worden gebruikt voor een ander doel dan de oorspronkelijke bedoeling voor hobbyservo's, maar ze hebben het voordeel dat ze kunnen worden bestuurd door een digitale logisch signaal en ze hebben geen externe H-brugschakeling nodig.
Hobby-servokabels kunnen afhankelijk van de fabrikant een andere kleurcodering hebben. Meestal is de middelste draad rood en gaat deze naar +5V. De zwarte of bruine draad is 0V. De witte of gele draad is de PWM-signaalingang.
Ontwikkeling starten – Borden aansluiten
Om de software te ontwikkelen, werden de RPI en startKIT met elkaar verbonden met behulp van een lintkabel en IDC-connectorassemblage - deze kunnen worden geassembleerd met een bankschroef of kant-en-klaar worden gekocht. Voor een zelf-geassembleerde versie is het de moeite waard om een extra IDC-connector aan te schaffen voor gebruik als debug-connector in het midden van de kabel, om het leven gemakkelijker te maken bij het aftasten van signalen met een multimeter of scoop.
SPI (spi_process) implementeren op de XMOS startKIT
Het gebruik van de XMOS-ontwikkelomgeving (xTIMEcomposer) kwam aan bod in deel 1. De screenshots hieronder tonen de Windows-versie van xTIMEcomposer, maar de Linux-versie ziet er identiek uit (en mogelijk kan de Mac-versie er ook hetzelfde uitzien).
Op dit punt kunt u met de rechtermuisknop op de SPI Slave Function Library in het xSOFTip-lab klikken en de bibliotheek in de werkruimte importeren. Ik ben geen expert op het gebied van xTIMEcomposer, dus ik gebruik het hier waarschijnlijk verkeerd, maar de broncode en het headerbestand voor de bibliotheek verschenen in een aparte map in de Projectverkenner (hieronder blauw omcirkeld):
De bestanden moesten zich in de spi-test-map bevinden (zodat ze verschijnen zoals hierboven omcirkeld in het groen) om te bereiken dat ik de bestanden spi_slave.h en spi_slave.xc handmatig kopieerde van de map module_spi_slave/src naar de spi-test /src map met Windows Verkenner.
De software gebruikt het concept van poorten om de output te controleren of input te lezen. Er is een mapping tussen deze logische poorten en de fysieke mapping naar de pin op de chip. De toewijzingen kunnen in bepaalde combinaties worden gewijzigd (zie figuur 3 in het PDF-document Inleiding tot XS1-poorten).
Invoer-/uitvoerpoorten op XMOS-apparaten kunnen 1, 4, 8, 16 of 32-bits breed zijn. Bij het ontwerpen met het onderdeel, wil je misschien bepaalde functies toewijzen aan 1-bit poorten, of andere functies aan multi-bit poorten, en dus zal figuur 3 erg handig zijn om te bepalen welke poorten en pinnen je moet gebruiken.
Met de SPI-slavecode nu in het spi-test/src-bestand, is deze code enigszins gewijzigd. De bibliotheekcode gaat ervan uit dat de poorten die worden gebruikt voor de SPI-interface allemaal 1-bits poorten zijn, terwijl de Raspberry Pi SPI SS-pin (CE1) is aangesloten op een 32-bits poort op het XMOS-bord. Afbeelding 8 van het startKIT Hardwarehandleiding PDF-document wordt hieronder weergegeven. In het midden in het groen zie je de 2×13-weg header die verbinding maakt tussen het XMOS-bord en de Raspberry Pi. Links en rechts in blauw staan de fysieke pinnamen op de chip (X0D0,, X0D11, etc). De pin gemarkeerde waarden zijn de logische poortnummers. P1A, P1D enzovoort zijn single-bit poorten. P32A1 is het eerste binaire cijfer van een 32-bits poort
Er zijn nogal wat wijzigingen aangebracht in de SPI-bibliotheek en de volledige code is aan het bericht toegevoegd, dus slechts enkele codefragmenten worden hier beschreven, het is niet nodig om te kopiëren/plakken, de volledige code is toegevoegd aan het einde van dit bericht kan worden gebruikt.
De SPI-interface op het XMOS-apparaat wordt geïnitialiseerd zoals hier wordt weergegeven. Het wordt hieronder verder uitgelegd.
+ open sourceview uitvouwen- void spi_slave_init(spi_slave_interface &spi_if)
- {
- int clk_start;
- set_clock_on(spi_if.blk);
- configure_clock_src(spi_if.blk, spi_if.sclk);
- configure_in_port(spi_if.mosi, spi_if.blk);
- configure_out_port(spi_if.miso, spi_if.blk, 0);
- start_clock(spi_if.blk);
- retour;
- }
Zoals vermeld in de post van deel 1, kan I/O op precieze tijden in en uit het XMOS-apparaat worden geklokt. In de bovenstaande code wordt de functie set_clock_on (gedefinieerd in het XMOS xs1.h-headerbestand) gebruikt om een van de ingebouwde klokmechanismen in de XMOS-chip in te schakelen. Het onderstaande diagram (uit het document Inleiding tot XS1 Ports) toont dit mechanisme in het geel. De functie configure_clock_src wordt gebruikt om een externe klok te selecteren (blauw weergegeven in het diagram). Het wordt verbonden met de SCLK-pin op de Raspberry Pi. De functies configure_in_port en configure_out_port worden gebruikt om poorten aan het klokmechanisme te koppelen. Zowel de MOSI- als de MISO-signalen (hieronder groen weergegeven) zijn geconfigureerd om te worden gekoppeld aan het klokmechanisme.
De manier waarop seriële gegevens worden verwerkt op XMOS-apparaten is echt netjes. De code hier wordt hieronder verder uitgelegd. Eerst wordt een structuur gebruikt om details te bevatten over de poorten die als SPI-interface moeten worden gebruikt.
+ open sourceview uitvouwen- typedef struct spi_slave_interface
- {
- klok blk;
- in poort ss;
- in gebufferde poort:8 mosi;
- uit gebufferde poort:8 miso;
- in poort sclk;
- } spi_slave_interface;
De interessante regels hierboven zijn degene die verwijzen naar de poortvariabelen mosi en miso. Ze zijn gedeclareerd als type port:8. Als aan de variabelen 1-bits poortadressen zijn toegewezen, zal het XMOS-apparaat de 1-draads stroom van bits automatisch deserialiseren in 8-bits waarden.
Het maakt de rest van de SPI-code heel eenvoudig. Hier is de code die de SPI-gegevensinvoer van de Raspberry Pi beheert:
+ open sourceview uitvouwen- void spi_slave_in_buffer(spi_slave_interface &spi_if, unsigned char buffer[], int num_bytes)
- {
- niet-ondertekende int gegevens;
- unsigned int vlen=0;
- clearbuf(spi_if.miso);
- clearbuf(spi_if.mosi);
- for (int i = 0; i < num_bytes; i++)
- {
- spi_if.mosi :> gegevens;
- data=data<<24;
- buffer[i]=bitrev(data);
- if (i==2)
- {
- vlen=((((unsigned int)buffer[1])<<8) | (niet-ondertekende int)buffer[2];
- if (vlen==0)
- pauze;
- }
- if (i >= vlen+2)
- {
- pauze;
- }
- }
- }
In de bovenstaande code kun je zien dat er een for-lus is, en binnen de lus de regel spi_if.mosi :> data; wordt gebruikt om 8 bits informatie op de MOSI-regel in te lezen in de variabele genaamd data.
De volgende twee regels worden gebruikt om de bits binnen de byte om te draaien en vervolgens worden de gegevens opgeslagen in een bufferarray.
De volgende paar regels hebben wat uitleg nodig; ze zijn gerelateerd aan het gewenste protocol. Het was bedoeld om algemene code te maken die voor veel dingen kon worden gebruikt, niet alleen voor XMP-1. Als de Raspberry Pi gegevens naar het XMOS startKIT-bord stuurt, moet het XMOS-bord weten hoeveel bytes aan gegevens het kan verwachten. Dit zou hard gecodeerd kunnen zijn, maar het zou inflexibel zijn.
Er is gekozen voor een heel eenvoudig ‘tag (of type), length, value’ (TLV) protocol. De eerste byte die de Raspberry Pi moet verzenden, is een tag of identifier in het bereik van 0-255 (d.w.z. één byte). Het is aan de gebruiker om te beslissen wat de waarden vertegenwoordigen. Een waarde van 1 kan bijvoorbeeld "ingestelde motorsnelheid" betekenen en een waarde van 2 kan "ingestelde intensiteit koplamphelderheid" betekenen. De tweede twee bytes zijn een 16-bits waarde die aangeeft hoeveel waardebytes (d.w.z. data) moeten volgen. Ik besloot dit te beperken tot 4 kbyte (4096 bytes), wat aan veel use-cases zou moeten voldoen, maar de werkelijke waarde kan worden gewijzigd door een BUFLEN-definitie in de code aan te passen.
Daarom is het minimum aantal bytes dat op de SPI-interface wordt verzonden drie (tag en een lengte van 0x0000) en het maximum is 4099, wat een tag is en een lengte van 0x1000 (dit is 4096 in hexadecimaal) en 4096 databytes.
Het protocol is enigszins verfijnd, zodat een oneven tagnummer betekent dat de Raspberry Pi een reactie verwacht in de volgende SPI-communicatie die wordt gestart nadat de huidige TLV-stream is voltooid, en een even tagnummer betekent dat de Raspberry Pi geen reactie verwacht terug.
Dit is een heel eenvoudig protocol, maar het moet aan veel gebruikelijke vereisten voldoen. Het wordt ook uitgelegd in de onderstaande tabel waar het blauwe getal de SPI-byte-index is in de ontvangende buffer van 4099-bytes.
Teruggaand naar het eerdere codefragment is te zien dat de volgende paar regels de inhoud van de buffer [1] en buffer [2] onmiddellijk controleren terwijl de SPI-gegevens worden ontvangen. De inhoud zal naar verwachting de lengte hebben zoals te zien is in het bovenstaande diagram (zie blauwe bufferindex). Zodra de code de resterende lengte heeft bepaald, accepteert deze precies dat aantal databytes en wordt de routine afgesloten.
Dat dekt de SPI-invoer naar het XMOS-bord op de MOSI-lijn. SPI-uitvoer van het XMOS-apparaat op de MISO-lijn werkt op een vergelijkbare manier, waarbij de lengte tegelijkertijd op de MOSI-lijn opnieuw wordt gecontroleerd, zodat de functie kan worden afgesloten zodra het gevraagde aantal bytes is overgedragen.
Inter-procescommunicatie
Nu SPI was bedacht en een protocol was geïmplementeerd om gegevens met variabele lengte in beide richtingen uit te wisselen tot 4096 bytes lang, werd er enige aandacht besteed aan de hoofdtekst van het programma. Het was duidelijk dat een XMOS-kern zou worden gebruikt voor het afhandelen van de SPI-taak, maar de rest van de code moet mogelijk in een of meer extra XMO-scores staan.
In deel 1 werd beschreven hoe taken parallel lopen op verschillende XMOS-kernen, en hoe de taken met elkaar kunnen communiceren door waarden in kanalen te duwen. Er is een andere manier om tussen kernen te communiceren en deze gebruikt het concept van "transacties via interfaces" in plaats van kanalen. Het is flexibeler omdat u meerdere variabelen van verschillende typen van de ene XMOS-kern naar de andere kunt sturen. De transactietypen zijn net als een prototype van een C-functie gedefinieerd. Dit wordt allemaal veel duidelijker door naar een voorbeeld te kijken.
Als een toepassing bijvoorbeeld een taak had die een beeldscherm bestuurde, dan kan een verzendtaak het beeldscherm aan of uit willen zetten, of een pixel plotten. De interfacedefinitie voor de communicatie tussen de twee XMOS-kernen zou er ongeveer zo uit kunnen zien:
+ open sourceview uitvouwen- interface programma_display
- {
- void backlight(int state, int color) ; // transactietype 1
- void plot(int x, int y, int color); // transactietype 2
- };
Interfacecommunicatie is unidirectioneel, dus als het display informatie wil verzenden, zoals (bijvoorbeeld) de status van het touchscreen, dan zou een andere interface in de andere richting moeten worden gebruikt. Hieruit blijkt duidelijk dat interfaces een client- en servereinde hebben. Het diagram hier toont twee XMOS-kernen (in paars), twee interfaces (in grijs) en de eerste interface (genaamd program_display) laat twee verschillende soorten transacties toe (in blauw) over de program_display-interface.
Het mooie van het gebruik van interfaces en transactietypes is dat je, net als prototypes van de C-functie, retourwaarden kunt hebben en verwijzingen naar variabelen kunt doorgeven, zodat, hoewel de communicatie altijd wordt gestart door de clientzijde van de interface, de gegevensoverdracht kan van twee kanten komen. Een andere zeer interessante functie die niet in het diagram wordt getoond, is de mogelijkheid voor de server om een 'melding' naar de client-kant te kunnen sturen. Dit kan een signaal zijn voor de klant om op de gebruikelijke manier een transactie uit te voeren, om misschien wat gegevens op te halen. Deze functie wordt gebruikt in de XMP-1-code. Dus meer informatie over hoe u de interfaces precies codeert en gegevens en meldingen verzendt, wordt hieronder verder uitgelegd.
De IPC-architectuur ontwerpen om SPI-inhoud te verwerken
De bediening van de SPI-interface is al beschreven. Nu moet de inhoud van de SPI-berichten op een bruikbare manier aan een taak worden gepresenteerd voor latere verwerking. Gewapend met de kennis over interfaces en transacties, was het mogelijk om te beginnen met het toewijzen van functionaliteit aan afzonderlijke XMOS-kernen en het ontwerpen van de communicatie tussen processen om tot een raamwerk voor algemene doeleinden te komen waarmee nuttige berichtinhoud van de RPI naar de XMOS kon worden verzonden board en vice versa, en worden verwerkt.
Het diagram hier laat zien wat er is ontwikkeld (een soortgelijk diagram als voorheen, behalve dat er nu een tijdreeks is van boven naar beneden).
Wanneer de Raspberry Pi een bericht naar het XMOS-bord wil sturen, zal de RPI het bericht samenstellen in het eerder beschreven TLV-formaat. De informatie wordt vervolgens uitgeklokt op de MOSI-signaaldraad (in groen weergegeven bovenaan het diagram hierboven). Tegelijkertijd moet het XMOS-apparaat iets terugsturen, maar aangezien er nog geen informatie is om terug te sturen, kan de MISO-regel rommel of alle nulwaarden bevatten, zoals weergegeven in roze. De spi_process-functie verzamelt het bericht in een buffer (een array van niet-ondertekende tekens) en initieert vervolgens een transactie naar een afzonderlijke data_handler XMOS-kern. De data_handler is verantwoordelijk voor het verwerken van de inhoud van het bericht en optioneel het terugsturen van informatie naar de spi_process XMOS-kern, zodat elke volgende SPI-uitwisseling nuttige gegevens terug kan sturen naar de Raspberry Pi in plaats van afvalwaarden.
De gegevens kunnen tussen spi_process en data_handler worden verzonden door een kopie van de buffer te maken. In plaats daarvan is het echter mogelijk om gewoon een pointer door te geven aan het buffergeheugen. Een manier om dit te doen, is door de besturing van de pointer- en buffergeheugenlocaties te 'verplaatsen' van spi_process naar data_handler. Zodra data_handler klaar is met de berichtinspectie, kan het de besturing terug verplaatsen naar spi_process met behulp van de retourvariabele die mogelijk is om in transacties te gebruiken. Dit is de reden waarom het bovenstaande diagram een transactie heeft met de naam array_data met een parameter die is gedefinieerd als een verplaatsbare aanwijzer en een retourwaarde die ook is gedefinieerd als een verplaatsbare aanwijzer. Op deze manier heeft slechts één XMOS-kern tegelijkertijd toegang tot het buffergeheugen.
Dit zijn de interfaces die worden gebruikt:
+ open sourceview uitvouwen- interface naar_rpi
- {
- void code(unsigned char c);
- };
- interface from_rpi
- {
- unsigned char* movable array_data(unsigned char* movable bufp);
- };
De spi_handler-code wijst ruimte toe aan een buffer en geeft vervolgens de besturing van de buffer door aan de data_handler-code met behulp van de regel buf=c.array_data(move(buf)) die hier in de code wordt weergegeven:
+ open sourceview uitvouwen- nietig
- spi_process(interface to_rpi server s, interface from_rpi client c)
- {
- niet-ondertekende char opslag[4099];
- niet-ondertekende char* movable buf=storage;
- …
- buf=c.array_data(move(buf));
- …
- selecteer
- {
- case s.code(unsigned char c):
- if (c==SEND)
- {
- spi_slave_out_buffer(spi_sif, buf, 4099);
- }
- pauze;
- }
- }
De data_handler-code verkrijgt de besturing van de buffer en als er vervolgens een reactie naar de RPI moet worden verzonden bij een volgende SPI-transactie, wordt de buffer gevuld met een reactie. Ten slotte wordt de controle over de buffer teruggegeven aan het spi_handler-proces.
+ open sourceview uitvouwen- nietig
- data_handler(interface naar_rpi client c, interface van_rpi server s)
- {
- selecteer
- {
- case s.array_data(unsigned char* movable vp) -> unsigned char* movable vq:
- // vq bevat de gegevens van SPI. We kunnen er hier mee doen wat we willen.
- // Elke reactie wordt hier ook opgebouwd:
- vq[0]=0x22; // tag
- vq[1]=0x00; // lengte
- vq[2]=0x00; // lengte
- vq=move(vp); // geef de aanwijzer terug naar spi_process
- tosend=1;
- pauze;
- }
- if (verzenden)
- {
- c.code(SEND); // send a code to spi_process so that it is aware there is data to send to RPI
- }
- }
Earlier it was mentioned that if an odd tag value was sent by the RPI then this would be an indication that the RPI expected a response message from the XMOS startKIT board on the subsequent SPI exchange. This is implemented by both the spi_process and data_handler making a note that a return message is expected if the first byte received is an odd value. Once data_handler has finished constructing the return message in the buffer memory it moves the buffer pointer back to the spi_process XMOS core and also sends a code transaction which could contain a message such as “ready to send”. The spi_process XMOS core is now ready for any subsequent SPI exchange. If the data_process doesn’t want to send any message back to the Raspberry Pi (for example if the tag was even valued) then the code transaction is not sent (or a different code could be sent such as “not ready to send”).
In the graphic diagram earlier you can see that the subsequent SPI exchange did transmit data back to the Raspberry Pi on the MISO wire.
To summarize, the spi_process and data_process present a fairly general-purpose capability to exchange data bidirectionally between the RPI and XMOS board.
Implementing PWM (servo_handler) on the startKIT
To test out the general purpose architecture, it was decided to use it to control many devices. The devices ended up being hobby servos because they require very little electrical interfacing effort – no H-bridge or transistor driver is needed – and the servo input wire can be directly connected to an XMOS output pin. I didn’t have many servos, so although the code implements 8 servo control, only two were used for XMP-1.
The code could be modified to provide DC motor control too (with a suitable external H-bridge circuit).
It was decided to use a single XMOS core to handle the eight servos. The diagram below shows the total of three XMOS processes used in the solution. The new addition is the servo_handler task which is shown on the right. This task has an array that stores the current servo values. As soon as the task starts up, the values are initialized to a centered value (or standstill for a continuous rotation servo) and then every microsecond the task wakes up to check if the servo PWM signal needs adjustment. If it does then the servo port output is toggled. After 20msec the process repeats.
For more detail:XMOS startKIT Building an XMOS and Raspberry Pi Robot XMP-1
Productieproces
- MQTT-communicatie tussen NodeMCU en Raspberry Pi 3 B+
- Python- en Raspberry Pi-temperatuursensor
- Eenvoudige temperatuur en vochtigheid op Raspberry Pi
- Raspberry Pi temperatuur- en lichtsensor
- Raspberry Pi-sensor en actuatorbediening
- Aerocultuur met Raspberry Pi en vochtigheidssensor
- NIEUWE RASPBERRY PI 3 MODEL B + FUNCTIES EN AANKOOP
- Robot die Raspberry Pi &Bridge Shield gebruikt
- BeagleBone en Raspberry Pi krijgen FPGA-add-ons
- De MonkMakes Raspberry Pi Robot Kit bouwen
- Raspberry Pi CD Box Robot