Vyhledávání

#11 - Propojujeme Arduino s jinými zařízeními

06.04.2014 20:00

Propojujeme Arduino s jinými zařízeními

V dnešním článku se budeme zabývat možnostmi připojení více desek Arduino k sobě a jejich vzájemné komunikace. Na začátku si předvedeme propojení přes sériovou linku, poté si ukážeme, jak k Arduinu připojit bluetooth modul. Nakonec si představíme sběrnici I2C.


Sériová linka

Většinu funkcí, které se pro sériovou komunikaci používají, jsme si popsali v pátém článku . Ve článku desátém jsme si je poté předvedli více prakticky ve spojení s prostředím Processing. Dnes si připojíme k sobě dvě Arduina (v mém případě Arduino Leonardo a Arduino Mega) a ukážeme si, jak spolu můžou komunikovat.


Propojení

V první řadě musíme Arduina správně spojit. To zde ale bude velmi jednoduché. Na obou deskách najdeme piny Rx (receive = přijmout) a Tx (transmit = odeslat). Tyto dva piny slouží právě pro sériovou komunikaci a za chvíli si ukážeme, jak sem připojit bluetooth modul. Desky k sobě propojíme tak, že Rx jedné desky bude připojeno na Tx druhé (jedna odesílá, druhá přijímá). Pozor! Jak už jsem zmínil dříve, některé typy desek mají více sériových portů. Ty jsou označeny Rx0, Rx1 atd. V tomto případě nezáleží na tom, jaké piny použijeme. Musíme ale použít vždy dvojici se stejným číslem. Také musíme mírně změnit kód. Pro piny Rx0 a Tx0 použijeme většinou funkce začínající Serial., pro Rx1 a Tx1 to budou funkce Serial1. atd. V našem případě budeme využívat Rx1 a Tx1 u Leonarda a Rx0 a Tx0 u Arduino Mega. Většinou platí, že Tx nalezneme na pinu 1 a Rx na pinu 0. Pokud bude napájená pouze jedna deska, musíme spojit 5V a GND obou desek.

Poznámka: Pozor! U Arduino Leonardo se situace ještě trochu komplikuje - má totiž od sebe oddělenou hardware a USB sériovou linku. Pro komunikaci přes USB využijeme funkci začínající Serial., pro hardware komunikaci (náš případ) využijeme Serial1..

Jelikož jsme si jednotlivé funkce popsali již v minulých dílech, přejdeme rovnou na příklad. Na Arduino Leonardo připojíme tlačítko. Pokud bude stisknuté, po sériové lince budeme odesílat hodnotu 'H', jinak odešleme hodnotu 'L'. Jak už jsem napsal před chvílí - zapojení je velmi jednoduché. Rx jedné desky připojíme na Tx druhé a GND a 5V obou desek připojíme k sobě.

Zapojení
Arduino, na kterém je připojeno tlačítko (u nás Leonardo), bude fungovat jako vysílač. Jeho úkolem bude zjišťovat, jestli je tlačítko stisknuté. Pokud bude, odešle po sériové lince funkcí Serial.print() znak 'H', v opačném případě odešle 'L'.

byte tl = 3; //tlačítko

void setup(){
    pinMode(tl, INPUT);
    Serial1.begin(9600);
}

void loop(){
    if(digitalRead(tl) == HIGH){
        Serial1.print("H");
    }
    else{
        Serial1.print("L");
    }
    delay(100);
}

Druhé Arduino (zde Mega) bude mít za úkol přijímat zprávy ze sériové linky a pokud nalezne znak 'H', tak rozsvítí LED diodu. Ke zpracování dat použijeme funkce Serial.available() a Serial.read(). Co tyto funkce dělají, si můžete připomenout v pátém článku .

void setup(){
    pinMode(13, OUTPUT);
    Serial.begin(9600);
}

void loop(){
    while(Serial.available()){
        char a = Serial.read();
        if(a == 'H'){
            digitalWrite(13, HIGH);
        }
        else if(a == 'L'){
            digitalWrite(13, LOW);
        }
    }
}

