RP2350-Zero/I2C: Rozdiel medzi revíziami

Zo stránky 3D liga wiki
Prejsť na navigáciu Prejsť na vyhľadávanie
Sebastian (diskusia | príspevky)
Vytvorená stránka „== I2C == I2C (Inter-Integrated Circuit) je zbernica, cez ktorú vie doska komunikovať s viacerými zariadeniami pomocou iba dvoch vodičov: * '''SDA''' (Serial Data) – samotné dáta * '''SCL''' (Serial Clock) – hodinový signál, ktorý synchronizuje prenos Výhoda oproti napr. ultrazvuku (TRIG/ECHO) je, že na tie isté dva vodiče (SDA, SCL) sa dá pripojiť viacero zariadení naraz – každé má svoju vlastnú '''adresu''' (7-bitové číslo), podľa…“
 
Sebastian (diskusia | príspevky)
dBez shrnutí editace
Riadok 1: Riadok 1:
== I2C ==
== I2C ==


I2C (Inter-Integrated Circuit) je zbernica, cez ktorú vie doska komunikovať s viacerými zariadeniami pomocou iba dvoch vodičov:
I2C (Inter-Integrated Circuit) je sériová komunikačná zbernica, ktorá umožňuje jednému riadiacemu zariadeniu (master) komunikovať s viacerými periférnymi zariadeniami (slave) pomocou iba dvoch vodičov. Bežne sa s ňou stretneš pri pripájaní senzorov, displejov alebo iných modulov k mikrokontroléru.
* '''SDA''' (Serial Data) – samotné dáta
* '''SCL''' (Serial Clock) – hodinový signál, ktorý synchronizuje prenos


Výhoda oproti napr. ultrazvuku (TRIG/ECHO) je, že na tie isté dva vodiče (SDA, SCL) sa dá pripojiť viacero zariadení naraz – každé má svoju vlastnú '''adresu''' (7-bitové číslo), podľa ktorej ho doska osloví. RP2350 sa správa ako "master" (riadiace zariadenie), senzory ako "slave".
Hlavná výhoda I2C oproti riešeniam, kde má každé zariadenie svoje vlastné piny (napr. ultrazvukový senzor cez TRIG/ECHO), je, že na tie isté dva vodiče (SDA, SCL) sa dá pripojiť viacero zariadení naraz – každé má svoju vlastnú '''adresu''' (7-bitové číslo), podľa ktorej ho master osloví. Vďaka tomu netreba pre každé nové zariadenie obetovať ďalšie piny.


Vo väčšine breakout dosiek (aj BNO055, aj VL53L0X) sú potrebné pull-up rezistory na SDA/SCL už priamo na doštičke, takže netreba pridávať vlastné.
Vo väčšine breakout dosiek (aj BNO055, aj VL53L0X) sú navyše potrebné pull-up rezistory na SDA/SCL už priamo na doštičke, takže netreba pridávať vlastné.


=== Princip ===
=== Princíp ===
I2C komunikuje master spolu so slave zariadenim.
Kazde slave zariadenie ma adresu podla ktorej sa identifikuje.
Kazda adresa je v rozsahu 7 az 10 bitov (128 az 1024 adries).
- Master zariadenie si mozeme predstavit ako nase RP2350-zero.
- Slave (otrok) si mozeme predstavit VL53L0X laser distance senzor alebo gyroskop BNO055.
- Komunikuje pomocou dvoch kablov SDA a SCL.
-- SDA - prepojenie medzi mastrom a otrokom, cez ktore sa posielaju a prijimaju data.
-- SCL - prepojenie z mastera do otroka, cez ktore sa posiela casovy signal.


Master ako z nazvu vypliva bude riadit slave a to podla svojich hodiniek.  
I2C komunikuje master so slave zariadením. Každé slave zariadenie má adresu, podľa ktorej sa identifikuje. Adresa je zvyčajne 7-bitová (128 možných adries), voliteľne aj 10-bitová (1024 adries).
Podla tychto hodiniek posiela impulz a popri tom (podla hodiniek) posiela data cez SDA.  


Data sa posielaju cez spravy. Spravy sa skladaju:
* '''Master''' zariadenie si môžeme predstaviť ako naše RP2350-Zero.
- start bit
* '''Slave''' (podriadené zariadenie) si môžeme predstaviť ako VL53L0X (laserový senzor vzdialenosti) alebo gyroskop BNO055.
- end bit
* Komunikujú pomocou dvoch vodičov – SDA a SCL:
- adresa
** '''SDA''' (Serial Data) – samotné dáta, prenášané medzi masterom a slave zariadením
- citaci/zapisaovaci bit
** '''SCL''' (Serial Clock) – hodinový signál, ktorý synchronizuje prenos (generuje ho master)
- 2x 8-bitove ramy
- potvrdzujjuce bity (od otroka)


