I2C Communications Part 1-Arduino till Arduino

introduktion

I2C communications har blivit de facto-metoden för att kommunicera mellan mikrokontroller, mikrodatorer och en mängd integrerade kretsar och sensorer. Det har funnits sedan 1982 och utvecklades ursprungligen för användning i TV-mottagare.

Även om vi har använt många I2C-sensorer och skärmar i tidigare artiklar har vi faktiskt inte tittat på hur I2C fungerar och hur det kan användas för att kommunicera mellan mikrokontroller.

idag kommer vi att korrigera det och lära oss mer om I2C. vi får också se hur det kan användas för att utbyta information mellan två Arduinos och hur det kan användas för att låta en Arduino styra en annan.

I2C Part 1-med 2 Arduinos

detta kommer att vara den första av fyra artiklar om I2C. i framtida artiklar kommer vi att se hur vi kan bygga våra egna I2C-enheter, hur man gränssnitt en Raspberry Pi och en Arduino med I2C och hur man gör några avancerade I2C-konfigurationer, inklusive att använda flera mästare på en I2C-buss.

Låt oss komma igång!

I2C Communications

I2C är ett seriellt protokoll som används på ett 2-tråds gränssnitt med låg hastighet. Det utvecklades ursprungligen av Phillips 1982 för att tillåta integrerade kretsar inom TV-mottagare att kommunicera med varandra.

tiderna har förändrats, Phillips är nu NXP och I2C har blivit en kommunikationsstandard som stöds av praktiskt taget alla större halvledartillverkare.

I2C är en förkortning för”Inter-Integrated Circuit”. Det kallas också” IIC”eller” i squared C”.

användningar och begränsningar

I2C används med mikrokontroller som Arduino och med mikrodatorer som Raspberry Pi. Många skärmar och sensorer gränssnitt till sin värd controller med hjälp av I2C.

I2C har flera begränsningar dock. Det är inte särskilt snabbt, men för de flesta av dess avsedda användningsområden är det tillräckligt snabbt.

I2C kan bara användas över korta avstånd, trots allt var det ursprungligen tänkt att kommunicera mellan integrerade kretsar på samma kretskort. Det maximala avståndet för pålitlig överföring minskar när hastigheten ökar, vid den långsammaste hastigheten (100 Kbaud eller en klockfrekvens på 100 KHz) är det maximala avståndet cirka en meter.

I2C-hastigheter

den ursprungliga I2C-bussen hade en maximal hastighet på 100 KHz. De vanligaste applikationerna använder fortfarande denna hastighet, eftersom det är tillräckligt för att överföra data från sensorer och till enkla skärmar.

I2C och har några högre hastighetslägen. Inte alla I2C-enheter stöder dessa lägen:

  • snabbläge – detta har en maximal klockhastighet på 400 KHz.
  • Hi-Speed Mode – en maximal klockfrekvens fo 3.4 MHz
  • Ultrasnabbläge – maximal klockfrekvens på 5 MHz

på en I2C-buss är det befälhavaren som bestämmer klockhastigheten.

hur I2C fungerar

en I2C-buss har två signaler, tillsammans med en ström-och jordanslutning.

I2C Bus Communications

de två signallinjerna är följande:

  • SDA – detta är den dubbelriktade datalinjen.
  • SCL – detta är klocksignalen.

det finns två dragmotstånd kopplade till varje signallinje, de drar bussen upp till matningsspänningen när den är inaktiv.

Observera att matningsspänningen inte är standard, den kan vara antingen 3,3 eller 5 volt. Det kan också vara en lägre spänning för vissa höghastighets I2C-implementeringar.

denna skillnad i matningsspänningar kan orsaka problem när du ansluter I2C-enheter som använder olika logiska nivåer. Vi kommer att diskutera detta mer i en framtida artikel när jag visar dig hur man gränssnitt en Raspberry Pi (3.3-volts logik) med en Arduino Uno (5-volts logik).

