Sunteți pe pagina 1din 77

http://www.robofun.

ro

Curs Gratuit Arduino si Robotica

L9
Senzori Atmosferici
Presiune Atmosferica BMP085
Senzorul BMP085 este un senzor foarte precis produs de firma Bosch, capabil sa masoare
presiunea atmosferica si temperatura. Cum presiunea atmosferica variaza cu altitudinea, pe baza
presiunii atmosferice masurate se poate calcula si altitudinea (lucru foarte util la drone si alte dispozitive
zburatoare). Conectarea senzorului la Arduino se face prin I2C, astfel ca avem nevoie de doar doi pini
(in afara celor doi pini de alimentare). Pentru a citi valorile senzorului recomand o librarie open-source,
disponibila aici : http://www.robofun.ro/senzor_presiune_bmp085 (primul link, "Librarie Arduino").
Dupa instalarea librariei, codul sursa este extrem de simplu, ca mai jos.

Arduino 3.3 V

BMP085 VCC

Arduino GND

BMP085 GND

Arduino SDA

BMP085 SDA

Arduino SCL

BMP085 SCL

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9
#include <Wire.h>
#include <BMP085.h>
BMP085 dps = BMP085();
long Temperature = 0, Pressure = 0, Altitude = 0;
void setup(void) {
Serial.begin(9600);
Wire.begin();
delay(1000);
dps.init();
delay(5000);
}
void loop(void) {
dps.getTemperature(&Temperature);
dps.getPressure(&Pressure);
dps.getAltitude(&Altitude);

Serial.print("Temp(C):");
Serial.print(Temperature);
Serial.print(" Alt(cm):");
Serial.print(Altitude);
Serial.print(" Pressure(Pa):");
Serial.println(Pressure);

Singurul lucru de remarcat aici este delay-ul de 5 secunde din setup, necesar pentru initializarea
senzorului.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9
Presiune Atmosferica MPL115A1
MPL115A1 este destul de similar cu BMP085. Difera modul de conectare cu Arduino (I2C in
cazul BMP085 si SPI in cazul MPL115A1). Conectarea se face folosind pinii SPI, ca mai jos.

Arduino 3.3 V

MPL115A1 VCC

Arduino GND

MPL115A1 GND

Arduino Digital 9

MPL115A1 SDN

Arduino Digital 10

MPL115A1 CSN

Arduino Digital 12

MPL115A1 SDO

Arduino Digital 11

MPL115A1 SDI

Arduino Digital 13

MPL115A1 SCK

Codul sursa integral in vei gasi la adresa:


http://www.robofun.ro/senzor_presiune_atmosferica_MPL115A1

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9
Temperatura si Umiditate SHT15
SHT15 este un senzor care masoare presiunea si umiditatea mediului ambiant extrem de precis
(precizie de 0.3 C, si 2 % RH ). Conectarea la Arduino se face folosind doi pini digitali.

Arduino 5 V

SHT15 VCC

Arduino GND

SHT15 GND

Arduino Digital 9

SHT15 DATA

Arduino Digital 8

SHT15 SCK

Codul
sursa
integral
este
http://www.robofun.ro/senzor_temperatura_umiditate_sht15 .

disponibil

aici

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9

Temperatura si Umiditate DHT22


Daca nu ai nevoie de o precizie chiar asa de mare ca in cazul SHT15 si te multumesti si cu +/0.5 C, atunci DTH22 s-ar putea sa fie alegerea corecta pentru tine. Frecventa de citire pentru acest
senzor este de asemenea destul de scazuta comparata cu SHT15 (poti face cel mult o citire la 2
secunde). Ca necesar de pini, este foarte modest, avand nevoie doar de un singur pin digital pentru
conectarea cu Arduino.

Arduino 5 V

DHT22 VCC

Arduino GND

DHT22 GND

Arduino Digital 2

DHT22 PIN2

Rezistor 10K

conectat intre
DTH22 VCC si DHT22
PIN2

Mai departe, instaleaza libraria pentru Arduino disponibila aici :


http://www.robofun.ro/senzor_umiditate_temperatura_dht22
#include <DHT22.h>
#define DHT22_PIN 2
DHT22 myDHT22(DHT22_PIN);
void setup(void)

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9

Serial.begin(9600);
Serial.println("DHT22 Library Demo");
}
void loop(void) {
DHT22_ERROR_t errorCode;

delay(2000);
Serial.print("Requesting data...");
errorCode = myDHT22.readData();
switch(errorCode)
{
case DHT_ERROR_NONE:
Serial.print("Got Data ");
Serial.print(myDHT22.getTemperatureC());
Serial.print("C ");
Serial.print(myDHT22.getHumidity());
Serial.println("%");
break;
case DHT_ERROR_CHECKSUM:
Serial.print("check sum error ");
Serial.print(myDHT22.getTemperatureC());
Serial.print("C ");
Serial.print(myDHT22.getHumidity());
Serial.println("%");
break;
case DHT_BUS_HUNG:
Serial.println("BUS Hung ");
break;
case DHT_ERROR_NOT_PRESENT:
Serial.println("Not Present ");
break;
case DHT_ERROR_ACK_TOO_LONG:
Serial.println("ACK time out ");
break;
case DHT_ERROR_SYNC_TIMEOUT:
Serial.println("Sync Timeout ");
break;
case DHT_ERROR_DATA_TIMEOUT:
Serial.println("Data Timeout ");
break;
case DHT_ERROR_TOOQUICK:
Serial.println("Polled to quick ");
break;
}

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9
Temperatura TMP102
TMP102 este un senzor de temperatura care comunica pe I2C, cu o rezolutie de 0.0625 C si o
precizie de 0.5 C. Alimentarea se face la 3.3 V, iar conectarea la Arduino se face folosind pinii I2C.
Limitele sale sunt -25 C pana la 85 C, iar consumul este de-a dreptul impresionant 10 microAmperi !.

Arduino 3.3 V

TMP102 V+

Arduino GND

TMP102 GND

Arduino SDA
(Analog 4)

TMP102 SDA

Arduino SCL
(Analog 5)

TMP102 SCL

Arduino GND

TMP102 ADD0

#include <Wire.h>
int tmp102Address = 0x48;
void setup(){
Serial.begin(9600);
Wire.begin();
}
void loop(){
float celsius = getTemperature();
Serial.print("Celsius: ");
Serial.println(celsius);
float fahrenheit = (1.8 * celsius) + 32;
Serial.print("Fahrenheit: ");

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9

Serial.println(fahrenheit);
delay(200);
}
float getTemperature(){
Wire.requestFrom(tmp102Address,2);
byte MSB = Wire.read();
byte LSB = Wire.read();
int TemperatureSum = ((MSB << 8) | LSB) >> 4;
float celsius = TemperatureSum*0.0625;
return celsius;
}

Senzorul TMP102 are 4 adrese distincte posibile, adresa curenta fiind selectata prin conectarea
pinului ADD0 la GND, 3.3 V, SDA sau respectiv SCL. Astfel, in exemplul de mai sus, pinul ADD0
este conectat la GND si atunci adresa senzorului este 0x48. Daca vom conecta pinul ADD0 la 3.3 V,
atunci adresa senzorului va deveni 0x49. Conectarea pinului ADD0 la pinul SDA va determina adresa
0x4A, iar conectarea la SCL va determina adresa 0x4B. Acest lucru este excelent pentru situatiile in care
avem nevoie de mai multi senzori conectati la acelasi Arduino. Putem astfel conecta pana la cel mult
patru senzori, toti conectati pe acelasi bus I2C. Pentru primul senzor, pinul ADD0 se conecteaza la
GND, pentru al doilea senzor, pinul ADD0 se conecteaza la 3.3V, pentru a treilea senzor, pinul ADD0
se conecteaza la SDA, iar pentru a al patrulea senzor, pinul ADD0 se conecteaza la pinul SCL. Toti
ceilalti pini se conecteaza exact ca mai sus.
In cod, vom avea patru adrese distincte, cate o adresa pentru fiecare senzor, ca mai jos.
#include <Wire.h>
int tmp102Address1
int tmp102Address2
int tmp102Address3
int tmp102Address4

=
=
=
=

0x48;
0x49;
0x4A;
0x4B;

void setup(){
Serial.begin(9600);
Wire.begin();
}
void loop(){
float celsius = getTemperature(tmp102Address1);
Serial.print("Celsius, Senzor 1: ");
Serial.println(celsius);
celsius = getTemperature(tmp102Address2);
Serial.print("Celsius, Senzor 2: ");
Serial.println(celsius);
celsius = getTemperature(tmp102Address3);
Serial.print("Celsius, Senzor 3: ");
Serial.println(celsius);
celsius = getTemperature(tmp102Address4);

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9

Serial.print("Celsius, Senzor 4: ");


Serial.println(celsius);
delay(200);
}
float getTemperature(int address){
Wire.requestFrom(address,2);
byte MSB = Wire.read();
byte LSB = Wire.read();
int TemperatureSum = ((MSB << 8) | LSB) >> 4;
float celsius = TemperatureSum*0.0625;
return celsius;
}

Temperatura la Distanta MLX90614


MLX90614 este un senzor de temperatura cu o functionalitate unica. Determina temperatura
obiectelor de la distanta, fara a le atinge ! Senzorul functioneaza pe baza determinarii lungimii de unda a
radiatiei infrarosie emisa de obiectul in cauza. Determina temperaturi intre -70 C si 382 C, cu o
rezolutie imensa (0.0034 C !).
Conectarea la Arduino este ceva mai complexa decat de obicei, pentru ca senzorul nu este inclus
pe un montaj, ci montajul va trebui sa il faci tu. Doua rezistoare de 4.7 K si un condensator de 0.1 uF
sunt tot ce iti trebuie.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9

Arduino 3.3 V

MLX90614 PIN2

Arduino GND

MLX90614 PIN1

Arduino SDA (Analog 4)

MLX90614 PIN3

Arduino SCL (Analog 5)

MLX90614 PIN4

Condensator 100nF

Conectat intre
MLX90614 PIN1 si
MLX90614 PIN2

Rezistor 4.7 K

Conectat intre
MLX90614 PIN3 si
Arduino 3.3V

Rezistor 4.7 K

Conectat intre
MLX90614 PIN4 si
Arduino 3.3V

Mai departe, vei avea nevoie sa iti instalezi in mediul tau de dezvoltare Arduino libraria
I2CMaster (disponibila ca download de pe pagina :
http://www.robofun.ro/senzor_infrarosu_MLX90614 ).
Codul sursa integral este disponibil mai jos.
#include <i2cmaster.h>
void setup(){
Serial.begin(9600);
i2c_init();

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L9
PORTC = (1 << PORTC4) | (1 << PORTC5);
}
void loop(){
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck();
data_high = i2c_readAck();
pec = i2c_readNak();
i2c_stop();
double tempFactor = 0.02;
double tempData = 0x0000;
int frac;
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;
float celsius = tempData - 273.15;
float fahrenheit = (celsius*1.8) + 32;
Serial.print("Celsius: ");
Serial.println(celsius);
Serial.print("Fahrenheit: ");
Serial.println(fahrenheit);
delay(1000);
}

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

LCD 16 X 2, LCD 16 X 4, LCD 20 X 4


Toate aceste LCD-uri se interfateaza cu Arduino exact la fel. Singura
diferenta este dimensiunea lor. Astfel, LCD-ul 16 X 2 permite 16 coloane si
doua linii de caractere (adica in total 32 de caractere), LCD-ul 16X4 permite 4
linii (64 de caractere in total), iar cel de 20X4 permite 80 de caractere afisate.
Ca sa-l folosesti cu Arduino, ai nevoie de fire de conectare si de un
potentiometru de 10K pentru reglarea contrastului (nu merge fara el). Schema
de conectare este cea de mai jos (nu este simpla).
Daca esti la primele tale teste cu Arduino, din pacate s-ar putea sa
gasesti conectarea LCD-ului o experienta frustranta. Sunt destul de multe fire
de conectat, si daca gresesti unul singur nu-ti va functiona. Iti recomand sa faci
montajul incet si sa verifici de cateva ori fiecare conexiune. Daca ai ajuns la
final, vei avea atat de multe fire incat iti va fi dificil sa vezi care fir duce unde.
Verifica cu atentie pe parcurs ca sa fii sigur ca fiecare fir duce acolo unde
trebuie.
Daca totusi nu ti-a iesit si vrei sa incerci ceva mai simplu, iti recomand
shield-ul cu LCD 2X16 (http://www.robofun.ro/bricks/shield-lcd-16x2) care nu
face altceva decat sa-ti ascunda conexiunile complicate.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

Arduino 5 V

Pin1 Potentiometru

Arduino GND

Pin3 Potentiometru

Pin2 Potentiometru

VO (PIN3) LCD

Arduino GND

GND (PIN1) LCD

Arduino GND

RW (PIN5) LCD

Arduino 5 V

VCC (PIN2) LCD

Arduino Digital 12

RS (PIN4) LCD

Arduino Digital 11

E (PIN6) LCD

Arduino Digital 5

D4 (PIN11) LCD

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
Arduino Digital 4

D5 (PIN12) LCD

Arduino Digital 3

D6 (PIN13) LCD

Arduino Digital 2

D7 (PIN14) LCD

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
lcd.begin(16, 2);
lcd.print("hello, world!");
}
void loop() {
lcd.setCursor(0, 1);
lcd.print(millis()/1000);
}

Codul sursa de mai sus utilizeaza libraria LiquidCrystal (inclusa in mod


standard in mediul de dezvoltare Arduino). Singura modificare pe care va trebui
sa o faci cand folosesti un alt tip de LCD este sa schimbi parametrii din rutina
de initializare. Astfel, pentru un LCD 20X4, linia 3 se schimba la "lcd.begin(20,
4)".
Alte rutine interesante ale librariei LiquidCrystal sunt mai jos :
clear() - curata ecranul complet. Se apeleaza fara parametri "lcd.clear()"
home() - muta cursorul in partea din stanga, sus. Se apeleaza fara parametri
"lcd.home()"
setCursor() - muta cursorul la pozitia specificata. Textul care urmeaza a fi
scris este scris la pozitia specificata de aceasta metoda. Astfel, pentru a scrie
text pe linia 2, coloana 4, vom apela "lcd.setCursor(1,3); lcd.print("TEXT");"
noDisplay() - opreste LCD-ul, fara a pierde textul afisat. Se apeleaza fara
parametri "lcd.noDisplay()"
display() - porneste LCD-ul dupa ce a fost oprit folosind "noDisplay". Se
apeleaza fara parametri "lcd.display()"
scrollDisplayLeft() - deplaseaza textul afisat pe LCD cu un caracter spre
stanga. Se apeleaza fara parametri "lcd.scrollDisplayLeft()"
scrollDisplayRight() - deplaseaza textul afisat pe LCD cu un caracter spre
dreapta. Se apeleaza fara parametri "lcd.scrollDisplayRight()"

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
LCD 16 X 2 pe I2C, LCD 20 X 4 pe I2C
Ambele LCD-uri sunt LCD-urile obisnuite despre care am discutat mai sus,
carora li s-a atasat o placa suplimentara care comunica pe I2C cu Arduino si
seteaza cei 8 pini pentru controlul LCD-ului la valorile care trebuie astfel incat
pe LCD sa fie afisat text-ul care trebuie. In acest fel, intre Arduino si LCD sunt
necesare doar doua fire (SDA si SCL), in afara firului de GND si alimentare.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

Conexiunile la Arduino sunt ca in cele doua imagini de mai jos. Ultimii doi
pini din mufa lipita pe placa LCD-ului nu se folosesc. In rest, de la stanga la
dreapta, avem SDA (se conecteaza la pinul analogic 4 pe Arduino UNO sau la
pinul SDA pe Arduino Leonardo), SCL (se conecteaza la pinul analogic 5 pe
Arduino UNO sau la pinul SCL pe Arduino Leonardo), 5V (se conecteaza la pinul
5V pe Arduino, si pinul GND (se conecteaza la pinul GND).

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
Arduino UNO

Arduino 5 V

LCD 5V

Arduino GND

LCD GND

Arduino Analog 4

LCD SDA

Arduino Analog 5

LCD SCL

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
Arduino Leonardo

Arduino 5 V

LCD 5V

Arduino GND

LCD GND

Arduino SDA

LCD SDA

Arduino SCL

LCD SCL

Urmatorul pas este actualizarea librariei LCD, astfel incat sa suporte si


comunicarea I2C.
Mergi la adresa http://www.robofun.ro/lcd_20x4_i2c_negru_verde
si
descarca libraria din acea pagina. Este bine sa o incerci prima data pe cea de
pe GITHUB, care este intotdeauna la zi. Dupa ce ai descarcat-o, inchide mediul
Arduino si deschide folder-ul "libraries" din folder-ul in care este instalat mediul
Arduino. Folder-ul "libraries" ar trebui sa arate similar cu imaginea de mai jos.
Deschide si folder-ul "LiquidCrystal" ca sa vezi ce fisiere sunt in interior.
Ar trebui sa vezi ceva similar cu ce este mai jos.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

Sterge apoi tot ceea ce este in acest folder si inlocuieste cu fisierele


descarcate anterior. Ar trebui sa fie similar cu imaginea de mai jos.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
Porneste acum mediul de dezvoltare Arduino si incearca programul de
mai jos.
#include "Wire.h"
#include "LiquidCrystal.h"
LiquidCrystal lcd(0);
void setup() {
lcd.begin(20, 4);
lcd.setBacklight(HIGH);
lcd.print("hello, world
lcd.setCursor(0, 1);
lcd.print("hello, world
lcd.setCursor(0, 2);
lcd.print("hello, world
lcd.setCursor(0, 3);
lcd.print("hello, world

0 !");
1 !");
2 !");
3 !");

}
void loop() {
}

Daca LCD-ul tau nu arata ca mai sus, pe spatele placutei rosii vei gasi un
potentiometru de culoare albastra. Acest potentiometru stabileste contrastul
LCD-ului, si probabil ca s-a miscat in timpul transportului. Folosind o surubelnita
mica, un varf de cutit ascutit, foarfeca sau pila de unghii, roteste-l usor si
urmareste in acelasi timp textul pe LCD pana cand devine foarte clar.
Si partea frumoasa abia acum vine ! Cu acest tip de LCD, poti conecta
simultan pana la opt LCD-uri la acelasi Arduino, folosind aceeasi doi pini I2C.
Pentru aceasta, intoarce LCD-ul pe spate, si observa cei 3 jumperi pentru
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
setarea adresei I2C. In mod obisnuit, nici unul dintre acesti jumperi nu este
lipit, asa ca adresa shield-ului este zero (lucru pe care il vezi in cod la linia
LiquidCrystal lcd(0)). Fiecare LCD va trebuie sa aiba o adresa I2C diferita, asa
ca ceea ce ai de facut este sa folosesti un letcon si putin fludor pentru a
conecta unul sau mai multi jumperi impreuna. Adresele sunt in cod binar, astfel
ca folosind cei trei jumperi poti obtine exact opt adrese. Pentru a conecta un
jumper, incalzeste ambele pad-uri, apoi adauga fludor si intinde fludorul astfel
incat sa faca contact intre ambele pad-uri, ca mai jos.

Pentru a conecta mai multe LCD-uri la acelasi Arduino, tot ce ai de facut


este conectezi toti pinii de SDA impreuna de la toate LCD-urile, toti pinii SCL
impreuna, si la fel si GND si 5V. In prealabil, ai grija sa setezi adrese I2C diferite
lipind cei trei jumperi de adresa in configuratii diferite. Apoi, in cod definesti
mai multe obiecte de tip LCD, ca mai jos.
#include "Wire.h"
#include "LiquidCrystal.h"
LiquidCrystal lcd1(0);
LiquidCrystalc lcd2(1);
LiquidCrystal lcd3(2);
void setup() {
lcd1.begin(20, 4);
lcd2.begin(20, 4);
lcd.3begin(20, 4);
lcd1.setBacklight(HIGH);
lcd1.print("LCD1, hello,
lcd1.setCursor(0, 1);
lcd1.print("LCD1, hello,
lcd1.setCursor(0, 2);
lcd1.print("LCD1, hello,
lcd1.setCursor(0, 3);
lcd1.print("LCD1, hello,

world 0 !");
world 1 !");
world 2 !");
world 3 !");

lcd2.setBacklight(HIGH);
lcd2.print("LCD2, hello, world 0 !");

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

lcd2.setCursor(0,
lcd2.print("LCD2,
lcd2.setCursor(0,
lcd2.print("LCD2,
lcd2.setCursor(0,
lcd2.print("LCD2,

1);
hello, world 1 !");
2);
hello, world 2 !");
3);
hello, world 3 !");

lcd3.setBacklight(HIGH);
lcd3.print("LCD3, hello,
lcd3.setCursor(0, 1);
lcd3.print("LCD3, hello,
lcd3.setCursor(0, 2);
lcd3.print("LCD3, hello,
lcd3.setCursor(0, 3);
lcd3.print("LCD3, hello,

world 0 !");
world 1 !");
world 2 !");
world 3 !");

}
void loop() {
}

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
MP3 Player Shield
Shield-ul MP3 Player contine chip-ul VS1053b, capabil sa decodeze
stream-uri MP3, OGG Vorbis, AAC, WMA, MIDI, si de asemenea contine si un slot
de card microSD pentru incarcarea fisierelor audio. Shield-ul mai contine si un
conector pentru casti sau boxe audio, astfel ca in final, ceea ce obtii este un
player MP3 complet.
Ce ai tu de facut este sa citesti informatia stocata pe SD card si sa o
trimiti catre chip-ul MP3, atunci cand acesta o solicitia. Suna complicat in
teorie, dar din fericire exista deja mai multe librarii care fac asta in locul tau.
Cea mai interesanta este libraria disponibila ca download la adresa
http://www.robofun.ro/mp3_player_shield (link-ul "Librarie pentru Arduino").
Fisierul .zip pe care il descarci contine atat libraria MP3, cat si libraria pentru SD
card. Va trebui sa le copiezi pe ambele in directorul "libraries" din mediul tau de
dezvoltare Arduino. Codul sursa este relativ simplu de inteles, toata partea
complexa este ascunsa de librarie.
#include
#include
#include
#include

<SPI.h>
<SdFat.h>
<SdFatUtil.h>
<SFEMP3Shield.h>

SFEMP3Shield MP3player;
byte temp;
byte result;
char title[30];
char artist[30];
char album[30];
void setup() {
Serial.begin(115200);
result = MP3player.begin();
if(result != 0) {
Serial.print("Error code: ");
Serial.print(result);
Serial.println(" when trying to start MP3 player");
}
Serial.println("STARTED");
}

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

void loop() {
result = MP3player.playMP3("melodie1.mp3");
delay(3000);
if (MP3player.isPlaying()){
MP3player.stopTrack();
}
}

Avem posibilitatea de a porni redarea unui fisier mp3 la alegere, putem


verifica daca s-a terminat intre timp redarea audio (daca s-a terminat fisierul)
sau putem opri redarea intr-un moment ales de noi. Spre exemplu, in codul
sursa de mai sus, pornim redarea pentru fisierul "melodie1.mp3", si daca dupa
3 secunda fisierul inca nu s-a terminat, atunci il oprim noi fortat.
Libraria mai permite sa facem fastForward pe un fisier pana la o anume
pozitie folosind "MP3player.skipTo(<pozitieInSecunde>);" si putem determina
pozitia
curenta
("MP3player.currentPosition();").
Spre
exemplu,
"MP3player.skipTo(30000);" va derula mp3-ul curent pana la secunda 30, iar
"int pozitie = MP3player.currentPosition();" va incarca in variabila "pozitie"
timpul in milisecunde de la inceperea redarii.
Pinii ocupati de acest shield sunt 2, 3, 4, 6, 7, 8, 9, 11, 12, 13 (aproape
toti, pentru Arduino UNO). Daca ai nevoie de mai multi pini, poti folosi Arduino
Mega in locul lui Arduino UNO sau poti schimba MP3 Player Shield-ul cu un MP3
Trigger (care are nevoie de mult mai putini pini).

MP3 Trigger
MP3 Trigger este varianta mult imbunatatita a lui shield-ului MP3 Player
prezentat in sectiunea anterioara. Pe langa chip-ul capabil sa redea MP3-uri, SD
Card-ul deja prezent pe placa, MP3 Trigger-ul are in plus si un microcontroller
pre-programat. Astfel, numarul de pini necesari pentru interfatarea cu Arduino
scade drastic (doar doi pini sunt necesari) si in plus, MP3 Trigger-ul poate
functiona chiar si standalone, fara Arduino. Dat fiind ca este cel mai simplu, sa
incepem cu acest mod de functionare.
MP3 Trigger-ul ofera 18 pini, fiecare dintre ei declansand redarea melodiei
al carei nume incepe cu numarul asociat pinului. Astfel, spre exemplu, atunci
cand pinul 3 este conectat la pinul GND, este redata melodia al carei nume
incepe cu "003" (un exemplu de nume valid este "003 Avion cu Motor.mp3".). O
schema de conectare folosind butoane brick este mai jos. Am pus in schema
doar doua butoane, pentru exemplificare. Evident ca tu poti conecta cate ai
nevoie, maxim 18 butoane.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
Buton 1 VCC

MP3 Trigger TRIG18 (pinul din interior)

Buton 1 OUT

MP3 Trigger TRIG18 (pinul din exterior)

Buton 2 VCC

MP3 Trigger TRIG9 (pinul din interior)

Buton 2 OUT

MP3 Trigger TRIG9 (pinul din exterior)

Pinii din interior marcati "TRIGNN" sunt conectati la microcontroller-ul


placii, si atunci cand unul dintre acesti pini este conectat la GND, incepe
redarea melodiei corespunzatoare de pe SD Card. In mod convenabil, toti pinii
din sirul exterior sunt conectati deja la pinul GND. Tot ce ai tu de facut atunci
cand vrei sa porneasca redarea unei melodii, este sa faci contact intre pinul din
interior si pinul din exterior. Butonul brick, in conectarea de mai sus,
conecteaza pinul din exterior (GND) cu pinul din interior (TRIGNN) atunci cand
este apasat. Acest mod de utilizare este foarte util pentru situatiile cand ai
nevoie sa pornesti redarea unei melodii MP3 ca raspuns la un stimul extern,
situatie in care nu mai ai nevoie de Arduino. Pentru situatiile mai complexe,
MP3 Trigger-ul ofera un API elaborat, accesibil peste un protocol serial TTL,
folosind Arduino. Schema de conectare este cea de mai jos.

Arduino 5V

MP3 Trigger USBVCC

Arduino GND

MP3 Trigger GND

Arduino Digital 7

MP3 Trigger TX

Arduino Digital 8

MP3 Trigger RX

http://www.robofun.ro/forum

http://www.robofun.ro

L10

Curs Gratuit Arduino si Robotica

Mai departe, tot ce ai de facut este sa folosesti libraria SoftwareSerial pe


pinii 7 si 8 si sa-i trimiti placii MP3 Trigger comenzi peste conexiunea seriala.
Cele mai des folosite comenzi sunt disponibile mai jos.

Comanda: Start/Stop
Numar de bytes: 1
Byte de comanda: O
Functionare: Daca exista o melodie care este redata la momentul primirii
comenzii, se opreste redarea. Altfel, incepe redarea.
Comanda: Inainte
Numar de bytes: 1
Byte de comanda: F
Functionare : Urmatoarea melodie MP3 este redata.
Comanda: Inapoi
Numar de bytes: 1
Byte de comanda: R
Functionare: Melodia precedenta MP3 este redata.
Comanda: Trigger (binary)
Numar de bytes: 2
Byte de comanda: t
Byte de date: n = 1 to 255
Functionare: Daca exista, melodia cu numele NNNxxxx.MP3 este redata,
unde NNN is echivalentul ASCII al bitului de comanda.
Comanda: Play (binary)
Numar de bytes: 2
Byte de comanda: p
Byte de date: n = 0 to 255
Functionare: Daca exista, melodia numarul n va fi redata.
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
Comanda: Set Volume (binary)
Numar de bytes: 2
Byte de comanda: v
Byte de date: n = 0 to 255
Comments: Volumul va fi setat la valoarea n. Volumul maxim se obtine cu
valoarea "0", iar volumul minim in jur de 100.
Toata gama de comenzi suportata este prezentata pe larg in manual de
utilizare al placii, disponibil la adresa http://www.robofun.ro/mp3_trigger_v2

Music Instrument Shield


Music Instrument Shield este capabil sa genereze note muzicale conform
standardului MIDI. Shield-ul comunica serial cu Arduino, pe pinii digitali 2 si 3,
pinul 4 digital functionand drept pin de reset. Controlul shield-ului se face
trimitand comenzi pe interfata seriala formata din pinii 2 si 3. Comenzile seriale
de control nu sunt foarte simple (lucru care se datoreaza protocolului MIDI,
care, in opinia mea, este destul de incurcat).
Shield-ul este capabil sa redea 248 de instrumente, de la cele mai
comune (pian, harpa, acordeon, chitara), pana la unele destul de ciudate (latrat
de caine, impuscatura, elicopter). Instrumentele sunt organizate in 3 "bankuri".

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

Cea mai simpla abordare pentru a intelege modul cum se foloseste acest
shield este sa urmarim mai jos un exemplu de program scris de Nathan Seidle
de la Sparkfun, program care genereaza cate zece note pentru fiecare
instrument inclus.
/*
2-12-2011
Spark Fun Electronics 2011
Nathan Seidle
This code is public domain but you buy me a beer if you use this and we
meet someday (Beerware license).
This code works with the VS1053 Breakout Board and controls the VS1053 in
what is called Real Time MIDI mode.
To get the VS1053 into RT MIDI mode, power up the VS1053 breakout board
with GPIO0 tied low, GPIO1 tied high.
I use the NewSoftSerial library to send out the MIDI serial at 31250bps.
This allows me to print regular messages
for debugging to the terminal window. This helped me out a ton.
5V : VS1053 VCC
GND : VS1053 GND
D3 (SoftSerial TX) : VS1053 RX
D4 : VS1053 RESET
Attach a headphone breakout board to the VS1053:
VS1053 LEFT : TSH

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
VS1053 RIGHT : RSH
VS1053 GBUF : GND
When in the drum bank (0x78), there are not different instruments, only
different notes.
To play the different sounds, select an instrument # like 5, then play
notes 27 to 87.
To play "Sticks" (31):
talkMIDI(0xB0, 0, 0x78); //Bank select: drums
talkMIDI(0xC0, 5, 0); //Set instrument number
//Play note on channel 1 (0x90), some note value (note), middle velocity
(60):
noteOn(0, 31, 60);
*/
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Tied to VS1053 Reset line
byte ledPin = 13; //MIDI traffic inidicator
int instrument = 0;
void setup() {
Serial.begin(57600);
//Setup soft serial for MIDI control
mySerial.begin(31250);

//Reset the VS1053


pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);

void loop() {
talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume
to near max (127)

/*

//Demo Basic MIDI instruments, GM1


//=================================================================
Serial.println("Basic Instruments");
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
//Change to different instrument
for(instrument = 0 ; instrument < 127 ; instrument++) {
Serial.print(" Instrument: ");
Serial.println(instrument, DEC);
talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
data byte command
//Play notes from F#-0 (30) to F#-5 (90):
for (note = 30 ; note < 40 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);
//Note on channel 1 (0x90), some note value (note), middle velocity
(0x45):
noteOn(0, note, 60);
delay(50);
//Turn off the note with a given off/release velocity
noteOff(0, note, 60);
delay(50);
}
delay(100); //Delay between instruments
}
//=================================================================

*/

//Demo GM2 / Fancy sounds


//=================================================================
Serial.println("Demo Fancy Sounds");
talkMIDI(0xB0, 0, 0x78); //Bank select drums
//For this bank 0x78, the instrument does not matter, only the note
for(instrument = 30 ; instrument < 31 ; instrument++) {
Serial.print(" Instrument: ");
Serial.println(instrument, DEC);
talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1
data byte command
//Play fancy sounds from 'High Q' to 'Open Surdo [EXC 6]'
for (note = 27 ; note < 87 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);
//Note on channel 1 (0x90), some note value (note), middle velocity
(0x45):
noteOn(0, note, 60);
delay(50);
//Turn off the note with a given off/release velocity
noteOff(0, note, 60);
delay(50);
}
delay(100); //Delay between instruments

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
}

/*
//Demo Melodic
//=================================================================
Serial.println("Demo Melodic? Sounds");
talkMIDI(0xB0, 0, 0x79); //Bank select Melodic
//These don't sound different from the main bank to me
//Change to different instrument
for(instrument = 27 ; instrument < 87 ; instrument++) {
Serial.print(" Instrument: ");
Serial.println(instrument, DEC);
talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1
data byte command
//Play notes from F#-0 (30) to F#-5 (90):
for (note = 30 ; note < 40 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);
//Note on channel 1 (0x90), some note value (note), middle velocity
(0x45):
noteOn(0, note, 60);
delay(50);
//Turn off the note with a given off/release velocity
noteOff(0, note, 60);
delay(50);
}
}

delay(100); //Delay between instruments

*/
}
//Send a MIDI note-on message. Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or
// that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
digitalWrite(ledPin, HIGH);

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
mySerial.write(cmd);
mySerial.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2
//data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if( (cmd & 0xF0) <= 0xB0)
mySerial.write(data2);
}

digitalWrite(ledPin, LOW);

Primul lucru la care merita sa ne oprim este declaratia conexiunii seriale


de tip sofware pe pinii 2 si 3 : "SoftwareSerial mySerial(2, 3);". Vom folosi
aceasta conexiune seriala pentru a trimite date catre shield. Rata de transfer
pentru aceasta conexiune seriala (rata presetata in shield) este de 31250 bps
(motiv pentru care avem in setup linia mySerial.begin(31250)). Tot in setup
dam o comanda de reset shield-ului (folosim pinul 4 digital, care este conectat
la pinul de reset al shield-ului, pin pe care il coboram in LOW si apoi il ridicam
in HIGH dupa 100 de milisecunde).
Prima instructiune din loop este talkMIDI(0xB0, 0x07, 120), care seteaza
volumul shield-ului la valoarea 120 (sunt posibile 127 de valori, intre 0 si 127).
Codul este apoi structurat in 3 sectiuni ("Demo Basic MIDI instruments",
"Demo GM2 / Fancy sounds" si "Demo Melodic"). La inceputul fiecarei sectiuni
avem cate o comanda care seteaza "bank-ul" (una dintre cele trei categorii de
instrumente). Astfel, la inceputul primei sectiune avem comanda
"talkMIDI(0xB0, 0, 0x00)", care seteaza bank-ul de instrumente MIDI clasice,
apoi la inceputul celei de-a doua sectiuni avem "talkMIDI(0xB0, 0, 0x78)" care
seteaza bank-ul cu instrumente de percutie, iar apoi in cea de-a treia sectiune
avem "talkMIDI(0xB0, 0, 0x79)", care seteaza bank-ul de instrumente melodice.
In prima sectiune avem doua instructiuni for. Prima instructiune for
cicleaza printre cele 128 de instrumente disponibile in acest bank, iar cel de-al
doilea for genereaza 10 note muzicale pentru fiecare instrument. Comanda
interesanta in aceasta sectiune este "talkMIDI(0xC0, instrument, 0)", care
seteaza instrumentul care va reda notele muzicale. Pentru bank-ul 0X00 (setat
anterior prin comanda talkMIDI(0xB0, 0, 0x00), avem 128 de instrumente
posibile, intre 0 si 128. Cel de-al doilea for genereaza zece note pentru fiecare
instrument. Redarea unui note muzicale este pornita cu "noteOn(0, note, 60)"
si este oprita cu "noteOff(0, note, 60)".
Cea de-a doua sectiune ("Demo GM2 / Fancy sounds") este ceva mai
speciala decat celelalte doua. Acest lucru se intampla din cauza protocolului
MIDI, care specifica faptul ca atunci cand este selectat bank-ul cu instrumente
de percutie, comanda care seteaza instrumentul nu mai are nici un efect, ci
fiecare instrument este de fapt o nota. Alt mod de a spune acelasi lucru este ca
in bank-ul cu instrumente de percutie este un singur instrument cu foarte
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
multe note, iar fiecare nota de fapt reda un alt instrument. Prima comanda din
aceasta sectiune selecteaza bank-ul cu instrumente de percutie
("talkMIDI(0xB0, 0, 0x78)"). Urmatoarea instructiune for va face exact un singur
ciclu (pentru ca asa cum am spus mai sus, instrumentul nu conteaza in cazul
bank-ului cu instrumente de percutie. A doua instructiune for din aceasta
sectiune cicleaza intre 27 si 87, cele 60 de instrumente disponibile pentru
bank-ul de percutie. Instructiunea "noteOn(0, note, 60)" genereaza o nota pe
cate unul dintre cele 60 de instrumente.
Cea de-a treia sectiune este perfect similara cu prima sectiune, doar ca in
bank-ul cu instrumente melodice instrumentele sunt intre 27 si 87.
Sa analizam acum mai atent functia noteOn, care genereaza o anumita
nota muzicala. Functia noteOn primeste trei parametri. Cel de-al doilea
parametru este nota muzicala, iar ultimul parametru reprezinta cat de
"puternic" este generata nota (daca ne gandim ca folosim un pian, atunci
ultimul parametru reprezinta cat de puternic apasam pe clapa pianului).
In rezumat :
3 bank-uri cu instrumente
talkMIDI(0xB0, 0, 0x00) selecteaza bank-ul cu instrumente clasice
talkMIDI(0xB0, 0, 0x78) selecteaza bank-ul cu instrumente de percutie
talkMIDI(0xB0, 0, 0x79) selecteaza bank-ul cu instrumente melodice
noteOn(0, note, 120) reda nota muzicala note; pentru bank-ul 0x78 valoarea
lui note selecteaza si instrumentul muzical (pentru bank-ul 0x78, valorile
posibile pentru note sunt intre 27 si 87).
noteOff(0, note, 120) opreste redarea notei muzicala note;
talkMIDI(0xB0, 0x07, volum) stabileste volumul instrumentului; valoarea
pentru volum este intre 0 si 127.
talkMIDI(0xC0, instrument, 0) stabileste instrumentul care va reda notele
muzicale; acest lucru este valabil doar pentru bank-urile 0X00 si 0X79; pentru
bank-ul 0X78, aceasta comanda nu are nici un efect.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

WiFly Shield
Daca ai nevoie sa obtii informatii direct din Internet folosind Arduino, sau
sa ai un server web ruland pe Arduino si vrei sa-l accesezi tu din Internet, si
toate astea fara fir de retea, atunci WiFly Shield este ceea ce ai nevoie.
Functioneaza prin WIFI, se conecteaza la un router si iti ofera conexiune la
Internet pe Arduino. Daca nu iti este foarte clar cum functioneaza o retea de
calculatoare (termeni gen IP, DNS, MAC, DHCP iti suna ciudat), atunci iti
recomand sa citesti mai intai sectiunea in care se discuta despre shield-ul
Ethernet pentru Arduino, sectiune in care am prezentat si aceste concepte.
Libraria de care vei avea nevoie in codul de mai jos o gasesti in aceasta
pagina http://www.robofun.ro/wifly_shield, descarc-o si instaleaz-o in mediul
tau Arduino inainte de a rula exemplul de mai jos.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

WiFly Shield Client Web


//pune "" la ambele daca nu ai parola la WIFI
#define SSID "networkID"
#define PASSPHRASE "password"
#include "WiFly.h"
#include "Credentials.h"
Client client("google.com", 80);
void setup() {
Serial.begin(9600);
WiFly.begin();
if (!WiFly.join(SSID, PASSPHRASE)) {
Serial.println("Conectare la reteaua WIFI esuata.");
}

Serial.println("Conectare in progres...");
if (client.connect()) {
Serial.println("Conectare reusita !");
client.println("GET /search?q=arduino HTTP/1.0");

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

client.println();
} else {
Serial.println("Conectare esuata");
}
}
void loop() {
if (client.available()) {
char c = client.read();
Serial.print(c);
}

if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
for(;;)
;
}

Daca ai parcurs deja sectiunea despre Ethernet shield, vei vedea ca ceea
ce avem mai sus seamana foarte mult cu codul de acolo. Practic, se modifica
doar modul de conectare la retea. Sunt de remarcat cele doua constante de la
inceputul programului, care iti permit sa declari care este identificatorul tau de
retea WIFI si care este parola. Daca ai o retea fara parola, pune "" in loc de
parola si de id de retea.
Codul se conecteaza la serverul google.com si afiseaza in Serial Monitor
rezultatele cautarii pentru termenul "arduino" (tu vei vedea informatie in
format HTML, asa cum am explicat la sectiunea despre Ethernet Shield).

WiFly Shield Server Web


//pune "" la ambele daca nu ai parola la WIFI
#define SSID "networkID"
#define PASSPHRASE "password"
#include "WiFly.h"
#include "Credentials.h"
Server server(80);
void setup() {
WiFly.begin();
if (!WiFly.join(SSID, PASSPHRASE)) {
Serial.println("Conectare la reteaua WIFI esuata.");
}

Serial.begin(9600);
Serial.print("IP: ");

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
Serial.println(WiFly.ip());
server.begin();
}
void loop() {
Client client = server.available();
if (client) {
boolean current_line_is_blank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n' && current_line_is_blank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
for (int i = 0; i < 6; i++) {
client.print("* pe portul analogic ");

client.print(i);

client.print(" s-a citit valoarea ");

client.print(analogRead(i));
client.println("<br />");

}
break;

}
if (c == '\n') {
current_line_is_blank = true;
} else if (c != '\r') {
current_line_is_blank = false;
}

}
}
delay(100);
client.stop();

Exemplul de mai sus creaza un server web care ruleaza pe placa Arduino
si la fiecare cerere din browser raspunde cu valorile de pe porturile analogice,
ca mai jos. IP-ul server-ului este alocat in mod dinamic de router, asa ca, pentru
a sti care este adresa pe care o folosesti in browser, iti recomand sa deschizi
Serial Monitor si sa vezi in debug IP-ul alocat placii.

Stocarea online a datelor culese de Arduino, folosind Google Docs


Google Docs reprezinta o solutie excelenta pentru a loga online date
culese cu Arduino. Temperatura, umiditatea sau presiunea atmosferica sunt
exemple foarte bune in acest sens. Trimiterea lor online intr-un document Excel
se bazeaza pe functionalitatea Forms, oferita de Google Docs. Ideea de
http://www.robofun.ro/forum

L10
http://www.robofun.ro

Curs Gratuit Arduino si Robotica

principiu este de a genera un request HTTP din Arduino, care request sa fie
perfect similar cu cel generat de pagina din form-ul Google. Astfel, Google este
"pacalit" sa creada ca datele trimise de Arduino sunt de fapt trimise de un form
creat cu Google Docs.
Pentru acest proiect ai nevoie un Arduino cu conectare la Internet. Ai de
ales intre Arduino Ethernet sau Arduino UNO + Ethernet Shield. Senzorii sunt la
alegerea ta, in functie de ce date vrei sa trimiti in Google Docs. Pentru
exemplul de mai jos, eu am ales un BMP085 (ca sa masor presiunea
atmosferica si temperatura), si un HIH-4030 pentru masurarea umiditatii.
Evident ca tu poti alege ce senzori doresti.
Mai departe, acceseaza http://docs.google.com si creaza un document tip
spreasheet ("CREATE", apoi "Spreadsheet"). Ar trebui sa vezi un document
similar unui document Excel. Din meniul "Tools", alege "Create a form". Form-ul
creat ar trebui sa aiba cate un camp de tip "Text" pentru fiecare senzor pe care
il vei trimite catre Google Docs. Spre exemplu, eu am creat un camp
"temperatura", un camp "umiditate" si un camp "presiune", toate de tip "Text".
Selecteaza apoi din meniul "Form (0)" intrarea "Go to live form". Vei
vedea formularul creat de Google Docs pentru culegerea datelor. Mai departe,
va trebui sa analizezi codul sursa al paginii (in functie de browser-ul pe care il
folosesti, acest lucru se face diferit spre exemplu in Chrome trebuie sa dai
click dreapta si apoi sa selectezi "View page source"). In codul sursa al paginii
localizeaza sirul de caractere "formkey=". Vei gasi ceva de genul
"formkey=dE9MTmlMc3N1RVNfdVJIRkFMNDltaXc6MQ". Acest sir de caractere
reprezinta identificatorul unic al formularului tau, identificator pe care Arduino il
va utiliza ca sa trimita informatiile. Localizeaza si campurile in care introduci
informatia utila (va fi simplu, pentru ca vor fi prefixate de numele campurilor
pe care le-ai dat tu cand ai creat formularul vezi si imaginea de mai jos).
Numele acestor campuri ar trebui sa fie ceva de genul "entry.0.single",
"entry.1.single", "entry.2.single" si tot asa pentru toate campurile care le-ai
declarat.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

Mai departe, ca sa trimita datele catre Google, Arduino va trimite o cerere


HTTP catre serverul Google, care cerere va fi identica cu cea pe care o trimite
browser-ul atunci cand apesi pe butonul "Submit" din formular. Practic, serverul
Google va fi convins ca acele date vin din formularul obisnuit si nu din Arduino.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10

Codul
sursa
integral
pentru
Arduino
il
gasesti
aici
http://robofun.ro/blog/cum-sa-trimiti-loghezi-pe-google-docs-temperaturapresiunea-atmosferica-si-umiditatea-direct-din-arduino . In cele ce urmeaza
vom analiza partile interesante din cod. Chiar la inceput ai o declaratie de
forma "char formkey[] = "dG9HWmNXWjNRdWhBWG5ITlpNeUVBU2c6MQ";"
Aici va trebui sa modifici cheia din cod cu cheia din documentul tau, pe care ai
obtinut-o mai sus. Mai departe, in functia "loop" vei gasi denumirile campurilor
din document, pe care le-ai identificat deja mai sus. Va trebui sa modifici
aceasta zona din cod pentru a trimite exact informatiile culese de tine. Spre
exemplu, in cazul meu codul este ca mai jos :
String data;
data+="";

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L10
data+="entry.2.single=";
data+=temperatura;
data+="&entry.3.single=";
data+=presiune;
data+="&entry.4.single=";
data+=umiditate;
data+="&submit=Submit";

Adaug in varianta data rand pe rand denumirea unui camp si valoarea


acestuia, citita de Arduino. Mai departe, codul trimite request-ul catre serverul
Google pentru a inregistra informatia in document.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11
Arduino Leonardo pe post de tastatura
Exact, daca ai un Arduino Leonardo, poti sa-l faci sa se comporte ca o
tastatura sau un mouse absolut obisnuite (din punct de vedere al
calculatorului). Este o facilitate a noului microcontroller Atmega32u4. Tot ce ai
facut este ca in codul Arduino sa apelezi libraria Keyboard si calculatorul (la
care ai conectat Arduino prin USB) se va comporta ca si cum ai fi apasat taste
pe tastatura obisnuita.
Inainte de a trece mai departe, este necesar sa iti atrag atentia asupra
unui lucru care ar putea fi neplacut. Imediat ce ai programat placa sa trimita
taste apasate catre calculator, Arduino le va trimite tot timpul, pana cand ii
spui sa se opreasca. Singurul mod in care ii poti spune sa se opreasca este
incarcand alt program. Dar daca ai pus placa sa trimita taste prea rapid, atunci
nu vei putea face acest lucru, pentru ca se vor apasa taste chiar in mediul de
dezvoltare, acolo unde vei vrea sa scrii codul. Ca sa nu se intample asta, ai
grija ca sa existe un mecanism prin care sa opresti trimiterea de taste (cum ar
fi un buton conectat la Arduino, sau un delay mare pus un setup). Cu un delay
in setup, poti oricand sa dai un reset placii altfel incat sa o fortezi sa ruleze
functia setup, si apoi cat timp placa sta in delay, tu ii vei putea modifica
programul.
Exemplu 1 void setup() {
delay(15000);
Keyboard.begin();
}
void loop() {
Keyboard.print("Hello!");
delay(10000);
}

In exemplul de mai sus, nu facem altceva decat sa initializam modul


tastatura (Keyboard.begin()) si apoi sa trimitem la fiecare 10 secunde sirul de
caractere "Hello" (exact ca si cum am apasa pe tastatura consecutiv tastele H
e l l o. Am pus un delay in setup de 15 secunde in ideea ca atunci cand vei vrea
sa schimbi programul placii, sa poti da un reset si astfel sa ai la dispozitie 15
secunde pentru a incarca noul program.
Cu Arduino Leonardo poti apasa si tastele CTRL, ALT, sau SHIFT, ca mai
jos.

http://www.robofun.ro/forum

http://www.robofun.ro

L11

Curs Gratuit Arduino si Robotica

Exemplu 2 char ctrlKey = KEY_LEFT_CTRL;


void setup() {
Keyboard.begin();
delay(15000);
}
void loop() {
delay(1000);
Keyboard.press(ctrlKey);
Keyboard.press('n');
delay(100);
Keyboard.releaseAll();
delay(30000);
}

Dupa ce au trecut cele 15 secunde din setup, Arduino apasa tasta CTRL
(si o mentine apasata), apoi apasa tasta "n" si apoi elibereaza ambele taste.
Efectul, pe majoritatea sistemelor de operare, este deschiderea unei ferestre
noi.
Mai jos, lista tuturor comenzilor asociate tastaturii emulate de Arduino.
Keyboard.begin()
- deschide o sesiune de emulare tastatura. Este necesar sa apelezi
aceasta comanda inainte de a le putea folosi pe restul.
Keyboard.end()
- inchide o sesiune de emulare tastatura.
Keyboard.press(<TASTA>)
- apasa si mentine apasata o tasta (utila pentru a trimite combinatii de
taste, gen CTRL + N).
Keyboard.print(<SIR_DE_TASTE>)
- apasa si elibereaza o tasta sau un sir de taste. Util pentru a apasa o
tasta sau un sir de taste apasate succesiv spre calculator.
Keyboard.println(<SIR_DE_TASTE>)
- acelasi lucru ca print, doar ca la final apasa si tasta ENTER. Util pentru a
introduce informatie intr-un document text si a trece automat la linie noua.
Keyboard.release(<TASTA>)
- elibereaza o tasta apasata anterior (cu Keyboard.press()).
Keyboard.releaseAll()
- elibereaza toate tastele apasate anterior (cu Keyboard.press())
Keyboard.write(<TASTA>)
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11

apasa si elibereaza o tasta.

Arduino Leonardo pe post de mouse


Exact in acelasi mod cum emuleaza tastatura, Arduino Leonardo poate fi
vazut de calculator si ca mouse. Poate misca cursorul pe ecran la orice pozitie
si poate simula apasarea pe butoanele mouse-ului.
Exemplu 1 void setup(){
Mouse.begin();
}
void loop(){
Mouse.move(50, 50, 0);
delay(10000);
}

Codul de mai sus initializeaza modul mouse, iar apoi la fiecare 10


secunde misca pointer-ul mouse-ului cu 50 de pixeli pe fiecare axa.
Mai jos, lista tuturor comenzilor asociate controlului mouse-ului din
Arduino Leonardo.
Mouse.begin()
initializeaza modul de control al mouse-ului.
Mouse.end()
inchide sesiunea de emulare mouse.
Mouse.click(<BUTON>)
- apasa si elibereaza un buton al mouse-ului. Valori posibile sunt
MOUSE_LEFT
,
MOUSE_RIGHT,
MOUSE_MIDDLE.
Astfel,
Mouse.click(MOUSE_LEFT) genereaza un click obisnuit pe butonul din stanga al
mouse-ului.
Mouse.move(<X>, <Y>, <SCROLL>)
- genereaza o miscare a cursorului de mouse pe fiecare axa in parte.
Primul parametru este miscarea pe axa orizontala, al doilea pe axa verticala,
iar al treilea reprezinta deplasarea rotitei de scroll.
Mouse.press(<BUTON>)
- apasa (fara a elibera) unul dintre butoanele mouse-ului. Valori posibile
sunt
MOUSE_LEFT
,
MOUSE_RIGHT,
MOUSE_MIDDLE.
Astfel,
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11
Mouse.press(MOUSE_LEFT) este ca si cum am apasa manual pe butonul din
stanga al mouse-ului, fara a-l elibera.
Mouse.release()
elibereaza unul dintre butoanele mouse-ului apasate anterior cu Mouse.press.
Valori posibile sunt MOUSE_LEFT , MOUSE_RIGHT, MOUSE_MIDDLE.

http://www.robofun.ro/forum

http://www.robofun.ro

L12

Curs Gratuit Arduino si Robotica

Logare presiune atmosferica, umiditate, nivel de iluminare si


temperatura in Excel, cu Arduino Leonardo
Folosindu-ne de capacitatea lui Arduino Leonardo de a emula o tastatura,
devine foarte simplu sa logam informatie pe calculator. Tot ce avem de facut
este sa apasam din Arduino acele taste corespunzatoare valorilor citite (ca sa
cand le-am introduce manual din tastatura).
Acest proiect foloseste un senzor BMP085 (presiune atmosferica si
temperatura), un senzor de lumina brick si un senzor de umiditate brick,
impreuna cu un Arduino Leonardo pentru a introduce periodic informatie intr-un
document Excel.
Primul pas este conectarea componentelor la Arduino, ca in schema de
mai jos. Probabil ca la prima vedere schema de conectare pare un fel de
paianjen cu multe picioare, dar daca vei reveni la schema de conectare pentru
fiecare senzor in parte (in sectiunea unde fiecare senzor este prezentat
separat), atunci lucrurile vor deveni mult mai simple. Cele doua componente
brick sunt conectate la 5V si GND pentru alimentare, iar apoi la pinii analogici
A0 si A1. Senzorul BMP085 este conectat la cei doi pini I2C SDA si SCL (care in
cazul Arduino Leonardo sunt in partea din stanga sus).

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L12

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L12
Mai departe, codul sursa nu face altceva decat sa combine exemplele
care demonstreaza citirea datelor de la senzori cu cel care demostreaza
utilizarea Arduino Leonardo pe post de tastatura.
#include <Wire.h>
#include <BMP085.h>
BMP085 dps = BMP085();
long Temperature = 0, Pressure = 0;
void setup(void) {
Serial.begin(9600);
Wire.begin();
delay(1000);
dps.init();
delay(5000);
Keyboard.begin();
}
void loop(void) {
dps.getTemperature(&Temperature);
dps.getPressure(&Pressure);
int nivelIluminare = analogRead(1);
int nivelUmiditate = analogRead(0);

Keyboard.print(String(Temperature));
Keyboard.print(KEY_RIGHT_ARROW);
Keyboard.print(String(Pressure));
Keyboard.print(KEY_RIGHT_ARROW);
Keyboard.print(String(nivelIluminare));
Keyboard.print(KEY_RIGHT_ARROW);
Keyboard.print(String(nivelUmiditate));
Keyboard.println();

Mouse cu accelerometru si Arduino Leonardo


Acest proiect se bazeaza pe capacitatea placii Arduino Leonardo de a se
comporta ca mouse. Prin combinarea unui Arduino Leonardo cu un
accelerometru pe 3 axe, vom obtine un mouse pe care il vom controla prin
miscarea mainii. Poti folosi orice fel de accelerometrul doresti. In cele ce
urmeaza vom folosi un accelerometru ADXL335, pentru simplitate.
Accelerometrul se conecteaza la Arduino in modul obisnuit, ca in schema mai
jos.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11
#define SENSIBILITATE_X 3
#define SENSIBILITATE_Y 3
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
Mouse.begin();
}
void loop() {
float xAcc=readAcc(0);
float yAcc=readAcc(1);
float zAcc=readAcc(2);
Serial.print("Acceleratie X: ");
Serial.print(xAcc,DEC);
Serial.print("Acceleratie Y: ");
Serial.print(yAcc,DEC);
Serial.println();
delay(50);
Mouse.move(xAcc * SENSIBILITATE_X, yAcc * SENSIBILITATE_Y, 0);
}
float readAcc(int port) {
int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11

Arduino 3.3 V

ADXL335 VCC

Arduino GND

ADXL335 GND

Arduino Analog0

ADXL335 X

Arduino Analog1

ADXL335 Y

Arduino Analog2

ADXL335 Z

Arduino 3.3

Arduino AREF

Constantele SENSIBILITATE_X si SENSIBILITATE_Y definesc cat de mult se


misca mouse-ul pe ecran atunci cand miscam accelerometrul. Cu cat valorile
pentru aceste constante sunt mai mari, cu atat mouse-ul se va misca mai mult
pe ecran atunci cand miscam accelerometrul. Esti liber sa te joci cu aceste
constante pana cand miscarea pe ecran este exact asa cum vrei tu.
Principiul de functionare al acestui mouse se bazeaza pe faptul ca in orice
locatie de pe Pamant avem o acceleratie gravitionala 1g, indreptata
intotdeauna pe directia verticala. Cand accelerometrul ADXL335 este orientat
pe directie orizontala, atunci pe axa X si pe axa Y acceleratiile citite sunt zero.
Este o acceleratie de 1g citita pe axa Z. Atunci cand inclinam accelerometrul in
plan, acceleratia de 1g care se manifesta doar pe axa Z cand accelerometrul
este orizontal, incepe sa se manifeste si pe axele X si Y. Astfel daca inclinam
accelerometrul la un unghi de 45 de grade pe axa X, vom avea o acceleratie de
0.5g pe axa X.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11

Acceleratiile citite de accelerometru sunt inmultite cu o valoare constanta


(in cazul nostru cu 3, valoarea constantei SENSIBILITATE_X) si mouse-ul este
miscat pe ecran corespunzator valorii obtinute. Poate vei spune ca o deplasare
de 3 pixeli atunci cand accelerometrul este inclinat maximum este putin, dar
adu-ti aminte ca functia loop se executa non-stop, astfel incat mouse-ul este
miscat cu 3 pixeli la fiecare 50 de milisecunde (pentru ca in loop exista o
instructiune delay(50)).
Daca ti se pare complicat sa tii mouse-ul fix pe ecran (pentru ca este
destul de dificil sa tii ADXL335 perfect orizontal), atunci putem imbunatati
programul de mai sus prin setarea unei zone in care mouse-ul nu se misca
deloc pe ecran, ca mai jos (modificarile in bold) :
#define
#define
#define
#define

SENSIBILITATE_X 3
SENSIBILITATE_Y 3
ZONA_MOARTA_X 0.3
ZONA_MOARTA_Y 0.3

void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
Mouse.begin();
}
void loop() {
float xAcc=readAcc(0);
float yAcc=readAcc(1);
float zAcc=readAcc(2);
Serial.print("Acceleratie X: ");
Serial.print(xAcc,DEC);
Serial.print("Acceleratie Y: ");
Serial.print(yAcc,DEC);
Serial.println();
delay(50);

http://www.robofun.ro/forum

http://www.robofun.ro

L11

Curs Gratuit Arduino si Robotica

int miscareX = 0;
if (abs(xAcc) > ZONA_MOARTA_X) {
miscareX = xAcc * SENSIBILITATE_X;
}

int miscareY = 0;
if (abs(yAcc) > ZONA_MOARTA_Y) {
miscareY = yAcc * SENSIBILITATE_Y;
}
Mouse.move(miscareX, miscareY, 0);
}
float readAcc(int port) {
int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

Am introdus doua constante, ZONA_MOARTA_X si ZONA_MOARTA_Y, care


definesc valorile acceleratiei sub care mouse-ul nu face nici o miscare. Astfel,
daca tii accelerometrul intr-o pozitie aproape de orizontala, mouse-ul nu se
misca deloc pe ecran.
In final, ca sa poti misca simplu accelerometrul, iti sugerez sa il prinzi pe
o manusa de piele (cumparata de la standul cu elemente de protectie din
Hornbach, BricoStore sau Practiker).
Urmatoarea extindere a acestui proiect este sa adaugi sistemului si doua
butoane brick, obtinand astfel un mouse perfect functional. Schema de
conectare este cea de mai jos. Butoanele le poti monta pe cate un deget al
fiecarei manusi, astfel incat sa le poti apasa cu degetul mare (prin
suprapunerea degetului mare peste unul dintre cele doua degete pe care sunt
lipite butoanele).

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11
#define
#define
#define
#define

SENSIBILITATE_X 3
SENSIBILITATE_Y 3
ZONA_MOARTA_X 0.3
ZONA_MOARTA_Y 0.3

#define BUTON1_PIN 9
#define BUTON1_PIN 10
#define DEBOUNCE_TIME 100
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
pinMode(BUTON1_PIN, INPUT);
pinMode(BUTON2_PIN, INPUT);

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11
Mouse.begin();
}
long lastButtonPress1 = 0;
long lastButtonPress2 = 0;
void loop() {
int buton1 = digitalRead(BUTON1_PIN);
int buton2 = digitalRead(BUTON2_PIN);
if (buton1 == 1) {
if ((millis() - lastButtonPress1) > DEBOUNCE_TIME) {
lastButtonPress1 = millis();
Mouse.click(BUTTON_LEFT);
}
}
if (buton2 == 1) {
if ((millis() - lastButtonPress2) > DEBOUNCE_TIME) {
lastButtonPress2 = millis();
Mouse.click(BUTTON_RIGHT);
}
}
float xAcc=readAcc(0);
float yAcc=readAcc(1);
float zAcc=readAcc(2);
Serial.print("Acceleratie X: ");
Serial.print(xAcc,DEC);
Serial.print("Acceleratie Y: ");
Serial.print(yAcc,DEC);
Serial.println();
delay(50);
int miscareX = 0;
if (abs(xAcc) > ZONA_MOARTA_X) {
miscareX = xAcc * SENSIBILITATE_X;
}
int miscareY = 0;
if (abs(yAcc) > ZONA_MOARTA_Y) {
miscareY = yAcc * SENSIBILITATE_Y;
}
Mouse.move(miscareX, miscareY, 0);
}
float readAcc(int port) {
int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

De remarcat in codul de mai sus este constanta DEBOUCE_TIME. Asa cum


http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

L11

am povestit mai pe larg in cadrul sectiunii despre butoane brick, atunci cand se
apasa un buton, semnalul receptionat de catre Arduino variaza de cateva ori
intre 0 si 1 (nu trece instantaneu din 0 in 1). Acest lucru se intampla datorita
faptului ca atunci cand apasam butonul, lamelele metalice care inchid
contactul nu se ating perfect. Ca sa evitam ca Arduino sa citeasca mai multe
apasari de buton, vreme de 100 de milisecunde dupa prima apasare
receptionata (valoarea lui DEBOUNCE_TIME) vom ignora orice alta apasare.
Acest lucru inca permite conceptul de dublu click (doar ca diferenta intre doua
click-uri succesive va fi exact DEBOUNCE_TIME milisecunde). Daca dublu click
nu este sesizat corect de calculatorul tau, poti sa micsorezi valoarea acestei
constante, sau sa modifici pe calculator durata intre cele doua click-uri
succesive pentru a obtine un dublu click.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Analogie electricitate curgerea fluidelor


Una dintre cele mai simple modalitati de a intelege conceptele de baza
ale electricitatii este de a apela la o analogie cu modul de curgere al fluidelor,
pe care il intelegem intuitiv din experienta proprie. Astfel, sa ne inchipuim apa
curgand printr-un mecanism de tevi, de diverse diametre. Sa ne inchipuim ca
avem pompe care imping apa prin tevi, pompe cu puteri diverse. Acum, daca in
loc de apa ne inchipuim un flux de electroni, in loc de tevi, fire conductoare si
in loc de pompe surse de tensiune (baterii sau alimentatoare), obtinem o
analogie care functioneaza aproape perfect pentru a intelege teoria
electricitatii.
Astfel, la un moment dat printr-o anumita teava trece o anumita cantitate
de apa. La fel, printr-un fir, la un moment dat trece o anumita cantitate de
curent. Cat de mult curent trece printr-un fir la un moment data este un
element caracterizat de intensitatea curentului electric, masurata in
Amperi.
Daca ne inchipuim un circuit format din mai multe tevi mufate intre ele
sub forma unui circuit inchis, este clar ca prin fiecare teava circula exact
aceeasi cantitate de apa la un moment dat (apa pleaca din pompa, trece prin
fiecare teava, si apoi se intoarce inapoi in pompa, exact cata apa pleaca, exact
atata se intoarce). Exact in acelasi mod, intensitatea curentului electric este
aceeasi in oricare punct al unui circuit electric simplu (fara bifurcatii). Altfel
spus, prin oricare punct al unui circuit fara bifurcatii trece aceeasi
cantitate de curent.
Mai departe, daca ne gandim ca tevile au diametre diferite, dar prin ele
circula aceeasi cantitate de apa, atunci presiunea apei este diferita in fiecare
teava, in functie de diametrul acesteia. Echivalentul presiunii apei din tevi, in
cazul curentului electric, este potentialul electric (sau tensiunea) si se
masoara in Volti.
Daca ai udat vreodata cu furtunul in gradina, atunci stii ca pentru a
creste presiunea apei, tot ce ai de facut este sa strangi furtunul (sa-i micsorezi
diametrul). Diametrul tevii (practic, rezistenta pe care o opune teava trecerii
apei) este echivalentul in cazul circuitelor electrice cu rezistenta elementului
electric, si se masoara in Ohm. Exista elemente electrice speciale, care se
cheama rezistoare si care sunt folosite tocmai pentru rezistenta cu care se
opun trecerii curentului electric. Daca ne gandim ca in cazul furtunului cu apa,
cu cat diametrul furtunului este mai mic (deci rezistenta opusa apei este mai
mare) cu atat presiunea apei este mai mare, atunci putem scrie :
intensitatea = tensiunea / rezistenta
Daca notam fiecare marime cu o singura litera, obtinem :

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica


I=U/R

care reprezinta legea lui Ohm.


Mai departe, fiecare pompa de lichid este capabila sa impinga lichidul in
tevi cu o anumita presiune. In cazul unui surse electrice, echivalenta este
tensiunea electromotoare a sursei (notata cu U sau cu V). In plus, o pompa
de lichid este capabila sa impinga la un moment dat doar o cantitate finita de
apa (adica, daca la pompa nu conectam absolut nimic si lasam apa sa curga
liber adica fara a intampina nici o rezistenta), atunci pompa va impinge cea
mai mare cantitate de lichid pe secunda. Exact la fel se intampla si in cazul
surselor electrice (baterii sau alte surse). O sursa este capabila sa furnizeze un
curent de maxim N amperi. Din acest motiv, intotdeauna vom intalni scris pe
alimentatoarele electrice "9 V, 1 A" sau "12 V, 4 A". Este important de inteles
ca aceasta valoare a curentului notat pe alimentator reprezinta valoarea
maxima a curentului pe care acea sursa este capabila sa il furnizeze (atunci
cand nu are nici o rezistenta la borne) si NU valoarea curentului pe care il
furnizeaza intotdeauna, in orice circuit. In cazul unui pompe care impinge apa
in tevi, cantitatea de apa din teava (adica intensitatea) este data de diametrul
tevii (adica de rezistenta circuitului), tot asa si in cazul circuitelor electrice
intensitatea curentului electric este stabilita de catre circuitul electric, si nu
este un parametru al sursei. Sursa limiteaza insa superior aceasta valoare. Din
aceasta cauza, nu este nici un fel de problema sa alimentam un motor care
functioneaza la 6 Volti si 1 Amper cu o sursa electrica pe care scrie "6V 4A".
Acei 4 Amperi notati pe sursa reprezinta valoarea maxima a intensitatii
curentului electric pe care acea sursa ii poate furniza. Cuplata insa cu motorul
de 1 Amper, prin circuit se va stabili un curent stabilit de motor (care va fi mai
mic de 1 Amper atunci cand motorul se invarte liber, si se va apropia de 1
Amper atunci cand blocam rotirea motorului folosind un cleste).
Recapituland, avem pana acum :
intensitatea curentului electric (notata cu I si masurata in Amperi (A)) = cata
apa trece prin tevi
tensiunea intr-un punct din circuit (notata cu V sau U si masurata in Volti (V) )
= presiunea apei intr-un numit punct
rezistenta (notata cu R si masurata in Ohm) = ce rezistenta opune teava
trecerii apei (cat de subtire este teava)
prin orice punct al unui circuit electric simplu (fara bifurcatii) trece acelasi
curent I.
I = U / R (legea lui Ohm) (cantitatea de apa este direct proportionala cu
presiunea cu care este impinsa apa si invers proportionala cu rezistanta opusa
apei de tevi).

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Divizorul de tensiune
Sa consideram circuitul electric de mai sus, format dintr-o sursa si doua
rezistoare inseriate. Curentul stabilit prin circuit este determinat foarte simplu
ca fiind I = U / (R1 + R2) (legea lui Ohm). Mai departe, daca ne concentram
doar pe R2, aceeasi lege se aplica si pentru ea, luata separat. In plus, am mai
stabilit ca in orice punct al unui circuit electric simplu (fara bifurcatii) avem
aceeasi intensitate a curentului electric. Asadar, putem scrie : I = U2 / R2 (unde
U2 este caderea de tensiune la capetele rezistorului R2. Putem astfel determina
U2 ca fiind U2 = I * R2, adica, folosind si prima relatie de mai sus : U2 = U *
R2 / (R1 + R2). Aceasta relatie, care ne da caderea de tensiune pe rezistorul R2
in functie de R1, R2 si U este foarte utila intr-o multitudine de situatii. Spre
exemplu, daca in loc de R1 (care in cazul nostru este fix), avem un senzor care
isi modifica rezistenta in functie de un element extern (de exemplu un
fotorezistor), atunci masurand cu Arduino caderea de tensiune U2 (pe un pin
analogic), indirect, masuram si valoarea lui R1, deci implicit nivelul de
iluminare al incaperii.

Circuite electrice cu bifurcatii


Desi nu te vei intalni prea des cu astfel de circuite, este interesant sa ne
aruncam o privire si asupra lor. Este vorba despre un circuit care la un moment
dat se separa, ca cel de mai jos.
Daca vom apela iarasi la analogia cu furtunul si cu apa, este evident ca
volumul de apa care trece prin sectiunea S este egal cu suma volumelor de apa
care trec prin sectiunile S1 si S2. Exact la fel, intensitatea curentului electric
care trece prin sectiunea S1 este suma intensitatilor curentilor electrici care
trec prin sectiunile S1 si S2. Adica :
I = I1 + I2
care este prima lege a lui Kirchoff.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Sa luam apoi bucla formata din R1 si R2. Nu stiu cat de evident este
acest lucru din analogia cu curgerea lichidelor, dar intotdeauna pe o bucla de
circuit inchisa suma caderilor de tensiune este zero. Adica :
U1 + U2 = 0
care este a doua lege a lui Kirchoff.
Gata ! Inarmati cu legea lui Ohm si cu cele doua legi ale lui Kirchoff,
putem acum determina curenti si tensiuni pe circuite oricat de complicate.

Condensatorul
Un condensator nu este altceva decat o galeata in care cad electronii.
Cand galeata s-a umplut, sarcinile incep sa curga mai departe pe fir. Din acest
motiv, vom intalni folositi condesatori peste tot unde avem nevoie de un buffer
de curent. Spre exemplu, aproape de alimentarea unui motor de curent
continuu. Astfel, atunci cand motorul porneste, are nevoie de o mare cantitate
de curent. Posibil chiar mai mare decat poate da sursa. In aceasta situatie, un
condensator de valoare mare va stoca acel curent in regimul de functionare
normal si il va oferi motorului la pornire. In acest fel, si restul dispozitivelor din
circuit vor avea suficient curent ca sa functioneze.

Semnalul PWM
Semnalul PWM (sau Pulse Width Modulation) este un tip de semnal pe
care il vom intalni destul de des cand lucram cu Arduino. Dat fiind ca Arduino
scoate porturile lui digitale doar semnal digital (cu doar doua nivele 5V si 0V),
semnalul PWM reprezinta o modalitate de a da in exterior informatie care sa
varieze pe mai multe trepte. Astfel, daca modificam raportul intre cat timp sta
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

semnalul in 5V si cat timp sta semnalul in 0V, obtinem un semnal a carui


putere se modifica in trepte. Acest raport il vom numi in cele ce urmeaza
"factor de umplere" al semnalului PWM.
Arduino poate genera un semnal de tip PWM doar pe o parte din porturile
digitale. Astfel, pentru Arduino UNO, porturile capabile de semnal PWM sunt : 3,
5, 6, 9, 10 si 11 iar pentru Arduino Mega porturile capabile de semnal PWM
sunt de la pinul 2 (inclusiv) pana la pinul 13, si de la pinul 44 la pinul 46 .

Una dintre cele mai comune aplicatii ale semnalului PWM este controlul
motoarelor de curent continuu. Un motor de curent continuu caruia i s-a aplicat
un semnal PWM cu factor de umplere 100% va functiona la viteza maxima.
Daca factorul de umplere scade la 50%, si viteza motorului se va modifica in
consecinta (tinand cont ca doar o jumatate din timp mai este actionat practic,
cealalta jumatate din timp invartindu-se din inertie).

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Cum sa faci o floare sa te traga de maneca atunci cand uiti sa o uzi


Cu un Arduino, destul de simplu. Iti mai trebuie doar un senzor de
umiditate "home-made" format din doua fire introduse in ghiveci, si un
dispozitiv care sa alerteze (un led care sa se aprinda atunci cand planta vrea
apa, un shield Ethernet care sa te contacteze pe Twitter sau sa-ti dea email
atunci cand este cazul, sau chiar un shield GSM care sa iti dea SMS sau apel de
voce pe telefon).
Schema de principiu este cea de mai jos.

In ghiveci avem cei doi electrozi metalici. Pot fi din orice metal, dar
pentru a nu oxida, cel mai bine este sa fie din inox. Daca este dificil sa gasiti
sarma sau electrozi din inox, sunt la fel de bune si doua cozi de furculita din
inox. Acestea se infig la o distanta de circa 1 cm intre ele (nu este foarte
importanta distanta, important este sa NU se atinga si sa nu fie foarte
departate - gen unul intr-o margine de ghiveci si celalalt in cealalta margine).
Urmatorul pas este sa stabilim valoarea rezistorului asociat celor doi
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

electrozi infipti in pamant. Pentru aceasta, avem nevoie de un ohmetru, aparat


de masura pentru rezistenta. Cei doi electrozi infipti in sol (sau cozi de furculita
din inox), impreuna cu pamantul dintre ei, formeaza un rezistor a carui valoare
depinde de cat de umed este pamantul. Cu cat mai umed este pamantul, cu
atat avem o rezistenta mai mica asociata sistemului. Folosind ohmetrul,
masoara valoarea rezistentei electrice intre cei doi electrozi. Porneste cu scala
aparatului in zona de megaohmi, si modifica scala pana cand obtii o valoare.
Valoarea depinde de tipul pamantului din ghiveci, de cat de departe ai infipt
electrozii, si de cat de ud este pamantul cand faci masuratoarea. Dupa ce ai
obtinut o valoare, alege o valoare similara si pentru rezistorul conectat in
sistem.
Mai departe, asambleaza sistemul conform schemei de mai sus. Ceea ce
obtii este de fapt un banal divizor de tensiune. Unul dintre rezistori este fizic,
montat in schema, iar cel de-al doilea este constituit de cei doi electrozi
impreuna cu pamantul dintre ei din ghiveci. Atunci cand valoarea rezistorului
format de cei doi electrozi se modifica (pentru ca pamantul se usuca sau
devine mai ud), atunci si valoarea citita de Arduino se modifica.
De aici incolo, tot ce ai de facut este sa testezi iar si iar, pentru a obtine
exact valorile corespunzatoare pentru a genera alarme. Incepe cu pamant
perfect uscat, si noteaza valoarea citita de Arduino pe portul analogic 0. Poti
vedea aceasta valoare in debug, folosind un program simplu ca cel de mai jos.
void setup() {
Serial.begin(9600);
}
void loop() {
int v = analogRead(0);
Serial.println(v);
}

Adauga apoi apa, foarte putina, si asteapta sa se raspandeasca uniform


in intreg ghiveciul. Astfel vei obtine mai multe valori, fiecare valoare pentru
anumit nivel de umiditate din ghiveci. Mai departe, tot ce ai de facut este sa iti
alegi ce tip de alarma iti doresti. Poti alege un simplu led, un shield WIFI, un
shield Ethernet, sau un shield GSM.
Cel mai simplu este sa folosesti un led brick, conectat la unul dintre
porturile digitale (sa spunem portul digital 12). Pinul IN il conectezi la pinul
digital 12, iar pinul GND la pinul GND al Arduino.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

#define LED_PIN 12
#define ALARM 300
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
int v = analogRead(0);
if (v < ALARM) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
delay(5000);
Serial.println(v);
}

Ca sa stabilesti o valoare pentru constanta ALARM cat mai aproape de


realitate, poti chiar sa lasi sistemul pornit mai multe zile, si ori de cate ori
constati ca planta are nevoie de apa sa te conectezi mai intai cu laptop-ul la
Arduino si sa citesti valoarea citita de Arduino, inainte de a pune apa si dupa ce
ai pus apa.

Aceasta a fost lectia 14. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.
Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe
http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Arduino Leonardo, accelerometru MMA8452Q si Excel

Arduino 3.3 V

MMA8452Q 3.3V

Arduino GND

MMA8452Q GND

Arduino SDA

MMA8452Q SDA

Arduino SCL

MMA8452Q SCL

MMA8452Q este un accelerometru relativ ieftin, suficient de capabil pentru pretul lui. Suporta
trei game de acceleratie (2g, 4g, 8g). Conectarea la Arduino se face folosind patru fire, ca in figura de
mai sus. Putem utiliza un accelerometru de acest tip impreuna cu un Arduino Leonardo pentru a
construi o aplicatie ce detecteaza vibratiile cum ar fi cele produse de un cutremur. Datele vor fi salvate
intr-un fisier excel pentru a fi stocate in caz ca vrei sa le utilizezi la ceva anume. Sau se pot construi mai
multe module de acest gen si interconectate intr-o retea iar daca sunt gestionate de catre un server pot fi
transformate intr-o adevarata retea de detectie a cutremurelor.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Cum functioneaza?
Accelerometrul se alimenteaza direct de la platforma Arduino si comunica cu microcontroller-ul
prin doua fire: SDA si SCL. Orice vibratie mica, orice fel de miscare aplicata accelerometrului provoaca
o schimbare la cele trei variabile de iesire. Variabilele de iesire sunt raportate la cele trei axe de
coordonate: X, Y, Z.
Astfel daca accelerometrul va sta cu axa Z perpendiculara pe planul orizontal, la iesire vei
observa trei valori. Primele doua valori, X si Y vor oscila in jurul valorii lui 0, pentru ca nu actioneaza
nici o forta asupra lor dar oscileaza pentru ca e posibil ca accelerometrul sa aibe o usoara inclinatie. Dar
asupra lui Z actioneaza forta gravitationala. Imaginea luata din Excel arata mai bine aceasta
situatie(coloanele sunt in ordinea: X, Y si Z, cel din urma fiind in jurul valorii de 250, aproximativ 1g).

Cum incarci datele in Excel ? In primul rand, vrem ca datele referitoare la vibratii sa se incarce
in Excel doar atunci cand se detecteaza vibratii si nu incontinuu. Apoi datele vor fi grupate in cate 10
esantioane si se va face o medie. Va exista si un threshold sau valoare limita, depinde cum vrei sa o
numesti.
Daca media celor 10 esantioane depaseste valoarea thresholdului atunci Arduino va incarca
datele in Excel si va realiza acest lucru pentru 10 secunde. Apoi va realiza din nou o mediere asupra
altor 10 esantioane si din nou va testa daca s-a depasit thresholdul iar daca nu, el va ramane in
standby(nu va transmite nimic in Excel).
Cum transmite Arduino Leonardo setul de date in Excel ? Arduino Leonardo se va comporta ca
o tastatura sau keyboard emulator. Exista niste functii interesante care realizeaza acest lucru si vom
vedea in continuare.

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Codul sursa.
Avem doua directive ce reprezinta defapt librariile: I2C pentru protocol si libraria
accelerometrului. Se initializeaza si obiectul accel. Librariile se vor copia in directorul libraries din
directorul arduino.
arduino-1.0.1-windows/arduino-1.0.1/libraries/I2C/I2C.cpp
arduino-1.0.1-windows/arduino-1.0.1/libraries/I2C/I2C.h
arduino-1.0.1-windows/arduino1.0.1/libraries/MMA8453_n0m1/MMA8453_n0m1.cpp
arduino-1.0.1-windows/arduino1.0.1/libraries/MMA8453_n0m1/MMA8453_n0m1.h
#include <I2C.h>
#include <MMA8453_n0m1.h>
MMA8453_n0m1 accel;

Se declara variabilele de tip int:


int
int
int
int
int
int

contor;
X[10];
Y[10];
Z[10];
mediaX, mediaY, mediaZ;
thresX, thresY, thresZ;

Functia setup initializeaza variabilele declarate mai sus, adresa accelerometrului, modul de lucru
al senzorului si emularea tastaturii. Aici am stabilit si valorile de threshold si le poti modifica daca vrei sa
modifici sensibilitatea senzorului la vibratii.
void setup()
{
mediaX=0;
mediaY=0;
mediaZ=0;
thresX=10;
thresY=10;
thresZ=300;
accel.setI2CAddr(0x1D); //change your device address if necessary, default
is 0x1C
accel.dataMode(true, 2); //enable highRes 10bit, 2g range [2g,4g,8g]
Keyboard.begin();
}

Loop() este compusa din mai multe bucle for. Prima bucla se ocupa de esantionul de date, zece
la numar. Citirile de la accelerometru sunt salvate in trei vectori: X, Y, Z.
for (contor=0; contor <= 9; contor++) {
accel.update();
X[contor]=accel.x();

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Y[contor]=accel.y();
Z[contor]=accel.z();
}

Se executa o alta bucla for care aduna toate elementele vectorilor. Adunarea se imparte la 10,
adica se realizeaza media aritmetica. Media este utila daca apare o vibratie generata de o alta sursa, care
nu ne intereseaza si vrem sa o eliminam.
for (contor=0; contor <= 9; contor++) {
mediaX=mediaX+X[contor];
mediaY=mediaY+Y[contor];
mediaZ=mediaZ+Z[contor];
}
mediaX=mediaX/10;
mediaY=mediaY/10;
mediaZ=mediaZ/10;

Se compara cele trei medii cu 3 valori de threshold iar daca una dintre cele 3 medii(am folosit
functia OR) depaseste valoarea de threshold, se incarca datele in Excel. Echivalent, daca apare o vibratie
anormala si este importanta, aceasta este salvata in Excel prin apelarea functiei tipareste(). Am introdus
si o intarziere pentru ca a emula o tastatura la o viteza foarte mare, inseamna sa soliciti procesorul putin
mai mult. Am folosit intarzierea si ca etalon pentru a crea o perioada de aproximativ 10 secunde in care
datele sunt incarcate in Excel.
if (mediaX > thresX || mediaY > thresY || mediaZ > thresZ) {
for (contor=0; contor < 50; contor++){
accel.update();
tipareste();
delay(100);
}

Functia tipareste are urmatoarea forma. Se printeaza valorile x, y si z prin functia


keyboard.print(). Dar pentru o ordonare frumoasa in Excel se transmite Enter, sageata dreapta si sageata
sus. Pentru asta se apeleaza functiile keyboard.write(). In Excel se intampla cum ai vazut in imaginea
capturata mai sus. Datele sunt ordonate de sus in jos.
void tipareste(){
Keyboard.print(accel.x());
Keyboard.write(KEY_RETURN);
Keyboard.write(KEY_RIGHT_ARROW);
Keyboard.write(KEY_UP_ARROW);
Keyboard.print(accel.y());
Keyboard.write(KEY_RETURN);
Keyboard.write(KEY_RIGHT_ARROW);
Keyboard.write(KEY_UP_ARROW);

http://www.robofun.ro/forum

http://www.robofun.ro

Curs Gratuit Arduino si Robotica

Keyboard.print(accel.z());
Keyboard.write(KEY_RETURN);
Keyboard.write(KEY_RIGHT_ARROW);
Keyboard.write(KEY_UP_ARROW);

Keyboard.write(KEY_DOWN_ARROW);
Keyboard.write(KEY_LEFT_ARROW);
Keyboard.write(KEY_LEFT_ARROW);
Keyboard.write(KEY_LEFT_ARROW);
Keyboard.write(KEY_LEFT_ARROW);

Vedere din ansamblu:

Concluzie.
Am optat sa montez accelerometrul cu un surub direct pe Arduino, din cauza ca este simplu.
Aplicatia nu detecteaza vibratiile foarte mici. Personal am dat volumul tare pe o melodie rock dar
vibratiile produse nu au fost detectate de senzor. Aici intra in calcul si valoarea de threshold dar si
sensibilitatea accelerometrului pe gama de lucru(2, 4 sau 8g).
In schimb aplicatia da rezultate foarte bune la vibratiile banale. In cazul unui cutremur, stim ca
miscarea se poate propaga pe orizontala sau pe verticala, adica pe una dintre cele 3 axe.
Va urez succes in constructie.

http://www.robofun.ro/forum

Arduino comunicatia I2C intre 2 placi

Ce reprezinta I2C ?

I2C este ,in explicatia lui, cea mai simpla un protocol prin care poti realiza transfer de date intre
mai multe dispozitive. Spre exemplu, doresti ca in proiectul tau sa transmiti la distanta, prin intermediul
a 2 fire, pachete de date. Aceste pachete de date le vei transmite bit cu bit, unul dupa altul, catre unul
sau mai multe dispozitive. Sau invers, poti receptiona si poti stoca pachete de date de la unul sau mai
multe dispozitive.
Cum se conecteaza dispozitivele ?
In primul rand, ai aflat ca protocolul I2C iti permite sa transmiti si sa receptionezi pachete de
date sau bytes. In al doilea rand, le poti conecta sub forma unei retele pe o singura magistrala. Poti
conecta in jur de 100 de placi Arduino folosind doar 2 fire, unul de date si unul de clock.
Conceptul de master si slave ?
Protocolul I2C introduce ideea ca o singura placa trebuie sa fie master, iar restul placilor trebuie
sa fie slave-uri. Master-ul este cel care initializeaza comunicatia si efectueaza transferul de date din si
catre slave-uri. Mai simplu spus, master-ul poate fi privit ca un server, iar slave-ul poate fi privit ca un
client.
Analogic vorbind, clientul intotdeauna raspunde cererilor serverului. Daca serverul doreste
date, acesta ii spune clientului identificat printr-o adresa ca doreste acest lucru. Clientul se
conformeaza si indeplineste cererea. In termeni generali, asa se realizeaza o tranzactie I2C intre mai
multe placi Arduino.
Daca doresti sa studiezi mai multe despre protocolul I2C, nivele logice, cum se transmit serial
octetii si alte informatii utile, acceseaza link-urile de mai jos:
http://www.i2c-bus.org/
http://www.robot-electronics.co.uk/acatalog/I2C_Tutorial.html
https://learn.sparkfun.com/tutorials/i2c

Cum conectez 2 placi Arduino ?


Pentru a conecta cele 2 placi Arduino vei avea nevoie de urmatoarele componente:

http://www.robofun.ro/forum

2 placi Arduino: http://www.robofun.ro/arduino

Fire de conexiune: http://www.robofun.ro/cabluri

Un breadboard: http://www.robofun.ro/breadboard

Rezistoare: http://www.robofun.ro/electronice/rezistoare
Conecteaza placile Arduino folosindu-te de diagrama de mai jos:

In primul rand, trebuie sa realizezi masa comuna intre cele 2 placi, altfel nimic nu va functiona
corect. Pe diagrama masa comuna este realizata prin firul de culoare albastra. Firul se afla conectat intre
pinii GND ale placilor Arduino.
De asemenea conecteaza pinii 5V folosind firul de culoare rosie. Lucrul asta este necesar
pentru ca trebuie sa alimentezi rezistoarele de 4.7K.
Magistrala I2C este cea formata din cele 2 fire de culoare galbena si albastra. Prin intermediul
firelor vor circula bitii si semnalele de tact.

Cum programez placile ?


In primul rand, trebuie sa alegi care placa este master-ul si care placa este slave. Nu conteaza ce

http://www.robofun.ro/forum

placa alegi, cat timp cealalta va fi diferita. Spre exemplu, poti alege placa din stanga ca fiind placa
master, iar placa din dreapta ca fiind placa slave.
Mai jos sunt listate 2 sketch-uri, unul il vei incarca in placa master, iar celalalt il vei incarca in
placa slave.
Codul pentru placa master:
#include <Wire.h>
#define LED_PIN 13
byte x = 0;
void setup()
{
Wire.begin();
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
void loop()
{
Wire.beginTransmission(9);
Wire.send(x);
Wire.endTransmission();
x++;
if (x > 5) x=0;
delay(450);
}

Cum functioneaza sketch-ul placii master ?


Chiar daca la prima vedere protocolul I2C pare greoi si complicat, toate instructiunile din
mediul Arduino sunt mult simplificate. Prima linie de cod este necesara, ea include libraria Wire, adica
libraria responsabila comunicatiei I2C intre placi. In mediul Arduino se numeste Wire si nu I2C. Se
declara LEDul aflat pe placa Arduino ca fiind conectat pe pinul 13 si se initializeaza o variabila de tip
byte, variabila x.
In rutina setup() au loc mai multe procese si anume:

se initializeaza placa master prin linia Wire.begin() fara niciun parametru intre paranteze (vei
vedea ca la placa Slave este musai sa aplici si un parametru, adica adresa slave-ului).

http://www.robofun.ro/forum

Se initializeaza pinul 13 ca fiind pin de OUTPUT si se stinge prin linia digitalWrite.


In rutina loop() au loc urmatoarele procese:

Prin linia Wire.beginTransmission(9) se initializeaza comunicatia I2C cu placa slave. Parametrul


9 reprezinta adresa placii slave.

Prin linia Wire.send(x) se transmite catre placa slave continutul variabilei x.

Prin linia Wire.endTransmission() se incheie transferul I2C catre slave.

Variabila x este incrementata, dupa care tot procesul explicat mai sus se reia, adica se va
transmite catre placa slave continutul variabilei x, dar incrementat.

Codul pentru placa slave:


#include <Wire.h>
#define LED_PIN 13
#define LED_1 12
#define LED_2 11
int x;
void setup() {
Wire.begin(9);
Wire.onReceive(receiveEvent);
pinMode(LED_PIN, OUTPUT);
pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
digitalWrite(LED_PIN, LOW);
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, LOW);
x = 0;
}

http://www.robofun.ro/forum

void loop() {
if (x == 0) {
digitalWrite(LED_1, HIGH);
delay(200);
digitalWrite(LED_1, LOW);
delay(200);
}
if (x == 1) {
digitalWrite(LED_2, HIGH);
delay(200);
digitalWrite(LED_2, LOW);
delay(200);
}
}
void receiveEvent(int howMany) {
x = Wire.receive();
}

La nivelul placii Slave, lucrurile se petrec sub urmatoarea forma:

Placa Arduino este initializata ca si placa Slave cu adresa 9.

La fiecare tranzactie I2C initializata de catre placa Master, placa Slave va executa rutina
receiveEvent(int howMany). Ea functioneaza asemanator cu o intrerupere. Ori de cate ori
Master-ul transmite ceva se va executa aceasta rutina, prin care se stocheaza in variabila x ceea
ce a transmis placa Master.

In rutina loop() placa Slave testeaza ceea ce a transmis placa Master si anume, daca a transmis
valoarea 0 atunci se va aprinde LEDul 1, iar daca s-a transmis valoarea 2 atunci se va aprinde
LEDul 2.

Acesta este un exemplu simplu, prin care o placa Arduino master transmite catre o alta placa
Arduino slave o serie de valori. Placa Slave reactioneaza diferit in functie de valoarea transmisa.

http://www.robofun.ro/forum

Cum pot dezvolta acest proiect ?


In general protocolul I2C se utilizeaza la transmisia informatiei cu viteze cuprinse intre 10 si
400 Khz. Poti transmite orice, in functie de proiectul pe care doresti sa il abordezi.
Spre exemplu, poti conecta o memorie I2C direct la placa Arduino sau iti poti realiza un
termometru digital care sa iti afiseze temperatura direct pe ecranul calculatorului:
http://www.hobbytronics.co.uk/arduino-external-eeprom
http://www.jeremyblum.com/2011/02/13/arduino-tutorial-7-i2c-and-processing/
Nu uita ca exista o gama variata de senzori ce utilizeaza protocolul I2C pentru a comunica la
viteze mari, senzori digitali de presiune, accelerometre, IMU, giroscoape, s.a.m.d.

http://www.robofun.ro/forum

S-ar putea să vă placă și