Master, ako už z názvu vyplýva, riadi komunikáciu podľa vlastného časovania – podľa hodinového signálu na SCL posiela impulzy, a súčasne s nimi posiela alebo číta dáta cez SDA.


Dáta sa posielajú vo forme správ, ktoré sa skladajú z:
* štart podmienky (start condition)
* adresy zariadenia
* read/write bitu
* jedného alebo viacerých 8-bitových rámov dát
* potvrdzujúcich bitov (ACK/NACK) po každom ráme
* stop podmienky (stop condition)


=== Posielanie dát ===
1. Na začiatku je SCL aj SDA v pokoji HIGH. Komunikácia začína tzv. '''štart podmienkou''': master zmení SDA z HIGH na LOW, zatiaľ čo SCL zostáva HIGH (práve táto kombinácia – zmena SDA počas HIGH na SCL – odlišuje štart podmienku od bežného prenosu dát, kde sa SDA mení iba keď je SCL LOW).
2. Master následne vyšle adresu zariadenia, s ktorým chce komunikovať.
3. Za adresou nasleduje read/write bit, ktorý určí, čo chce s daným zariadením robiť: ak chce dáta '''poslať''', bit = 0 (LOW); ak chce dáta '''prijať''' zo zariadenia, bit = 1 (HIGH).
4. Slave zariadenie odpovie potvrdzujúcim bitom (ACK/NACK): ak zariadenie s danou adresou existuje, '''stiahne SDA na LOW (ACK)'''. Ak žiadne zariadenie s takouto adresou neexistuje, nikto SDA nestiahne a linka zostane HIGH vďaka pull-up rezistoru ('''NACK'''), a master komunikáciu ukončí.
5. Ďalej sa posielajú 8-bitové rámy dát, každý nasledovaný potvrdzujúcim bitom od zariadenia, ktoré dáta prijíma. Bez ACK po ráme sa ďalší rám neposiela.
6. Nakoniec master ukončí komunikáciu tzv. '''stop podmienkou''': zmení SDA z LOW na HIGH, zatiaľ čo SCL zostáva HIGH.
Príklad tejto komunikácie medzi RP2350-Zero a VL53L0X v kóde:
<syntaxhighlight lang="cpp">
#include <Wire.h> // kniznica pre I2C komunikaciu
#include <VL53L0X.h>
VL53L0X sensor;
void setup() {
  Serial.begin(115200);
  Wire.setSDA(4);  // nastavenie datoveho pinu
  Wire.setSCL(5);  // nastavenie hodinoveho pinu
  Wire.begin();    // start podmienka pri kazdej komunikacii sa posle automaticky
  // RP2350 posle adresu (0x29) VL53L0X a chce od neho citat data (read/write bit = 1)
  if (!sensor.init()) { // ak zariadenie odpovie, stiahne SDA na LOW (ACK); ak nie, zostane HIGH (NACK)
    Serial.println("Senzor nenájdený!");
    while (1);  // ziadne zariadenie s touto adresou neodpovedalo
  }
  sensor.setTimeout(500);
  sensor.startContinuous(); // ACK prislo, mozu sa zacat posielat data
  Serial.println("VL53L0X OK");
}
void loop() {
  int dist = sensor.readRangeContinuousMillimeters(); // kniznica precita viacero 8-bitovych ramov, kazdy s ACK
  if (sensor.timeoutOccurred()) {
    Serial.println("Timeout!");
  } else {
    Serial.print("Vzdialenosť: ");
    Serial.print(dist);
    Serial.println(" mm");
  }
  delay(100);
  // po kazdej transakcii sa posle stop podmienka, ale kniznica hned zacne dalsiu - preto stale citame nove data
}
</syntaxhighlight>
'''Príklad – rovnaká komunikácia s BNO055'''
Rovnaký princíp, len iná adresa (0x28) a iná knižnica (Adafruit BNO055 + Adafruit Unified Sensor, obe cez Library Manager):
<syntaxhighlight lang="cpp">
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);
void setup() {
  Serial.begin(115200);
  Wire.setSDA(4);
  Wire.setSCL(5);
  Wire.begin();
  // RP2350 posle adresu (0x28) BNO055 a chce od neho citat data (read/write bit = 1)
  if (!bno.begin()) { // ak BNO055 odpovie, stiahne SDA na LOW (ACK); ak nie, zostane HIGH (NACK)
    Serial.println("BNO055 nenájdený!");
    while (1); // ziadne zariadenie s touto adresou neodpovedalo
  }
  delay(1000);
  bno.setExtCrystalUse(true);
  Serial.println("BNO055 OK");
}
void loop() {
  sensors_event_t event;
  bno.getEvent(&event); // kniznica poziada o registre a precita viacero 8-bitovych ramov, kazdy s ACK
  Serial.print("X: ");
  Serial.print(event.orientation.x);
  Serial.print("  Y: ");
  Serial.print(event.orientation.y);
  Serial.print("  Z: ");
  Serial.println(event.orientation.z);
  delay(200);
}
</syntaxhighlight>