det finns två typer av enheter som kan kopplas till I2C – bussen-mästare och slavar.

huvudenheten styr bussen och levererar klocksignalen. Den begär data från slavarna individuellt. Det kan finnas mer än en huvudenhet på bussen men endast en kan vara den aktiva befälhavaren vid varje givet ögonblick.

masterenheterna har ingen adress tilldelad dem.

slavenheter har en adress, och den här adressen måste vara unik på bussen. De använder ett 7-bitars adresseringssystem, så upp till 128 slavar kan vara på en I2C-buss. I verkligheten används denna stora samling enheter aldrig, det är sällsynt att se över ett dussin I2C-enheter på en buss.

ett nyare 10-bitars adresseringsschema har implementerats, det är bakåtkompatibelt med den befintliga 7-bitars adresseringsmetoden.

kommersiella I2C-enheter tilldelas I2C-adress av NXP, som upprätthåller bussspecifikationerna. Även om I2C har varit öppen källkod sedan 2006 debiteras en avgift för att få en Slavadress från NXP. Ingen avgift krävs för master-enheter eller för enheter som inte är avsedda för kommersiell tillverkning.

vissa I2C-enheter tilldelas flera adresser, vanligtvis avvikelser i de nedre adressbitarna. Dessa enheter kan konfigureras manuellt för olika adresser, vilket gör att flera enheter av samma typ kan användas på en enda I2C-buss.

andra I2C-derivat

det finns andra bussar som har härletts från I2C-bussen och som på många sätt är kompatibla med I2C.

  • TWI – Tvillingtrådsgränssnittet är praktiskt taget identiskt med I2C-bussen. Detta är faktiskt bussen som Arduino använder, TWI utvecklades när I2C-bussen inte var öppen källkod och Atmel inte ville riskera ett brott mot handelsnamnet. Den enda stora skillnaden mellan TWI och I2C är att TWI inte stöder en avancerad teknik som kallas ”klocksträckning”.
  • SMBus är en annan I2C-ekvivalent buss, utvecklad av Intel. Liksom TWI stöder de flesta I2C-funktioner.

i en framtida artikel kommer jag att förklara hur data på I2C-bussen är strukturerad. Men nu har vi lite grundläggande I2C-information, tillräckligt för att börja experimentera.

Arduino Wire Library

Arduino har ett inbyggt bibliotek för att arbeta med I2C som heter Wire Library. Det gör det väldigt enkelt att kommunicera på I2C-bussen, och det kan konfigurera Arduino att bli antingen en mästare eller en slav.

Trådbiblioteket har flera användbara funktioner för att arbeta med I2C.

  • begin() – detta initierar biblioteket och ställer in Arduino att vara antingen master eller slav.
  • requestfrån() – denna funktion används av befälhavaren för att begära data från en slav.
  • beginTransmission() – denna funktion används av befälhavaren för att skicka data till en angiven Slav.
  • endTransmission() – denna funktion används av befälhavaren för att avsluta en överföring som startas med beginTransmission-funktionen.
  • skriv() – används av både master och slave för att skicka data på I2C-bussen.
  • tillgänglig() – används av både master och slave för att bestämma antalet byte i de data de tar emot.
  • läs() – läser en byte av data från I2C-bussen.
  • SetClock() – används av befälhavaren för att ställa in en specifik klockfrekvens.
  • onReceive() – används av slaven för att ange en funktion som kallas när data tas emot från master.
  • onRequest() – används av slaven för att ange en funktion som anropas när befälhavaren har begärt data.

Vi kommer att använda några av dessa funktioner i våra skisser.

Arduino I2C-anslutningar

SDA-och SCL-anslutningarna för I2C skiljer sig mellan Arduino-modellerna. Experimenten jag ska visa dig gjordes med två Arduino Unos, men du kan använda andra modeller av Arduino förutsatt att du ändrar stiften i enlighet därmed.

