Pe scurt comunicarea se face pe 2 "fire": SDA (A4 la Arduino Uno) si SCL (A5 la Arduino Uno), necesitand si firul de masa (GND).
In mod normal, cele 2 "fire" se conecteaza la plus (5V) prin rezistente de 1..10kohmi, dar pentru o placa Master (stapan) si una Slave (sclav), pot lipsi, cum am facut eu in montajul de test.
Sursa de inspiratie a fost articolul Comunicarea i2c de pe site-ul roroid, care are schema de conexiuni pentru teste:
Eu voi folosi placuta (brick, shield/semishield) cu un LED multicolor si 3 rezistente, cu conector pentru zona digitala D8...D13 si GND
Schema mea de testare are doar 4 fire, plus 5V, masa (GND), SDA(A4) si SCL(A5); ea permite alimentarea din cablul USB folosit la una din placi:
Pentru inceput, am adaptat sketch-urile din articolul mentionat mai sus, schimband doar partea de conectare a led-ului de la pinul D8 la D8 cum are placuta mea.
Ulterior, am modificat sketch-urile pentru a comanda cele 3 led-uri componente ale led-ului multicolor, obtinand:
Sketch-urile pentru comanda celor 3 led-uri sunt:
- sketch-ul pentru "master" (stapan):
Ulterior, am modificat sketch-urile pentru a comanda cele 3 led-uri componente ale led-ului multicolor, obtinand:
- sketch-ul pentru "master" (stapan):
// MASTER ver1
// sketch de inspiratie de la http://www.roroid.ro/comunicarea-i2c/
// sketch adaptat pentru led multicolor de niq_ro de la http://nicuflorica.blogspot.ro/
// si http://arduinotehniq.blogspot.com/
//se incarca biblioteca pentru comunicarea pe I2C
#include <Wire.h>
void setup()
{
// initializeaza bus pentru i2c
Wire.begin();
Serial.begin(9600);
}
void loop()
{
Serial.println("MASTER:Toate LED-urile stinse");
Wire.beginTransmission(4); // transmit dispozitivului de la adresa #4
//in functie de cate dispozitive aveti legate pe I2C acest numar variaza
//comenzile de mai jos comanda ledurile de pe pinii 9, 10 si 11
//comenzile sunt de formatul LPPS; unde L- inseamna LED;PP-reprezinta numarul pinului;S-inseamna starea pinului
//Ex. L100;-va stinge ledul de pe pinul 10;L081 va aprinde ledul de pe pinul8
//L100;L081;-va stinge ledul de pe pinul 10 si aprinde ledul de pe pinul 8 concomitent.
Wire.write("L09"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L10"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L11"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.requestFrom(4, 15); // se citesc 15 biti de raspuns de la dispozitivul
//de pe adresa 4
while(Wire.available()) //atata timp cat se primeste ceva
{
char c = Wire.read();
Serial.print(c); // tipareste caracterele primite
}
Serial.println("");
Wire.endTransmission(); // intrerupe transmisia
delay(2000); //asteptam un pic dupa care reluam cu 0
Serial.println("MASTER:Aprind LED-ul 1");
Wire.beginTransmission(4); // transmit dispozitivului de la adresa #4
//in functie de cate dispozitive aveti legate pe I2C acest numar variaza
//comenzile de mai jos comanda ledurile de pe pinii 9, 10 si 11
//comenzile sunt de formatul LPPS; unde L- inseamna LED;PP-reprezinta numarul pinului;S-inseamna starea pinului
//Ex. L100;-va stinge ledul de pe pinul 10;L081 va aprinde ledul de pe pinul8
//L100;L081;-va stinge ledul de pe pinul 10 si aprinde ledul de pe pinul 8 concomitent.
Wire.write("L09"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("1"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L10"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L11"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.requestFrom(4, 15); // se citesc 15 biti de raspuns de la dispozitivul
//de pe adresa 4
while(Wire.available()) //atata timp cat se primeste ceva
{
char c = Wire.read();
Serial.print(c); // tipareste caracterele primite
}
Serial.println("");
Wire.endTransmission(); // intrerupe transmisia
delay(2000); //asteptam un pic dupa care reluam cu 0
Serial.println("MASTER:Aprind LED-ul 2");
Wire.beginTransmission(4); // transmit dispozitivului de la adresa #4
//in functie de cate dispozitive aveti legate pe I2C acest numar variaza
//comenzile de mai jos comanda ledurile de pe pinii 9, 10 si 11
//comenzile sunt de formatul LPPS; unde L- inseamna LED;PP-reprezinta numarul pinului;S-inseamna starea pinului
//Ex. L100;-va stinge ledul de pe pinul 10;L081 va aprinde ledul de pe pinul8
//L100;L081;-va stinge ledul de pe pinul 10 si aprinde ledul de pe pinul 8 concomitent.
Wire.write("L09"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L10"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("1"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L11"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.requestFrom(4, 15); // se citesc 15 biti de raspuns de la dispozitivul
//de pe adresa 4
while(Wire.available()) //atata timp cat se primeste ceva
{
char c = Wire.read();
Serial.print(c); // tipareste caracterele primite
}
Serial.println("");
Wire.endTransmission(); // intrerupe transmisia
delay(2000); //asteptam un pic dupa care reluam cu 0
Serial.println("MASTER:Aprind LED-ul 3");
Wire.beginTransmission(4); // transmit dispozitivului de la adresa #4
//in functie de cate dispozitive aveti legate pe I2C acest numar variaza
//comenzile de mai jos comanda ledurile de pe pinii 9, 10 si 11
//comenzile sunt de formatul LPPS; unde L- inseamna LED;PP-reprezinta numarul pinului;S-inseamna starea pinului
//Ex. L100;-va stinge ledul de pe pinul 10;L081 va aprinde ledul de pe pinul8
//L100;L081;-va stinge ledul de pe pinul 10 si aprinde ledul de pe pinul 8 concomitent.
Wire.write("L09"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L10"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("0"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.write("L11"); // trimite numarul ledului care sa fie aprins/stins
Wire.write("1"); // trimite starea acestuia
Wire.write(";"); // trimite separator
Wire.requestFrom(4, 15); // se citesc 15 biti de raspuns de la dispozitivul
//de pe adresa 4
while(Wire.available()) //atata timp cat se primeste ceva
{
char c = Wire.read();
Serial.print(c); // tipareste caracterele primite
}
Serial.println("");
Wire.endTransmission(); // intrerupe transmisia
delay(2000); //asteptam un pic dupa care reluam cu 0
}
- sketch-ul pentru "slave" (sclav):// SLAVE ver.1
// sketch de inspiratie de la http://www.roroid.ro/comunicarea-i2c/
// sketch adaptat pentru led multicolor de niq_ro de la http://nicuflorica.blogspot.ro/
// si http://arduinotehniq.blogspot.com/
//se incarca biblioteca pentru comunicarea pe I2C
#include <Wire.h>
int LED[] = {99,4,5,6,7,8,9,10,11,12,13};//se definesc pinii pe care sunt conectate LED-urile
char comanda[15]; //vectorul in care va fi receptionata comanda pe I2c
char *i;
String p="";
void setup()
{
Serial.begin(9600);
for(int i = 0; i <= 10; i++){
pinMode(LED[i],OUTPUT);//initializeaza toti pini pe care sunt legate leduri ca output
}
Wire.begin(4);//suntem dispozitivul de la adresa #4
Wire.onReceive(receptie);//datele primite pe i2c le interpretam in functia receptie
Wire.onRequest(da_sefu); // activam functia da_Sefu
}
void loop()
{
delay(100);
}
// aici interpretam datele
void receptie(int howMany)
{
byte index = 0;
//se salveaza comanda primita pe I2C intr-un string
while(Wire.available())
{
comanda[index++] = Wire.read();
}
//se interpreteaza comanda
p=strtok_r(comanda,";",&i);
while(p!="")
{
if (p.startsWith("L")) //se verifica daca trebuie sa aprindem un led
{//daca este led stim ca urmatoarele 2 caractere reprezinta pinul iar urmatorul caracter starea
String pin=p.substring(1,3);//cauta valoarea pin in comanda
String stare=p.substring(3,4);//cauta valoarea stare in comanda
digitalWrite(pin.toInt(),stare.toInt());//trimite valorile pinului respectiv
}
p=strtok_r(NULL,";",&i);//verific daca mai am ceva de executat
}
}
void da_sefu()
{
Wire.write("ARDUINO:Da sefu"); // raspunde cu un mesaj de 15 bytes
}
Am facut un filmulet numit i2c: un Arduino comanda, celalalt executa si raporteaza in care se vede mai bine ce am descris eu mai sus:// MASTER ver2
// sketch de inspiratie de la http://www.roroid.ro/comunicarea-i2c/
// sketch adaptat pentru led multicolor de niq_ro de la http://nicuflorica.blogspot.ro/
// si http://arduinotehniq.blogspot.com/
//se incarca biblioteca pentru comunicarea pe I2C
#include <Wire.h>
int r, g, b; // variabile pentru intensitate culori
int r1, g1, b1; // alte variabile
int intarziere = 1000; // intarziere intre comenzile mari, in ms
int fadespeed = 100; // intarziere intre trepte de intensitate, in ms
String ghe1;
void setup()
{
// initializeaza bus pentru i2c
Wire.begin();
Serial.begin(9600);
}
void loop()
{
// trecere de la stins la alb
for (r = 0; r < 25; r++) {
Serial.println(r);
r1 = r *10;
ordin (r1, r1, r1);
delay(fadespeed);
}
delay(intarziere);
// trecere de la alb la stins
for (r = 25; r > 0; r--) {
Serial.println(r);
r1 = r *10;
ordin (r1, r1, r1);
delay(fadespeed);
}
delay(intarziere);
// trecere de la stins la rosu
for (r = 0; r < 25; r++) {
Serial.println(r);
r1 = r *10;
ordin (0, 0, r1);
delay(fadespeed);
}
delay(intarziere);
// trecere de la rosu la stins
for (r = 25; r > 0; r--) {
Serial.println(r);
r1 = r *10;
ordin (0, 0, r1);
delay(fadespeed);
}
delay(intarziere);
// trecere de la stins la verde
for (r = 0; r < 25; r++) {
Serial.println(r);
r1 = r *10;
ordin (r1, 0, 0);
delay(fadespeed);
}
delay(intarziere);
// trecere de la verde la stins
for (r = 25; r > 0; r--) {
Serial.println(r);
r1 = r *10;
ordin (r1, 0, 0);
delay(fadespeed);
}
delay(intarziere);
// trecere de la stins la albastru
for (r = 0; r < 25; r++) {
Serial.println(r);
r1 = r *10;
ordin (0, r1, 0);
delay(fadespeed);
}
delay(intarziere);
// trecere de la albastru la stins
for (r = 25; r > 0; r--) {
Serial.println(r);
r1 = r *10;
ordin (0, r1, 0);
delay(fadespeed);
}
delay(intarziere);
}
void ordin (int er, int ghe, int be)
{
Serial.println("MASTER:ordon sa executi comanda - ");
Wire.beginTransmission(4); // transmit dispozitivului de la adresa #4
//in functie de cate dispozitive aveti legate pe I2C acest numar variaza
//comenzile de mai jos comanda ledurile de pe pinii 9, 10 si 11
//comenzile sunt de formatul LPPSSS; unde L-inseamna LED;PP-reprezinta numarul pinului;SSS-inseamna numarul PWM pentru aprindere reglabila
//Ex. L10000;-va stinge ledul de pe pinul 10;L09255 va aprinde ledul de pe pinul9 la maxim, iar L11123 va aprinde ledul de la pinul 11 la jumatate
Wire.write("L11"); // trimite numarul ledului care sa fie aprins/stins (aici e rosu, la pinul 11)
Serial.print("L11");
Serial.println(er);
// starea trebuie sa fie din 3 cifre, dar trebuie sa le transmit drept caractere
Serial.print("=");
int er1 = er/100;
Wire.write(er1+48); // trimit cifra sutelor
Serial.print(er1);
er = er-100*er1;
er1 = er/10;
Wire.write(er1+48); // trimit cifra zecilor
Serial.print(er1);
er = er-er1*10;
Serial.println(er);
Wire.write(er+48); // trimit cifra unitatilor
Wire.write(";"); // trimite separator
Wire.write("L09"); // trimite numarul ledului care sa fie aprins/stins (aici e verde, la pinul 9)
// starea trebuie sa fie din 3 cifre, dar trebuie sa le transmit drept caractere
Serial.print("L09");
Serial.println(ghe);
// starea trebuie sa fie din 3 cifre, dar trebuie sa le transmit drept caractere
Serial.print("=");
int ghe1 = ghe/100;
Wire.write(ghe1+48); // trimit cifra sutelor
Serial.print(ghe1);
ghe = ghe-100*ghe1;
ghe1 = ghe/10;
Wire.write(ghe1+48); // trimit cifra zecilor
Serial.print(ghe1);
ghe = ghe-ghe1*10;
Serial.println(ghe);
Wire.write(ghe+48); // trimit cifra unitatilor
Wire.write(";"); // trimite separator
Wire.write("L10"); // trimite numarul ledului care sa fie aprins/stins (aici e albastru, la pinul 10)
// starea trebuie sa fie din 3 cifre, dar trebuie sa le transmit drept caractere
Serial.print("L10");
Serial.println(be);
// starea trebuie sa fie din 3 cifre, dar trebuie sa le transmit drept caractere
Serial.print("=");
int be1 = be/100;
Wire.write(be1+48); // trimit cifra sutelor
Serial.print(be1);
be = be-100*be1;
be1 = be/10;
Wire.write(be1+48); // trimit cifra zecilor
Serial.print(er1);
be = be-be1*10;
Serial.println(be);
Wire.write(be+48); // trimit cifra unitatilor
Wire.write(";"); // trimite separator
Wire.requestFrom(4, 15); // se citesc 15 biti de raspuns de la dispozitivul
//de pe adresa 4
while(Wire.available()) //atata timp cat se primeste ceva
{
char c = Wire.read();
Serial.print(c); // tipareste caracterele primite
}
Serial.println("");
Wire.endTransmission(); // intrerupe transmisia
}
Sketch-ul pentru "sclav" este:// SLAVE ver.2
// sketch de inspiratie de la http://www.roroid.ro/comunicarea-i2c/
// sketch adaptat pentru led multicolor de niq_ro de la http://nicuflorica.blogspot.ro/
// si http://arduinotehniq.blogspot.com/
//se incarca biblioteca pentru comunicarea pe I2C
#include <Wire.h>
int LED[] = {99,4,5,6,7,8,9,10,11,12,13};//se definesc pinii pe care sunt conectate LED-urile
char comanda[21]; //vectorul in care va fi receptionata comanda pe I2c
char *i;
String p="";
void setup()
{
Serial.begin(9600);
for(int i = 0; i <= 10; i++){
pinMode(LED[i],OUTPUT);//initializeaza toti pini pe care sunt legate leduri ca output
}
}
void loop()
{
Wire.begin(4);//suntem dispozitivul de la adresa #4
Wire.onReceive(receptie);//datele primite pe i2c le interpretam in functia receptie
Wire.onRequest(da_sefu); // activam functia da_Sefu
delay(5);
}
// aici interpretam datele
void receptie(int howMany)
{
byte index = 0;
//se salveaza comanda primita pe I2C intr-un string
while(Wire.available())
{
comanda[index++] = Wire.read();
}
//se interpreteaza comanda
p=strtok_r(comanda,";",&i);
while(p!="")
{
// Serial.print(p);
if (p.startsWith("L")) //se verifica daca trebuie sa aprindem un led
{//daca este led stim ca urmatoarele 2 caractere reprezinta pinul iar urmatorul caracter starea
//Serial.println("---------------------------");
String pin=p.substring(1,3);//cauta valoarea pin in comanda
//Serial.print(pin);
String stare=p.substring(3,6);//cauta valoarea stare in comanda
//Serial.print(stare);
//digitalWrite(pin.toInt(),stare.toInt());//trimite valorile pinului respectiv
analogWrite(pin.toInt(),stare.toInt());//trimite valorile pinului respectiv
//digitalWrite(pin.toInt(),);//trimite valorile pinului respectiv
}
p=strtok_r(NULL,";",&i);//verific daca mai am ceva de executat
}
}
void da_sefu()
{
Wire.write("ARDUINO:Da sefu"); // raspunde cu un mesaj de 15 bytes
}
Pentru moment, cred ca e suficient ce am invatat despre acest mod de comunicare...
Niciun comentariu:
Trimiteți un comentariu