Wat is dat allemaal? GPIO, SPI, I2C, en UART communicatie

overzicht_bron_tessel_io
bron: https://tessel.io/docs/communicationProtocols

Drieletterwoorden hebben normaal gesproken niet veel toelichting nodig. Afkortingen van 3 (of 4) letters vaak wel. Daarom in dit bericht aandacht voor 4 afkortingen die te maken hebben met de communicatie tussen apparaten zoals een Raspberry Pi, een Arduino, de ESP8266, de BBC micro:bit met randapparatuur of sensoren.

Ik moet bekennen dat ik ze vaak gebruikt heb zonder te weten welk van de vier om welke redenen zou moeten kiezen. Meestal was het een kwestie van “wat wordt ondersteund?” en dan koos ik de eerste waarvoor ik code kon vinden.

Op tessel.io staat duidelijke uitleg voor hun eigen hardware. Ik ga de begrippen, verschillen en overeenkomsten generieker en in het Nederlands beschrijven.

GPIO / General Purpose Input Output

microbit_breakout
micro:bit breakout

Het is zo ongeveer het eerste waar een hacker / maker naar kijkt bij een apparaat: zitten er “pinnen”  aan? 🙂
En dan natuurlijk net zo belangrijk: zijn die pinnen als input of output poorten te gebruiken. De Raspberry Pi heeft ze, een Arduino heeft ze, de ESP8266 idem (al hebben sommige modellen er maar heel weinig), ook de BBC micro:bit heeft ze al worden ze daar niet standaard als pinnen ontsloten, door gebruik te maken van een breakout-box die je zelf kunt maken of kunt kopen, komen ze ook daar beschikbaar.

En het kan zijn dat je heel lang vooruit kunt zonder meer nodig te hebben dan dat. Wil je bv een LED aan of uit-schakelen, de waarde van een eenvoudige thermometer lezen, een relais schakelen, dan heb je aan 1 GPIO poort per device voldoende en zul je de andere protocollen niet eens gebruiken.

In andere gevallen wil je echter complexere data versturen en/of meer devices kunnen aansturen, en dan heb je verschillende keuzes. Voor alle drie de hieronder genoemde opties geldt dat zowel de Raspberry Pi (eerst aanzetten), een Arduino, de BBC micro:bit en de ESP8266 er ondersteuning voor hebben.

SPI / Serial Peripheral Interface

De eerste optie voor is SPI of Serial Pheripheral Interface. Zoals uit de tabel al blijkt is dit het “snelste” van alle hier beschreven protocollen. Dus als er veel data over de lijn moet, bijvoorbeeld voor het aansturen van een ingewikkeld grafisch display of als er juist veel data ontvangen moet kunnen worden, dan is SPI daar geschikt voor.

Het vergt wel meer GPIO poorten: 3 + 1 voor elk aangesloten device (elke “slave”).
De aansluitingen voor SPI zijn (hier is bv de Raspberry Pi de “master” en een LCD-scherm de slave):

  • SCK  = dit is het clock signaal dat er voor zorgt dat de master en de slave op dezelfde snelheid (de bitrate) met elkaar communiceren. Anders begrijpen ze elkaar niet.
  • MOSI Master Out Slave In en is de verbinding waarmee de host met de slave communiceert
  • MISO = Master In Slave Out en is de verbdining waarmee de slave communiceert met de host
  • SS of CS =  Slave Select (SS) of Chip Select (CS) hiermee wordt aangegeven met welke slave de master wil communiceren.

De selectie voor een slave kan op twee manieren: de master kan één GPIO-pin per slave gebruiken of er kan een ketting van slaves opgebouwd worden. Zie ook de afbeeldingen van Wikipedia:

350px-SPI_three_slaves.svg 350px-SPI_three_slaves_daisy_chained.svg

Meer info over het gebruik van SPI voor verschillende platformen:

esp12 Node-MCU

 

I2C / Inter-Integrated Circuit