Jag har sammanställt ett diagram för att hjälpa dig att få det räknat ut. Den innehåller några vanliga Arduino styrelser, liksom några av de diskreta marker. Pinouts för chips i list (ATTiny och ATmega328P) är med DIP-paketet, inte de ytmonterade.

Arduino Board or Chip SDA SCL
Uno A4 A5
Mega2560 20 21
Nano A4 A5
Pro Mini A4 A5
Leonardo 2 3
Due (has two I2C) 20 + SDA1 20 + SCL1
ATTiny85 & ATTiny45 5 7
ATmega328P 27 28

vissa Arduino Uno-kloner har separata SDA-och SCL-stift och du kan använda dem istället för de två analoga stiften om du vill. De är internt anslutna till samma plats.

Observera att Arduino Due faktiskt har två I2C-portar.

också, vara medveten om att det finns några felaktiga hookup diagram på internet för Pro Mini. Använd de två analoga stiften, A4 och A5, som visas i tabellen ovan.

I2C mellan 2 Arduino ’ s

för vårt första experiment kommer vi att hoo två Arduinos tillsammans och utbyta data mellan dem. En Arduino kommer att vara mästaren, den andra kommer att vara slaven.

Jag använder två Arduino Unos, men du kan ersätta andra Arduino om du inte har två Unos. Använd föregående diagram för anslutningarna.

ansluter 2 Arduino ’ s

Så här kopplade jag mina två Arduino Unos tillsammans:

I2C Arduino till Arduino

det är en ganska enkel anslutning, i huvudsak knyter du bara marken och de två I2C-stiften tillsammans.

en sak att vara medveten om är att mitt diagram inte visar användningen av dragmotstånd, jag fann att allt verkade fungera korrekt utan dem. Du kanske dock vill inkludera dem, särskilt om du upplever fel eller intermittent drift.

att koppla upp några pull-up motstånd attache ett par 10K motstånd till SDA och SCL linjer. Fäst den andra änden på 5-voltsutgången på en av Arduino.

Master Demo Sketch

här är skissen som kommer att användas på Arduino som du har utsett som master.

I2C Master Demo

1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
33
34
35
36
37
38
39
40
41
42
44
45
46
47
48
49
50
51
52
53