Další příklady by byly pouhé opakování věcí z minula. Pojďme se nyní podívat, jak může Arduino komunikovat s BT.

Poznámka: Na Arduino Esplora piny Rx a Tx nenajdete.

 


Bluetooth

Naštěstí pro nás existuje celá řada modulů (a nejenom bluetooth), které jsou určeny pro ovládání přes sériovou linku. K jejich ovládání se většinou nepoužívá nic jiného, než nám známé funkce pro sériovou komunikaci. U některých si musíme dát pozor na napájení. Nemusí být totiž určeny na napětí 5V a mohly by být poškozeny. To však neplatí o modulech přímo určených pro Arduino. Jedním z takovýchto bluetooth modulů je BlueSMiRF Silver, popřípadě o třídu vyšší BlueSMiRF Gold. BlueSMiRF Silver
Modul zapojíme stejným způsobem jako Arduino v minulém příkladu.
 

Arduino Modul
Tx Rx
Rx Tx
+5V VCC
GND GND

Tímto je modul zapojen a my se můžeme pustit do programování.

 


Odeslání a zpracování dat z potenciometru

Na pin A0 si připojíme potenciometr. Na něm naměřené hodnoty budeme přes bluetooth odesílat do PC a pomocí Processing zpracovávat. PC identifikuje bluetooth zařízení stejným způsobem jako připojené Arduino. Náš modul tedy bude také připojen na nějaký COM port. Výchozí rychlost komunikace obou uvedených modulů je 115200 bps. Program v Arduinu má velmi jednoduchou funkci - přečti hodnotu a pošli ji přes bluetooth do PC.

void setup(){
	Serial.begin(115200);    
}

void loop(){
    Serial.println(analogRead(A0));
    delay(10);
}

Před začátkem komunikace musíme PC s modulem spárovat. Zapneme bluetooth u PC a vyhledáme BT zařízení. Po nalezení našeho modulu jej přidáme. Pokud budeme vyzváni k zadání kódu, výchozí PIN je 1234. Modul zabere v PC dva COM porty. V Processing musíme pomocí indexu u funkce Serial.list()[] vyzkoušet, jaký je ten správný. Kód pro vykreslování grafu je převzatý z příkladu na konci minulého dílu.

import processing.serial.*;

Serial port;
String h;
int inth, i = 0;
int eol = 10; //ASCII znak pro zalomení řádku

void setup(){
    size(512,512);
    println(Serial.list());
    port = new Serial(this, Serial.list()[1], 115200);
}

void draw(){
    while(port.available() > 0){
        if(i == 512){
            background(255);
            i = 0;
        }
        h = port.readStringUntil(eol);
        if(h != null){
            inth = int(trim(h));
            line(i,512,i,512-inth/2);
            i++;
            println(inth);
        }
    }
}


Poznámka: Může se stát, že program po připojení modulu k Arduinu nepůjde nahrát. Stačí ale na dobu nahrávání odpojit modul od Arduina, čímž by se měl problém vyřešit.

 


Arduino a Android

Existuje celá řada aplikací pro Android, která je přímo určená pro práci s Arduinem. Velmi zajímavá je aplikace SensoDuino, která umí přes bluetooth odesílat data snad ze všech dostupných senzorů. Po instalaci aplikace se nám zobrazí následující rozhraní. SensoDuino
Zde si můžete vybrat, jaký senzor bude zapnutý a jestli se z něj budou odesílat informace. Data jsou vždy odeslána v pořadí: číslo senzoru (integer), číslo měření (integer) a tři naměřené hodnoty (float). Některé senzory odesílají pouze jednu hodnotu. V tom případě jsou zbylé dvě nastaveny na 99.99. Část senzorů odesílá tři hodnoty. Jde většinou o měřené hodnoty v jednotlivých osách. Tyto čísla můžeme získat pomocí funkcí Serial.parseInt() a Serial.parseFloat() - tu jsme si ještě nepředstavili, ale funguje stejně jako Serial.parseInt, pouze čeká na číslo typu float. Ještě před tím ale musíme nastavit jinou rychlost komunikace s modulem. Výchozí rychlost přenosu je totiž s aplikací nekompatabilní. U představených modulů to provedeme příkazy Serial.print("$") a poté Serial.println("U,9600,N"). Pouhé vypsání hodnot zajistí program:

int a,b;
float c,d,e;

void setup(){
	Serial.begin(115200);  
	// výchozí rychlost našich modulů
	// tříkrát vypíšeme dolar - tím se dostaneme do módu pro nastavování
	Serial.print("$");  
	Serial.print("$");
	Serial.print("$");
	delay(100);
	// dočasně nastavíme rychlost modulu na 9600 bps
	Serial.println("U,9600,N");  
	Serial.begin(9600);
}

void loop(){
    while(Serial.available() > 0){
        a = Serial.parseInt(); //typ senzoru
        b = Serial.parseInt();  //číslo měření
        c = Serial.parseFloat();  //první hodnota
        d = Serial.parseFloat();  //druhá hodnota
        e = Serial.parseFloat();  //třetí hodnota
        
        Serial.println(a);
        Serial.println(b);
        Serial.println(c);
        Serial.println(d);
        Serial.println(e);
    }
}

To není vskutku žádný div. Je to ale vše, co potřebujeme k dalšímu programování. Ještě si ale musíme uvést, jaké označení mají jaké senzory (typ senzoru). V následujícím seznamu, převzatém z oficiální dokumentace aplikace, naleznete číslo typu senzoru, jednotky a další doplňkové informace.

  • 1 - ACCELEROMETER (m/s^2 - X,Y,Z)
  • 2 - MAGNETIC_FIELD (uT - X,Y,Z)
  • 3 - ORIENTATION (Yaw, Pitch, Roll)
  • 4 - GYROSCOPE (rad/sec - X,Y,Z)
  • 5 - LIGHT (SI lux)
  • 6 - PRESSURE (hPa millibar)
  • 7 - DEVICE TEMPERATURE (C)
  • 8 - PROXIMITY (Centimeters or 1,0)
  • 9 - GRAVITY (m/s^2 - X,Y,Z)
  • 10 - LINEAR_ACCELERATION (m/s^2 - X,Y,Z)
  • 11 - ROTATION_VECTOR (Degrees - X,Y,Z)" );
  • 12 - RELATIVE_HUMIDITY (%)
  • 13 - AMBIENT_TEMPERATURE (C)
  • 14 - MAGNETIC_FIELD_UNCALIBRATED (uT - X,Y,Z)
  • 15 - GAME_ROTATION_VECTOR (Degrees - X,Y,Z)
  • 16 - GYROSCOPE_UNCALIBRATED (rad/sec - X,Y,Z)
  • 17 - SIGNIFICANT_MOTION (1,0)
  • 97 - AUDIO (Vol.)
  • 98 - GPS1 (Lat., Long., Alt.)
  • 99 - GPS2 (Bearing, Speed, Date/Time)

Se získanými informacemi už je poměrně jednoduché například udělat z Arduina vozítko ovládané pomocí náklonu telefonu a podobně.

Poznámka: Pro hlubší nastavení modulu, jako rychlost připojení, jméno, nebo PIN se používají tzv. AT commands. Ty ale pro základní činnost nejsou potřeba. Jejich výpis naleznete například zde.

Pokud chcete na telefonu pouze zobrazit přijatá data jako číslo, můžete použít jednoduchý Bluetooth terminál
.

 


Sběrnice i2c