'''Zariadenia v našej stavebnici'''
'''Zariadenia v našej stavebnici'''
Riadok 93: Riadok 182:


[[Category:RP2350-Zero]]
[[Category:RP2350-Zero]]
__notoc__

Verzia z 17:52, 3. september 2026

I2C

I2C (Inter-Integrated Circuit) je sériová komunikačná zbernica, ktorá umožňuje jednému riadiacemu zariadeniu (master) komunikovať s viacerými periférnymi zariadeniami (slave) pomocou iba dvoch vodičov. Bežne sa s ňou stretneš pri pripájaní senzorov, displejov alebo iných modulov k mikrokontroléru.

Hlavná výhoda I2C oproti riešeniam, kde má každé zariadenie svoje vlastné piny (napr. ultrazvukový senzor cez TRIG/ECHO), je, že na tie isté dva vodiče (SDA, SCL) sa dá pripojiť viacero zariadení naraz – každé má svoju vlastnú adresu (7-bitové číslo), podľa ktorej ho master osloví. Vďaka tomu netreba pre každé nové zariadenie obetovať ďalšie piny.

Vo väčšine breakout dosiek (aj BNO055, aj VL53L0X) sú navyše potrebné pull-up rezistory na SDA/SCL už priamo na doštičke, takže netreba pridávať vlastné.

Princíp

I2C komunikuje master so slave zariadením. Každé slave zariadenie má adresu, podľa ktorej sa identifikuje. Adresa je zvyčajne 7-bitová (128 možných adries), voliteľne aj 10-bitová (1024 adries).

  • Master zariadenie si môžeme predstaviť ako naše RP2350-Zero.
  • Slave (podriadené zariadenie) si môžeme predstaviť ako VL53L0X (laserový senzor vzdialenosti) alebo gyroskop BNO055.
  • Komunikujú pomocou dvoch vodičov – SDA a SCL:
    • SDA (Serial Data) – samotné dáta, prenášané medzi masterom a slave zariadením
    • SCL (Serial Clock) – hodinový signál, ktorý synchronizuje prenos (generuje ho master)

Master, ako už z názvu vyplýva, riadi komunikáciu podľa vlastného časovania – podľa hodinového signálu na SCL posiela impulzy, a súčasne s nimi posiela alebo číta dáta cez SDA.

Dáta sa posielajú vo forme správ, ktoré sa skladajú z:

  • štart podmienky (start condition)
  • adresy zariadenia
  • read/write bitu
  • jedného alebo viacerých 8-bitových rámov dát
  • potvrdzujúcich bitov (ACK/NACK) po každom ráme
  • stop podmienky (stop condition)

Posielanie dát

1. Na začiatku je SCL aj SDA v pokoji HIGH. Komunikácia začína tzv. štart podmienkou: master zmení SDA z HIGH na LOW, zatiaľ čo SCL zostáva HIGH (práve táto kombinácia – zmena SDA počas HIGH na SCL – odlišuje štart podmienku od bežného prenosu dát, kde sa SDA mení iba keď je SCL LOW).

2. Master následne vyšle adresu zariadenia, s ktorým chce komunikovať.

3. Za adresou nasleduje read/write bit, ktorý určí, čo chce s daným zariadením robiť: ak chce dáta poslať, bit = 0 (LOW); ak chce dáta prijať zo zariadenia, bit = 1 (HIGH).

4. Slave zariadenie odpovie potvrdzujúcim bitom (ACK/NACK): ak zariadenie s danou adresou existuje, stiahne SDA na LOW (ACK). Ak žiadne zariadenie s takouto adresou neexistuje, nikto SDA nestiahne a linka zostane HIGH vďaka pull-up rezistoru (NACK), a master komunikáciu ukončí.

5. Ďalej sa posielajú 8-bitové rámy dát, každý nasledovaný potvrdzujúcim bitom od zariadenia, ktoré dáta prijíma. Bez ACK po ráme sa ďalší rám neposiela.

6. Nakoniec master ukončí komunikáciu tzv. stop podmienkou: zmení SDA z LOW na HIGH, zatiaľ čo SCL zostáva HIGH.

Príklad tejto komunikácie medzi RP2350-Zero a VL53L0X v kóde:

#include <Wire.h> // kniznica pre I2C komunikaciu
#include <VL53L0X.h>

VL53L0X sensor;