/*
I2C Master Demo
I2C-Master-Demo.ino
Demonstrate use of I2C bus
Master sends character and gets reply from Slave
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// Define Slave I2C Address
#define SLAVE_ADDR 9
// Define Slave answer size
#define ANSWERSIZE 5
void setup() {
// Initialize I2C communications as Master
Wire.begin();
/ / Setup seriell bildskärm
seriell.börja (9600);
seriell.println (”I2C Master Demonstration”);
}
void loop () {
fördröjning(50);
seriell.println (”skriv data till slav”);
// Skriv en charatre till slaven
tråd.beginTransmission (SLAVE_ADDR);
tråd.skriv (0);
tråd.endTransmission ();
seriell.println (”ta emot data”);
// Läs svar från Slav
// Läs tillbaka 5 tecken
tråd.förfrågan från (SLAVE_ADDR, ANSWERSIZE);
/ /Lägg till tecken till sträng
Strängrespons=””;
medan (tråd.tillgänglig ()) {
röding b = tråd.läs ();
svar += b;
}
// Skriv ut till seriell bildskärm
seriell.println (svar);
}

som med alla I2C-skisser börjar vi med att inkludera Trådbiblioteket.

därefter definierar vi några konstanter för att representera slavens I2C-adress och antalet byte av data som vi förväntar oss att hämta från den.

i installationen initierar vi I2C-kommunikationen som en mästare. Vi vet att det är en mästare eftersom det inte finns någon adressparameter i begin-funktionen. Vi ställer också in en seriell bildskärm och skriver ut en textrad till den.

nu till slingan.

vi börjar med en liten tidsfördröjning, mestadels för att sakta ner saker tillräckligt så att vi kan läsa skärmen på seriemonitorn.

Nästa använder vi funktionen beginTransmission för att skicka data till slaven. I det här fallet är de data vi skickar bara ett nummer noll. Vi slutar skicka med ett samtal till slutetöverföringsfunktion.

nästa begär vi några data tillbaka från slaven med funktionen requestFrom.

därefter formulerar vi en svarsträng genom att läsa data, en byte åt gången, från slaven.

vi skriver ut detaljerna om vad vi gör och om de data vi får till seriemonitorn. Och sedan avslutar vi slingan och gör det igen.

Slave Demo Sketch

Nu på skissen som används av slaven.

I2C Slavdemo

1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
33
34
35
36
37
38
39
40
41
42
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

/*
I2C Slave Demo
i2c-slave-demo.ino
Demonstrate use of I2C bus
Slave receives character from Master and responds
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// definiera Slav I2C adress
#definiera SLAVE_ADDR 9
// definiera Slav svar storlek
#definiera SVARSTORLEK 5
// definiera sträng med svar på Master
sträng svar = ”Hej”;
Void setup() {
// initiera I2C-kommunikation som slav
tråd.börja (SLAVE_ADDR);
// funktion för att köra när data begärs från master
tråd.onRequest (requestEvent);
// funktion för att köra när data tas emot från master
tråd.onReceive (receiveEvent);
/ / Setup seriell bildskärm
seriell.börja (9600);
seriell.println (”I2C Slav Demonstration”);
}
void receiveEvent () {
// Läs medan data mottagna
medan (0 < tråd.tillgänglig ()) {
byte x = tråd.läs ();
}
// Skriv ut till seriell bildskärm
seriell.println (”ta emot händelse”);
}
void requestEvent () {
/ /Setup byte variabel i rätt storlek
byte svar;
/ /formatera svaret som array
för (byte i=0;i<ANSWERSIZE;i++) {
svar = (byte)svar.charAt(i);
}
// Skicka svar tillbaka till Master
tråd.skriv (svar, storlekof (svar));
// Skriv ut till seriell bildskärm
seriell.println(”begär händelse”);
}
void loop() {
// tidsfördröjning i loop
fördröjning(50);

återigen börjar vi med att inkludera trådbiblioteket. Som med föregående skiss definierar vi också I2C-adressen för slaven, liksom antalet byte vi planerar att skicka tillbaka till befälhavaren.

därefter definierar vi strängen som vi ska skicka tillbaka till befälhavaren, i det här fallet bara ordet ”Hej”. Om du bestämmer dig för att ändra detta, se till att du justerar ANSWERSIZE-konstanten i båda skisserna för att vara korrekt.

i installationen initierar vi anslutningen till I2C-bussen med en begin-funktion. Notera det olika sättet vi gör detta, eftersom det här är en slav anger vi I2C-adressen vi ska använda. Genom att göra detta vet Trådbiblioteket att vi vill arbeta i slavläge.

Nu måste vi definiera namnen på de funktioner som vi kommer att ringa när två händelser inträffar – en dataförfrågan mottagen från master och data mottagen från master. Vi ställer också in och skriver ut till seriell bildskärm.

funktionen receivehändelse kallas när vi tar emot data från befälhavaren. I den här funktionen läser vi data medan data är tillgängliga och tilldelar den till en byte (kom ihåg att data kommer att tas emot en byte åt gången).

funktionen requestEvent anropas när vi får en begäran om data från master. Vi måste skicka vår sträng ” hej ” tillbaka till befälhavaren. Eftersom vi behöver skicka data en byte åt gången delar vi tecknen i ”Hej” i enskilda objekt i en array och skickar dem sedan en efter en.

Vi rapporterar alla våra framsteg i båda funktionerna till seriemonitorn.

slingan i denna skiss lägger bara till en tidsfördröjning, som matchar den som används i huvudskissen.

kör Demoskisserna

för att köra dessa skisser måste du kunna se seriell bildskärm på varje Arduino. Om du har två datorer med Arduino IDE installerat så kommer det att göra det mycket enklare.

I2C Experiment 1

på Microsoft Windows är det möjligt att öppna två instanser av Arduino IDE. Om det är gjort kan du visa båda seriella bildskärmar sida vid sida på samma skärm.

Alternativt kan du använda en dator och driva upp den andra Arduino med egen strömförsörjning. Du måste byta dator och ström mellan de två Arduino. genom att göra detta kan du övervaka båda skärmarna en efter en.

Arduino Remote med I2C

i nästa demonstration kommer vi att koppla en potentiometer till master Arduino och en LED till slaven. Vi kommer att använda potentiometern för att styra blinkningshastigheten för lysdioden.

detta är en annan enkel demonstration, du kan bygga vidare på den för att skapa något mer praktiskt.

Remote Demo Hookup

Här är hur detta experiment sätts ihop.

I2C Arduino Control

det är i huvudsak samma anslutning som föregående experiment, med tillägg av potentiometern på master och LED på slaven.

Observera att lysdioden på slaven har fästs på stift 13. Eftersom Arduino Uno har en inbyggd LED på stift 13 kan du eliminera LED och dess droppmotstånd om du vill.

anmärkningarna om pull-up motstånd gäller även för denna hookup.

Remote Demo Master Sketch

skissen för mastersidan av detta experiment är mycket enkel, på vissa sätt är I2C-sidan ännu enklare än den som användes i den första demonstrationen. Detta beror på att vi bara skickar data till slaven och inte förväntar oss att få någon tillbaka.

I2C Master med Potentiometer

1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
33
34
35
36
37
38
39
40

/*
I2C Master Control Demo
I2C-Master-Demo-kontroll.ino
Demonstrate use of I2C bus
Master sends potentimeter position data
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// Define Slave I2C Address
#define SLAVE_ADDR 9
// Analog pin for potentiometer
int analogPin = 0;
// Integer to hold potentiometer value
int val = 0;
void setup () {
/ /initiera I2C-kommunikation som Master
tråd.börja();
}
void loop () {
fördröjning (50);
/ / Läs pottvärde
/ / karta till intervallet 1-255 för flashhastighet
val = karta(analogRead (analogPin), 0, 1023, 255, 1);
/ / Skriv en charatre till slaven
tråd.beginTransmission (SLAVE_ADDR);
tråd.skriv (val);
tråd.endTransmission();
}

som alltid måste vi inkludera Trådbiblioteket i början av skissen. Vi kommer också att definiera en konstant för att hålla slavadressen.

eftersom vi använder en potentiometer måste vi definiera både stiftet den är ansluten till och en variabel för att hålla dess värde.

allt vi gör i installationen är att initiera I2C-anslutningen som en master.

i slingan läser vi potentiometervärdet och kartlägger det till ett intervall på 01-255. Vi måste göra det eftersom vi skickar en byte av information och bara kan hålla så många värden i en enda byte.

Observera att vi vänder numreringssekvensen i Arduino – kartfunktionen, detta görs så att systemet beter sig som vi förväntar oss-att vrida potentiometern åt höger ökar blixthastigheten. Eftersom ”flash rate” anges av en tidsfördröjning kommer ett större antal som skickas att motsvara en längre flash rate.

Observera också att vi inte skickar värdet 0, vilket bara skulle hålla lysdioden i ett tillstånd. Vi sätter vårt sortiment till slut på 1 istället.

Nu handlar det bara om att skicka byte till slaven och upprepa slingan igen.

Remote Demo Receive Sketch

slavsidan måste ta emot data från befälhavaren och använda den för att blinka lysdioden.

I2C slav med LED

1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
33
34
35
36
37
38
39
40
41
42
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

/*
I2C Slav kontroll demo
I2C-Slav-demo-kontroll.ino
Demonstrate use of I2C bus
Receives potentimeter position data
Controls LED blink rate
DroneBot Workshop 2019
https://dronebotworkshop.com
*/
// Include Arduino Wire library for I2C
#include <Wire.h>
// Define Slave I2C Address
#define SLAVE_ADDR 9
// Define LED Pin
int LED = 13;
// Variable for received data
int rd;
// Variable for blink rate
int br;
void setup () {
pinMode(LED, utgång);
/ /initiera I2C-kommunikation som slav
tråd.börja (SLAVE_ADDR);
// funktion för att köra när data tas emot från master
tråd.onReceive (receiveEvent);
// Setup Serial Monitor
seriell.börja (9600);
seriell.println(”I2C Slavdemonstration”);
}
void receiveEvent() {
// läs ett tecken från I2C
rd = tråd.läs ();
// utskriftsvärde för inkommande data
seriell.println (rd);
}
tomgångsslinga () {
fördröjning (50);
/ / beräkna blinkvärde
br = karta (rd, 1, 255, 100, 2000);
digitalWrite(LED, hög);
fördröjning(br);
digitalWrite(LED, låg);
fördröjning(br);
}