I2c je sběrnice, která umožňuje mít na dvou vodičích (jeden pro udávání taktu a druhý pro data) připojeno až 128 zařízení (každé má svoji 7-bitovou adresu). Vodič, který udává takt komunikace, se nazývá SCL (clock line). Druhý vodič přenášející data je označován SDA (data line). U tohoto typu komunikace je vždy jedno zařízení řídící (master) a ostatní jsou řízená (slave). Zařízení master nemusí mít definovanou adresu. Piny, ke kterým se sběrnice připojuje, jsou u různých desek nastaveny různě. Přehled naleznete v následující tabulce:
 

Deska SDA pin SCL pin
Uno, Ethernet A4 A5
Mega 2560 20 21
Leonardo 2 3
Due 20, SDA1 21, SCL1

Ke správné funkci budeme potřebovat dva rezistory o odporu asi 4700 Ohm. Jeden zapojíme mezi SDA a +5V a druhý mezi SCL a +5V. I2c zapojení
Tím máme za sebou zapojení obou desek. Nyní ž se můžeme podívat na software.

 


Funkce pro práci s i2c

Funkce, které si zde ukážeme, jsou velmi podobné těm, se kterými jsme se setkali u sériové komunikace. Na začátku programu musíme vložit knihovnu Wire.h pomocí příkazu #include <Wire.h>. Další funkce jsou pro přehlednost popsány v tabulce.

Funkce Kdo používá Popis
Wire.begin(adr) master, slave Připojí zařízení ke sběrnici. Pokud je zařízení master, nemusí mít žádný parametr. U slave je parametrem adresa zařízení (číslo mezi 0 a 127).
Wire.beginTransmission(adr) master Zahájí komunikaci se zařízením s adresou danou v parametru.
Wire.endTransmission() master Ukončí komunikaci se zařízením.
Wire.requestFrom(adr,p) master Touto funkcí si master vyžádá data od slave. Prvním parametrem je adresa slave zařízení. Druhým je počet bytů, které očekáváme.
Wire.available() master, slave Stejně jako u Serial.available() i tato funkce vrátí počet bytů čekajících na zpracování.
Wire.write(data,delka) master, slave Tato funkce slouží k odeslání informací po i2c. Může mít buďto jeden parametr, a to číselnou hodnotu či řetězec, nebo dva parametry - pole bytů a jejich délku.
Wire.read() master, slave Používá se ke čtení hodnot z i2c.
Wire.onReceive(fce) slave Parametrem této funkce je jméno jiné funkce, která je volána, pokud jsou od zařízení master přijata nějaká data. Volaná funce by měla mít jeden parametr a to počet přijatých bitů.
Wire.onRequest(fce) slave Zde je parametrem jméno funkce volané, když jsou od master požadována data.

Nyní si tyto funkce ukážeme v praxi.

 


Přenos master -> slave

V tomto případě bude master číst data ze sériové linky. Pokud mu pošleme hodnotu H nebo L, pošle ji dále do slave zařízení (ale tentokrát přes i2c). Pokud slave obdrží hodnotu H, rozsvítí LED, v případě L ji zhasne.

Kód pro master zařízení

//master

#include <Wire.h>

char a = ' ';

void setup(){
    Wire.begin();
    Serial.begin(9600);
}

void loop(){
    while(Serial.available() > 0){
        a = Serial.read();
    }
    
    if(a != ' '){
        Wire.beginTransmission(100);
        Wire.write(a);
        Wire.endTransmission();
    }
    
    a = ' ';
    delay(500);
}

Kód pro slave zařízení

//slave

#include <Wire.h>

char a;

void setup(){
    Wire.begin(100);
    
    pinMode(13, OUTPUT);
    
    Wire.onReceive(priPrijmu);
}

void loop(){
    delay(100);
    if(a == 'H'){
        digitalWrite(13, HIGH);    
    }
    else if(a == 'L'){
        digitalWrite(13, LOW);    
    }
}

void priPrijmu(int b){
    while(Wire.available() > 0){
        a = Wire.read();
    }
}

 


Přenos slave -> master

V minulém příkladu bylo hlavním úkolem zařízení master odesílat data. V této ukázce bude mít úkol opačný, a to informace přijímat. Slave na vyžádání master zařízení změří hodnotu na A0. Tuto hodnotu ale musíme ještě před odesláním rozebrat na dva byty (odesílají se jednotlivě). Algoritmus rozkladu je stejný, jako kdybychom chtěli číslo převést z desítkové soustavy do "dvěstěpadesátšestkové" soustavy. Dva odeslané byty by potom odpovídaly dvěma znakům z této soustavy reprezentující naši hodnotu. Více o číselných soustavách naleznete na Wikipedii. Master si tedy vyžádá dva byty, které mu vzápětí přijdou. Následně je musí spojit, což probíhá obdobně jako u rozebírání, jen postup otočíme. Nakonec získanou hodnotu vypíšeme pomocí sériové linky.

//master

#include <Wire.h>

int hodnota;
byte mb[2];

void setup(){
    Wire.begin();
    Serial.begin(9600);
}

void loop(){
    Wire.requestFrom(100, 2);
    while(Wire.available() > 0){
        mb[0] = Wire.read(); //nižší byte
        mb[1] = Wire.read(); //vyšší byte
        //nyní hodnoty opět spojíme dohromady
        hodnota = mb[0] + mb[1]*256;
        Serial.println(hodnota);
    }
    delay(1000);
}
//slave

#include <Wire.h>

int mereni;
byte mb[2];

void setup(){
    Wire.begin(100);
    Wire.onRequest(odeslatData);
}

void loop(){
    delay(100);
}

void odeslatData(){
    mereni = analogRead(A0);
    //nyní rozebereme hodnotu mereni na dva byty
	//kolik celých 256 se vejde do naměřené hodnoty
	mb[1] = (mereni-(mereni%256))/256; //byte s vyšší hodnotou
	//jaký je zbytek po dělení 256
    mb[0] = mereni%256; //byte s nižší hodnotou - 

    Wire.write(mb, 2);
}

Stejně jako u sériových modulů, i zde existuje celá řada součástek, vybavená možností komunikovat přes i2c. Patří mě například různé typy pamětí, převodníků, řadičů ale i displejů. Tím se nám otevírá celá škála dalších možností, co s Arduinem dělat.

 


Zdroje obrázků

[SensoDuino]

V případě jakýchkoliv dotazů či nejasností se na mě neváhejte obrátit v komentářích.

 

Kam pokračovat?


<-- #10 - Arduino a Processing || #12 - Arduino a displeje I. -->

 

Zpět

Diskusní téma: #11 - Propojujeme Arduino s jinými zařízeními

Datum
Vložil
Titulek

safebox@seznam.cz

Dobrý den. Jsem začátečník a potýkám se s problémem jak přenášet pomocí arduina data asi tak na vzdálenost max 15m.Nejedná se o audio, ale o náhradu seriového portu - datový přenos . potřeboval bych co nejlacinější řešení z důvodů návaznosti na další projekty. Jen pro doplnění. potřebuji komunikaci z jednoho místa mezi čtyřmi zařízeními najednou.
Moc děkuji za případnou radu a návod jak to provést.

Datum
Vložil
Titulek

propojení arduina s androidem

Ahoj jsem zčátčník a potřebuji poradit co a jak na jednoduché použití androuidu.Zkoušel jsem různé aplikace,ale stále se mi nedaří najít ten správný klíč k tomu abych něco androidem ovládal přes bluetooth,třeba jen diody,nebo serva.Dá se nějak ověřit,zda skutečně arduino komunikuje s mobilem-tabletem,krom toho,že se spárují?Případně přečíst přes serial monitor jaké znaky,data posílám do arduina?
kolar.v@seznam.cz

Datum
Vložil
Titulek

kjgikoss@gmail.com

Datum
Vložil
Titulek

xriwlvdcec@gmail.com

Datum
Vložil
Titulek

qxnlisjuez@gmail.com

© 2015 Všechna práva vyhrazena.

www.hwkitchen.com