I2C Arduino - Master odosiela znaky na slave

Page

Stránky / Zbernice / I2C /

V tomto článku sa pozrieme na najzákladnejšiu možnú komunikáciu pomocou zbernice I2C medzi dvomi Arduinami. Toto je príklad, ku ktorému sa obvykle dostanete na ľubovoľných stránkach ku Arduinu. Bude pre nás slúžiť ako východiskový bod pre zložitejšie dátové štruktúry.

V tomto príklade prenesieme postupne znaky 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 z jedného Arduina na druhé. Medzi jednotlivými odoslaniami bude pauza 1 sekunda. Arduino ktoré bude znaky odosielať označíme ako Master. Arduino ktoré bude znaky prijímať označíme ako Slave.

Schéma

Základom je zapojiť Arduina podľa nasledovného obrázku. Treba prepojiť na oboch Arduinach SDA na pine A4 a SLC na pine A5. Obe linky treba pomocou pull-up rezistora prepojiť na +5 V. Okrem toho sa prepojí napájanie a GND.

Keďže ale budeme predpokladať, že sa s tým budete hrať na počítači a oba Arduina máte napojené cez USB, nie je potrebné napájanie a GND spájať, pretože sú už takto prepojené krížom cez PC. Okrem toho ich v takomto prípade asi prepojíte cez USB šnúru, ktorú si kupujeme k Arduinu a teda oba Arduina budú blízko pri sebe.

Počas experimentov môžete vynechať aj oba pull-up rezistory, pretože knižnica, ktorú používame v Arduine používa interné pull-up rezistory v Arduine, ktoré na túto komunikáciu stačia. To ale používajte iba počas experimentov. V reálnom nasadení použite vždy externé pull-up rezistory s hodnotami 10k alebo 4k7.

Master

Master potrebuje poznať adresu podriadeného Arduina. Tú máme uloženú v premennej SLAVE_ADDRESS. Príkazom Wire.beginTransmission(SLAVE_ADDRESS); spustíme prenos. Príkazom Wire.write(x); zapíšeme jeden znak. Pozor na to, že v tejto chvíli ešte komunikácia nenastala. Dáta sa iba zhromažďujú v internom bufferi. Príkazom Wire.endTransmission() ukončíme komunikáciu a v tomto okamihu sa aj údaje skutočne prenesú.

Dajte si pozor na to, ako sú znaky reprezentované v pamäti. Je rozdiel medzi znakom s hodnotou 0 a znakom '0', ktorý má hodnotu 48. V našom príklade používam to prvé.

#include <Wire.h>

const byte SLAVE_ADDRESS = 42;
const byte LED = 13;

void setup() 
  {
  Serial.begin(9600); 
  Serial.println("I2C Master 01");
  Wire.begin();
  pinMode(LED, OUTPUT);     
  }  // end of setup

void loop() 
  {
  for (byte x = 0; x < 10; x++)
    {
    Serial.print((int)x);
    Wire.beginTransmission(SLAVE_ADDRESS);
    Wire.write(x);
    if (Wire.endTransmission() == 0)
      {
      Serial.println(" OK");
      digitalWrite(LED, HIGH); 
      }
    else
      {
      Serial.println(" ERROR");
      digitalWrite(LED, LOW); 
      }
      
    delay(1000);
    }  // end of for loop
  }  // end of loop

Slave

Prvou úlohou je začať počúvať na linke. To urobíme pomocou príkazu Wire.begin(MY_ADDRESS);. A aby sme vedeli prichádzajúce znaky spracovať, musíme si pripojiť obslužnú funkciu príkazom Wire.onReceive(receiveEvent);. Keďže sa jedná o modelový príklad, prichádzajúce znaky skladujem v globálnej premennej b a z funkcie receiveEvent si len dávam signály do funkcie loop, pretože znaky sú zachytávané pomocou prerušenia.

#include <Wire.h>

const byte MY_ADDRESS = 42;
int how;
boolean signal=false;
byte b;

void setup() 
{
  Serial.begin(9600); 
  Serial.println("I2C Slave 01");
  Wire.begin(MY_ADDRESS);
  // set up receive handler
  Wire.onReceive(receiveEvent);
}  // end of setup

void loop() 
{
  if(signal)
  {
    Serial.print("how=");
    Serial.print(how);
    Serial.print(", b=");
    Serial.print(b);
    Serial.println("");
    signal=false;
  }
}

// called by interrupt service routine when incoming data arrives
void receiveEvent(int howMany)
{
  how=howMany;
  for (int i = 0; i < howMany; i++)
  {
    b = Wire.read();
  }  // end of for loop
  signal=true;
}  // end of receiveEvent


Download

01.09.2015


Menu