De tweede optie is I2C of I2C, daarom vaak uitgesproken als “I squared C”, “I two C” of “I-I-C”. Dit protocol is niet zo snel als SPI, maar je hebt slechts 2 kabels nodig, ook als je meerdere devices wilt koppelen:

  • SCL = dit is het clock signaal dat er voor zorgt dat de master en de slave op dezelfde snelheid (de bitrate) met elkaar communiceren. Anders begrijpen ze elkaar niet. Net als SCK bij SPI dus.
  • SDA = dit is de datalijn voor de communicatie tussen de master(s) en de slave(s). Nu dus niet aparte lijnen zoals bij SPI, maar 1 datalijn. De master(s) zorgen voor de coördinatie zodat maar 1 device tegelijkertijd aan het “praten” is.

Zoals je ziet staat hierboven “master(s)”. Anders dan bij SPI namelijk kan I2C overweg met meer dan één master (zie deze toelichting)

Je hebt dus minder kabels nodig bij I2C dan bij SPI, maar levert daarvoor wel snelheid in. Bij I2C heeft elk device een eigen identificatienummer zodat het device op de “bus” geadresseerd kan worden. Deze identificatie ligt vaak vast en als twee devices hetzelfde nummer hebben kun je ze niet samen op een I2C bus gebruiken.

UART / Universal Asynchronous Receiver / Transmitter

Last but not least: UART (Universal Asynchronous Receiver / Transmitter), een dure naam voor wat de ouderen onder ons gewoon kennen als een seriële poort. Je weet wel, dat ding waar je je computermuis op aansluit voordat er USB-muizen waren of zelfs PS/2 muizen. Overigens, voor wie het niet weet: USB = Universal Serial Bus = Universele Seriële Bus. USB is een stuk complexer (hogere snelheid, meerdere apparaten) en ga ik hier verder niet op in, UART wel omdat je ook die kunt gebruiken bij de apparaten waar we het eerder over hadden.

Voor de volledigheid ook nu de aansluitingen:

  • TX = wordt gebruikt door de master om data naar de slave te sturen
  • RX = wordt gebruikt door de slave om data naar de master te sturen

Als je een master en een slave op elkaar aansluit die UART ondersteunen, dan zullen beide apparaten een label TX en RX hebben. Let op! Je moet de TX van de master verbinden aan de RX van de slave en de TX van de slave gaat aan de RX van de master (stop en lees die zin nog even een keer!)

Om een master en slave via UART met elkaar te laten communiceren moeten ze een aantal dingen van elkaar weten:

  1. Hoeveel data bits worden er per keer verstuurd (5 tot 8)?
  2. Hoe snel worden de data verstuurd (baud rate)?
  3. Wordt er een “parity bit” (controle bit) aan het einde verstuurd en is dat een 1 of een 0?
  4. Hoeveel stopbits worden er aan het einde van een transmissie verstuurd?

Dit zijn zaken die je dus meestal in de code vooraf zult aangeven. Het voordeel van UART is dat het brede ondersteuning kent. Het is echter wel langzamer dan SPI en I2C en je kunt geen meerdere apparaten op dezelfde bus aansluiten.

Voorbeelden:

Let op!

Soms kan het zijn dat een device voor meerdere protocollen ondersteuning heeft. Dan kan het nog afhankelijk zijn van de driver. De RFID-RC522 RFID-scanner die ik hier getest en beschreven heb heeft, zie ook de afbeelding hieronder, zowel ondersteuning voor SPI, I2C als UART, maar de Arduino library die ik gebruikte heeft alleen ondersteuning voor SPI.

RFID-RC522-pinout

Soms zijn de pinnen voor een bepaald protocol niet altijd even eenvoudig te herkennen. Ik noemde al de ESP8266, ook bij de BBC micro:bit zitten ze goed verstopt:

microbit_pins

Maar als het goed is zou je nou voldoende moeten weten om een keuze te maken tussen GPIO, SPI, I2C en UART én moeten kunnen herkennen aan de labels bij de pins of in de documentatie welke opties een device heeft.