vi börjar med det vanliga införandet av trådbiblioteket, liksom att definiera slavadressen. Vi definierar också en stift för LED.

ett par ytterligare variabler definieras, en håller den mottagna data medan den andra bär tidsfördröjningsvärdet för blinkhastigheten.

i inställningen ställer vi in i/O-stiftet för LED som en utgång och initierar I2C-bussen. När vi använder slavadressen i begin-funktionen vet Trådbiblioteket att vi agerar som slav.

vi behöver bara definiera en onReceive-funktion, till skillnad från den senaste demoen förväntar vi oss inga förfrågningar från befälhavaren. Vi ställer också in och skriver ut till seriell bildskärm, vi använder bildskärmen för att visa inkommande data.

receiveEvent-funktionen läser inkommande data och tilldelar den till i-variabeln. Det skriver också ut värdet till seriell bildskärm.

slutligen, i slingan använder vi inkommande data för att blinka lysdioden. Återigen använder vi kartfunktionen för att uppnå detta och ändrar inkommande värden på 1-255 till ett större intervall. Du kan experimentera med att ändra detta intervall för att få LED-lampan att blinka snabbare eller långsammare om du vill.

de sista uttalandena är i huvudsak Arduino Blink skissen i förklädnad! Vi slår på och stänger av lysdioden under en tidsperiod som vi bestämde i det sista steget.

och sedan upprepar vi slingan.

kör Fjärrdemonstrationen

ladda koden och ström båda Arduino s. Du kan använda din seriella bildskärm på Slav Arduino för att visa inkommande data.

I2C Experiment 2

att vrida potentiometern bör nu variera LED-blinkningshastigheten på slaven.

slutsats

detta avslutar vår första detaljerade titt på I2C. i nästa del kommer vi att lära oss mer om strukturen för de data som utbyts. Vi tar också en vanlig sensor och gör den till en I2C-sensor.

Glad kommunikation!

resurser

skisser – alla I2C-skisser som används i den här artikeln.

I2C information – Information om I2C – protokollet

I2C Communications Part 1 – Arduino till Arduino
sammanfattning
I2C communications Part 1 - Arduino till Arduino
Artikelnamn
I2C communications Part 1-Arduino till Arduino
beskrivning
i den här första delen av en serie artiklar om I2C lär du dig vad I2C är. Du ser också hur Arduino Wire library gör kommunikation över I2C mycket enkel.
författare
DroneBot Workshop
Utgivare namn
DroneBot Workshop
DroneBot Workshop

taggade på: Arduino Tutorial

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *