Avand la dispozitie 2 placi de dezvoltare Arduino, am considerat ca e timpul sa testez si modul de comunicare i2c, despre care puteti gasi informatii pe net. 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: Practic, montajul arata asa: 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): // 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 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 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: Dupa ce am vazut cum "lucreaza", atat "stapanul", cat si "sclavul", am rescris cele 2 sketck-uri pentru a aprinde led-urile cu intensitate regabila (cu factor de umplere variabil - PWM), dupa cum se vede in filmuletul i2c: un Arduino comanda, celalalt executa si raporteaza (2) Sketch-ul pentru "stapan" este: // 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 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 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...