void setup() {
  Serial.begin(115200);
  Wire.setSDA(4);  // nastavenie datoveho pinu
  Wire.setSCL(5);  // nastavenie hodinoveho pinu
  Wire.begin();    // start podmienka pri kazdej komunikacii sa posle automaticky

  // RP2350 posle adresu (0x29) VL53L0X a chce od neho citat data (read/write bit = 1)
  if (!sensor.init()) { // ak zariadenie odpovie, stiahne SDA na LOW (ACK); ak nie, zostane HIGH (NACK)
    Serial.println("Senzor nenájdený!");
    while (1);  // ziadne zariadenie s touto adresou neodpovedalo
  }
  sensor.setTimeout(500);
  sensor.startContinuous(); // ACK prislo, mozu sa zacat posielat data
  Serial.println("VL53L0X OK");
}

void loop() {
  int dist = sensor.readRangeContinuousMillimeters(); // kniznica precita viacero 8-bitovych ramov, kazdy s ACK
  if (sensor.timeoutOccurred()) {
    Serial.println("Timeout!");
  } else {
    Serial.print("Vzdialenosť: ");
    Serial.print(dist);
    Serial.println(" mm");
  }
  delay(100);
  // po kazdej transakcii sa posle stop podmienka, ale kniznica hned zacne dalsiu - preto stale citame nove data
}

Príklad – rovnaká komunikácia s BNO055

Rovnaký princíp, len iná adresa (0x28) a iná knižnica (Adafruit BNO055 + Adafruit Unified Sensor, obe cez Library Manager):

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>

Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28);

void setup() {
  Serial.begin(115200);
  Wire.setSDA(4);
  Wire.setSCL(5);
  Wire.begin();

  // RP2350 posle adresu (0x28) BNO055 a chce od neho citat data (read/write bit = 1)
  if (!bno.begin()) { // ak BNO055 odpovie, stiahne SDA na LOW (ACK); ak nie, zostane HIGH (NACK)
    Serial.println("BNO055 nenájdený!");
    while (1); // ziadne zariadenie s touto adresou neodpovedalo
  }

  delay(1000);
  bno.setExtCrystalUse(true);
  Serial.println("BNO055 OK");
}

void loop() {
  sensors_event_t event;
  bno.getEvent(&event); // kniznica poziada o registre a precita viacero 8-bitovych ramov, kazdy s ACK

  Serial.print("X: ");
  Serial.print(event.orientation.x);
  Serial.print("  Y: ");
  Serial.print(event.orientation.y);
  Serial.print("  Z: ");
  Serial.println(event.orientation.z);

  delay(200);
}

Zariadenia v našej stavebnici

Zariadenie Čo meria Predvolená I2C adresa
BNO055 Gyroskop / akcelerometer / kompas (9-DOF IMU) 0x28
VL53L0X Laserový senzor vzdialenosti (Time-of-Flight) 0x29

Keďže majú tieto dve zariadenia rôzne adresy, dajú sa obe pripojiť na tú istú I2C zbernicu súčasne bez konfliktu.

Poznámka: konkrétne GPIO piny pre SDA/SCL si over v pinoute RP2350-Zero – v príkladoch nižšie použijeme GPIO0 (SDA) a GPIO1 (SCL), keďže sú v našej stavebnici zatiaľ voľné, ale dajú sa nastaviť aj inak.

I2C skener (test zapojenia)

Skôr než skúšaš konkrétny senzor, oplatí sa overiť, či ho doska na zbernici vôbec "vidí". Na to slúži klasický I2C skener – prejde všetky možné adresy a vypíše, na ktorých našiel odpoveď:

#include <Wire.h>

const int PIN_SDA = 0;
const int PIN_SCL = 1;

void setup() {
  Wire.setSDA(PIN_SDA);
  Wire.setSCL(PIN_SCL);
  Wire.begin();

  Serial.begin(115200);
  delay(1000);
  Serial.println("I2C skener spusteny...");
}

void loop() {
  byte pocetNajdenych = 0;

  for (byte adresa = 1; adresa < 127; adresa++) {
    Wire.beginTransmission(adresa);
    byte chyba = Wire.endTransmission();

    if (chyba == 0) {
      Serial.print("Zariadenie najdene na adrese 0x");
      if (adresa < 16) Serial.print("0");
      Serial.println(adresa, HEX);
      pocetNajdenych++;
    }
  }

  if (pocetNajdenych == 0) {
    Serial.println("Ziadne I2C zariadenie nenajdene.");
  }

  delay(3000);
}

Ak sa objaví 0x28, je zapojený BNO055. Ak 0x29, je zapojený VL53L0X. Ak sa nezobrazí nič, skontroluj zapojenie SDA/SCL/VCC/GND.