V tomto článku si povieme niečo o sériovom rozhraní v Arduinu. Ukážeme si na zaujímavých príkladoch ako správne komunikovať po sériovej linke s PC alebo s iným zariadením.

Sériové rozhranie v Arduinu

Sériové rozhranie v Arduinu tvoria vývody TX a RX. Tieto vývody sú priamo spojené so Serial-To-USB prevodníkom na Arduino doskách, ktoré obsahujú USB port (okrem verzie Leonardo). Čo znamená že tieto vývody sa používajú aj na programovanie Arduina.

Popis vývodov sériového rozhrania:

Číslo vývodu na Arduino UNO Označenie Popis
0 RX

RX alebo RXD (Receiver`s Serial Input). Môžeme ho nazvať ako vstup alebo prijímač dát. Pripájame ho na TX výstup zariadenia s ktorým chceme komunikovať.

1 TX TX alebo TXD  (Transmitter`s Serial Output) je výstup sériového rozhrania. Pripájame ho RX vstup zariadenia s ktorým chceme komunikovať po sériovej linke.

Ak používame digitálne vývody 0 a 1 ako sériový port, nemôžeme ich zároveň používať ako digitálne vstupy alebo výstupy.

 

Sériové rozhranie na ostatných doskách Arduina

Na ostatných verziách Arduina môžeme nájsť rôzny počet sériových rozhraní. V tabuľke nižšie je vidieť prehľad jednotlivých verzii Arduina a počet sériových rozhraní, ktoré v sebe obsahujú.

Arduino Počet sériových rozhraní Použitie
Leonardo, Yún, Micro 1* Serial.print(..)
Mega, Mega ADK, Due 4 Serial.print(..), Serial1.print(..), Serial2.print(..), Serial3.print(..)
Lilypad, Ethernet, Nano, Pro, Pro Mini, Mini 1 Serial.print(..)

* Používa sa Serial1.print(..) namiesto Serial.print(..)

Príklad 1: Základné použitie sériového rozhrania

Na jednoduchom príklade si ukážeme ako vlastne použiť sériové rozhranie na komunikáciu s počítačom alebo s iným zariadeným.

V tomto prípade nebudeme k Arduinu pripájať žiadne iné komponenty. Pripojíme len Arduino k PC a uploadneme nasledujúci program. Nie je teda nutná žiadna schéma zapojenia. Po tom ako uploadneme tento sketch do Arduina, otvoríme Serial Monitor v ktorom uvidíme správu "Testovacia sprava z Arduina..".

Zdrojový kód

void setup()
{
	//Inicializa serioveho rozhrania
	Serial.begin(9600);

	Serial.println("Testovacia sprava z Arduina..");
}

void loop()
{
}

 

Treba ešte pripomenúť ďalšiu dôležitú vec, ktorá súvisí s prenosom dát. A to tú, že ak komunikujú dve zariadenia po sériovej linke, tak obe tieto zariadenia musia mať nastavenú rovnakú šírku prenášaných dát, teda baud rate.

Popis zdrojového kódu

Ako je vidieť, je to veľmi jednoduché. Avšak je veľmi dôležité mať správne nastavené sériové rozhranie viď riadok 4.

Metóda Serial.begin(long baudRate) existuje v dvoch verziách. V našom príklade máme použitú verziu s jedným parametrom, ktorým je baud rate (počet bitov za sekundu, anglicky: bite per seconds = bps). Baud rate môže v Arduinu nadobúdať tieto hodnoty: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, a 115200. Hodnotu volíme podľa množstva prenášaných dát, tzn. ak prenášame malé množstvo postačí nám baud rate napríklad 9600 bps, ale v prípade ak sériovým rozhraním posielame väčšie množstvo dát, zvolím radšej vyšší baudrate napr. 115200 (čo je maximálna hodnota).

Druhá verzia metódy s dvoma parametrami Serial.begin(long baudRate, config). Prvý parameter už poznáme. Ten druhý je nastavenie parity, stop bitu a dát. V Arduinu máme na toto vytvorené konštanty. Default nastavenie je SERIAL_8N1.

Príklad 2: Ovládanie Arduina z PC (serialEvent)

V tomto príklade si ukážeme ako jednoduchými príkazmi poslanými sériovým portom z PC môžeme ovládať funkcie Arduina resp. programu, ktorý sme doňho nahrali. Príkazy budeme posielať cez Serial Monitor v Atmel Studiu.

Zapojenie na kontaktnom poli

Schéma zapojenia

Zapojenie je veľmi jednoduché. Slúži viac menej ako ukážka. Pripojili sme k Arduinu dve LED diódy, jednu budeme zapínať a vypínať príkazmi z PC (LED1) a tu druhu budeme regulovať pomocou PWM signálu (LED2).

Zdrojový kód

Zdrojový kód v súbore ArduinoSerial2.ino.

#define PIN_LED 12
#define PIN_PWM 11

String serialData = "";  
boolean dataComplete = false;

void setup()
{
	pinMode(PIN_LED, OUTPUT);
	
	serialData.reserve(200);
	
	Serial.begin(19200);
	Serial.println("Arduino UNO is ready");
}

void loop()
{	
	if (dataComplete)
	{
		// obsahuju poslane data retazec LED=1
		if (serialData.substring(0,3)=="LED")
		{
			uint8_t ledValue = (uint8_t)serialData.substring(4,5).toInt();
			if (ledValue==HIGH)
			{
				ledOn();
				Serial.println("LED ON");
			}
			else
			{
				ledOff();
				Serial.println("LED OFF");
			}
		}
		// nastavenie PWM hodnoty
		if (serialData.substring(0,3)=="PWM")
		{
			long pwmValue = serialData.substring(4, serialData.length()-1).toInt();
			if (pwmValue>=0 && pwmValue<=255)
			{
				analogWrite(PIN_PWM, pwmValue);
				Serial.print("PWM SET TO ");
				Serial.println(pwmValue);
			}
		}
		
		// vynulovanie premennych
		serialData = "";
		dataComplete = false;
	}
}

void serialEvent()
{
	while (Serial.available())
	{
		// nacitame prichadzajuci bajt
		char inChar = (char)Serial.read();
		// pridame ho do retazca serialData
		serialData += inChar;
		// ak je znak 'enter' tak ukoncime prijimanie dat
		if (inChar == '\n')
		{
			dataComplete = true;
		}
	}
}

void ledOn()
{
	digitalWrite(PIN_LED, HIGH);
}

void ledOff()
{
	digitalWrite(PIN_LED, LOW);
}

Popis zdrojového kódu

V setup metóde máme nastavenie vývodu a sériového rozhrania, v tomto príklade sme nastavili baud rate na 19200. Prejdem až k metóde serialEvent, ktorú ešte nemusíte poznať. Táto metóda sa vykonáva vždy ak prídu nové data na vstup RX. Jej volanie je až za metódou loop. Tu môže nastať malé oneskorenie, ak máme nejaký zložitejší kód v loop metóde, ktorý sa vykonáva dlhšie. V tomto prípade sa volanie metódy serialEvent oneskorí, čo môže byť niekedy nevyhovujúce.

Takže táto metóda nám načíta data, ktoré prídu do RX vstupu. V metóde si môžete všimnúť podmienky, ktorá ukončuje načítavanie dát v prípade ak prichádzajúci znak je "\n" (enter, nový riadok).

V tomto prípade sa teda ukončí načítavanie dát. Pozrime sa teraz do loop metódy. Vidíme tam jednu veľkú podmienku (riadok 19). V tejto podmienke máme parsovanie dát, ktoré sme poslali z PC.

Teraz je dôležité si určiť tzv. protokol akým budeme komunikovať s Arduinom po sériovej linke. Na zapnutie a vypnutie ledky LED1 si určíme príkaz LED, tzn. na zapnutie zadáme príkaz LED=1 a na vypnutie LED=0. ďalej si určíme príkaz na ovládanie ledky LED2, ktorú ovládame pomocou PWM signálu, príkaz bude PWM=pwmHodnota, kde pwmHodnota môže nadobúdať hodnoty 0 až 255, napr. PWM=127.

Vráťme sa teraz späť do kódu, konkrétne na riadok 22, kde parsujeme data a zisťujeme či sa v poslaných datách nenachádza reťazec LED (teda ten náš príkaz). Ak sa nachádza, zistíme ešte hodnotu a následne buď zapneme alebo vypneme ledku volaním metód ledOn() (riadok 27) alebo ledOff() (riadok 32). Za volaním týchto metód posielame späť do PC informáciu o tom čo sa v Arduinu vykonalo, viď riadky 28 a 33.

V prípade odchytávania príkazu PWM je to podobné, rozdiel je len pri zisťovaní pwm hodnoty. Ak máme pwm hodnotu získanú z dát a vyhovuje zadanej podmienke, tak nastavíme jas ledky LED2 viď riadok 42.

Na parsovanie používame metódy knižnice String, konkrétne metódu substring. Substring nám vlastne "odreže" z reťazca reťazec podľa indexov, ktoré sme zadali ako parametre. Index znakov začína vždy 0 (nulou). V prípade ak chceme z reťazca "LED=1" dostať reťazec "LED", musíme do metódy substring zadať nasledovné hodnoty substring(0, 3). Prvý parameter je index znaku, ktorým začína časť reťazca, ktorý chceme vytiahnuť. Druhý parameter je index znaku, ktorým končí náš chcený reťazec ale prirátame ešte číslo 1.

Na riadkoch 49 a 50 máme dôležitú časť kódu. Je to "vynulovanie" premenných serialData a dataComplete. Ak by sme toto neurobili vykonávali by sa nám príkazy vo vnútri podmienky stále dookola a to nechceme.

Testovanie príkazu LED

Testovanie príkazu PWM

Príklad 3: Monitorovanie a ovládanie Arduina z PC

Tento príklad bude pokročilejší. Vytvoríme program pre Arduino, ktorý bude posielať v určitých intervaloch údaje zo senzorov. Tento interval budeme môcť upraviť poslaným jednoduchého príkazu z PC. Budeme môcť riadiť aj iné parametre programu alebo konkrétnych vývodov. Na strane PC budeme mať špeciálnu aplikáciu Arduino Monitor & Controller.

Zapojenie na kontaktom poli

Schéma zapojenia

 

Aj toto zapojenie nie je vôbec zložité. Máme k Arduinu zapojené dva spínače, ktoré nám slúžia ako senzory otvorených dverí alebo okna. ďalej máme zapojený teplotný senzor LM35 na snímanie teploty v miestnosti. K Arduinu máme ešte pripojenú ledku, táto ledka môže byť nahradená napríklad nejakým relé na spínanie nejakého elektrického zariadenia, napr. osvetlenie,..atď.

Zdrojový kód

Zdrojový kód v súbore ArduinoSerial3.ino.

#include <TaskAction.h>

#define PIN_INPUT_0 2
#define PIN_INPUT_1 4
#define PIN_LED 8
#define PIN_LM35 A5
#define MEASURE_INTERVAL 5000

static const char version[6] = "1.0.0";
uint8_t pinInputs[2] = {PIN_INPUT_0, PIN_INPUT_1};
String serialData = ""; 
boolean dataComplete = false;

TaskAction measureTask(measure, MEASURE_INTERVAL, INFINITE_TICKS);

void setup()
{
	pinMode(PIN_INPUT_0, INPUT_PULLUP);
	pinMode(PIN_INPUT_1, INPUT_PULLUP);
	pinMode(PIN_LED, OUTPUT);
	
	Serial.begin(19200);
	Serial.println("Arduino is Ready");
	
	serialData.reserve(200);	
}

void loop()
{	
	measureTask.tick();	
	
	if (dataComplete)
	{
		if (serialData.substring(0,1)=="V") // V
		{
			sendVersion();
		}
		if (serialData.substring(0,1)=="T") // T=10
		{
			long val = serialData.substring(2,(serialData.length())).toInt();			
			setMeasureTaskInterval(val);
		}		
		if (serialData.substring(0,3)=="LED")// LED=1 alebo LED=0
		{
			uint8_t val = (uint8_t)serialData.substring(4,5).toInt();
			setLed(val);
		}				
		serialData = "";
		dataComplete = false;
	}
}

void serialEvent()
{
	while (Serial.available())
	{		
		char inChar = (char)Serial.read();	
		serialData += inChar;		
		if (inChar == '\n')
		{
			dataComplete = true;
		}
	}
}

void measure()
{	
	measureTemperature();
	measureInputs();
}

/*
 * Meranie vstupov
 */
void measureInputs()
{	
	//SENSOR INPUT0=0, INPUT1=1
	Serial.print("SENSOR ");
	for (int i=0; i < sizeof(pinInputs); i++)
	{
		Serial.print("INPUT");
		Serial.print(i);
		Serial.print("=");
		Serial.print(digitalRead(pinInputs[i]));
		if (i<(sizeof(pinInputs)-1))
		{
			Serial.print(",");
		}
		delay(50);
	}
	Serial.println();
}

/*
* Meranie teploty
*/
void measureTemperature()
{
	//SENSOR LM35=25
	int analogValue = analogRead(PIN_LM35);	
	float tempInCelsius = ((analogValue * 5000.0) / 10.0) / 1024;

	Serial.print("SENSOR ");
	Serial.print("LM35=");
	Serial.println(tempInCelsius);
}

/*
* Poslanie verzie firmveru do PC
*/
void sendVersion()
{
	Serial.print("Firmware version: ");
	Serial.print(version);
	Serial.println();
}

/*
* Nastavenie LED
*/
void setLed(uint8_t val)
{
	digitalWrite(PIN_LED, val==HIGH ? HIGH : LOW);	
}

/*
* Nastavenie intervalu merania
* - min 5 sekund a max. 5 min
* @param interval, pocet sekund
*/
void setMeasureTaskInterval(long interval)
{
	if(interval<=300 && interval>=5)
	{
		measureTask.Enable(false);
		measureTask.SetInterval(interval*1000);
		measureTask.Enable(true);
	}
	if(interval==0)
	{
		measureTask.Enable(false);
	}
}

Popis zdrojového kódu

Kód sa nám tentokrát tak trochu rozrástol. Popíšem tie najdôležitejšie časti. V tomto príklade využívame knižnicu TaskAction na pravidelné spúštanie funkcii. Na začiatku máme teda include tejto knižnice. Ďalej máme definíciu vývodov a pomocné premenné.

Na riadku 14 máme vytvorenú inštanciu triedy TaskAction. Inštancia measureTask je nastavená tak, aby sa funkcia measure spúšťala každých 5 sekúnd. Konštruktor triedy TaskAction má tri parametre. Prvý parameter je metóda, ktorá bude spúšťaná, druhý parameter je interval v milisekundách a tretí parameter je tzv. ticks, je to počet spustení zadanej metódy. V našom prípade máme nastavenú konštantu INFINITE_TICKS, čo je vlastne 0 (nula), čo znamená, že sa nám bude metóda measure spúšťať stále dookola. Ak by sme chceli v nejakom inom prípade spúšťať metódu len napríklad 10 krát, zadáme namiesto INFINITE_TICKS číslo 10.

Prejdem k metóde measure() riadky 66 až 70. Vo vnútri sa volajú metódy measureInputs a measureTemperature. Metóda measureInputs nám zisťuje stav vstupných vývodov, či je vstup zopnutý (log 0) alebo rozopnutý (log 1). Hodnoty sa následne posielajú do PC sériovým rozhraním v takomto tvare "SENSOR INPUT0=1,INPUT1=1".

Metóda measureTemperature ako už tušíte meria teplotu. Táto teplota je posielaná rovnakým spôsobom ako údaje zo vstupov "SENSOR LM35=22.3". Neskoršie vysvetlím prečo som zvolil takýto formát.

Prebrali sme časť, ktorá nám získava údaje zo senzorov a posiela ich do PC. Teraz preberiem druhú časť kódu, tú ktorou dokážeme riadiť funkcie programu.

Už viete čo je to serialEvent, tak prejdem rovno k parametrom. Máme tentokrát zadefinované tri parametre: V - pošle do PC aktuálnu verziu firmvéru, T=10 - nastavenie intervalu merania teploty a vstupov (na 10 sekúnd), LED=1 - zapnutie (a vypnutie) LED diódy.

Kontrola zadania parametrov sa vykonáva v loop metóde rovnako ako v predchádzajúcom príklade. Takže ak sú splnené zadané podmienky vykonávajú sa požadované metódy.

Testovanie

Testovanie senzorov - Arduino nám v intervale každých 5 sekúnd bude posielať údaje zo senzorov.

Testovanie parametrov - Pomocou Serial monitoru pošleme do Arduina príkaz napr. T=6, čím nastavíme interval merania na každých 6 sekúnd. (samozrejme môžeme túto hodnotu parametra T ľubovoľne meniť). Tiež môžeme vyskúšať parameter LED, na zapnutie ledky pošleme LED=1 a analogicky na vypnutie zase LED=0.

Testovanie s aplikáciou Arduino Monitor & Controller

Na komunikáciu s Arduinom (a možno nielen s nim) som vyvinul aplikáciu v .NET C#, ktorú spustíte pod Windowsom. Aplikáciu si môžete stiahnuť na tomto odkaze. Aby ste mohli aplikáciu na počítači spustiť, musíte mať vo Windowse nainštalovaný .NET Framework 4.5, stiahnuť si ho môžete na stránkach Microsoftu.

Aby ste mohli aplikáciu správne použiť, postupujte podľa nasledujúcich krokov.

Krok 1 - Nastavenie aplikácie

Po prevzatí aplikácie spustite nastavenia File -> Settings. Tu nastavíme COM port ku ktorému máme pripojené arduino a baud rate podľa programu v Arduinu.

Krok 2 - Pripojenie (Odpojenie)

Teraz môžeme aktivovať aplikáciu resp. komunikáciu s Arduinom. Klikneme na File->Connect. Ak budeme chcieť odpojiť aplikáciu tak klikneme na File->Disconnect.

Krok 3 - Monitorovanie údajov

Ak máme aplikáciu pripojenú, po chvíli sa budú zobrazovať v tabuľke napravo názvy a hodnoty senzorov. Ak posielame údaje z Arduina v tvare "SENSOR NIECO=HODNOTA", zobrazí sa nám tento údaj v tabuľke "INPUTS / SENSORS".

Krok 4 - Zobrazenie grafu

Údaje môžeme zobraziť aj prehľadne v grafe. Graf zobrazíme dvojklikom na riadok v tabuľke so zoznamom senzorov. V grafe sa zobrazuje posledných 10 nameraných hodnôt. Ak je aplikácia pripojená k Arduinu graf sa vždy zaktualizuje ak prídu nové hodnoty pre zvolený senzor.

Krok 5 - Vytvorenie príkazu

Do poľa "Parameter Name" zadáme názov parametra, ktorý chceme poslať do Arduina a klikneme na tlačítko Add. Zadáme napríklad T, ktorým si nastavíme interval posielania a merania teploty a vstupov.

Môžeme si vytvoriť niekoľko takýchto parametrov a upravovať ich nezávisle na sebe.

Krok 6 - Úprava hodnoty a odoslanie

V tabuľke so zoznamom výstupných parametrov alebo príkazov, môžeme upravovať ich hodnoty. Pri každej zmene sa odošle parameter do Arduina. Informáciu o tom či sa parameter odoslal uvidíme v logeri.

 

Aplikáciu je možné použiť aj po úprave programu pre Arduino, je však nutné zachovať spôsob komunikácie tzn. údaje zo senzorov je treba posielať v tvare: "SENSOR L=12,X=0" (Medzi slovom SENSOR a písmenom L je medzera). Tiež treba brať na vedomie, že aplikácia posiela parametre v tvare P=10. Ďalej po ukončení aplikácie sa stratia všetky údaje poslané z Arduina a do Arduina. Zostávajú uložené len nastavenia COM portu a baud rate.

Ešte spomeniem, že aplikácia je stále vo vývoji, môžete ju používať zdarma, ale je možné že sa vyskytnú nejaké problémy alebo chyby. Ak sa niečo také stane prosím pošlite mi popis chyby na mail.

Záver

Na záver zhrniem čo sme si v článku povedali. Vieme čo znamenajú vývody na Arduinu s označením RX a TX. Vieme nastaviť sériové rozhranie na Arduinu a komunikovať s počítačom. Na komunikáciu môžeme využiť aj aplikáciu Arduino Monitor & Controller. Ak budete mať nejaké otázky na túto tému napíšte mi do komentára alebo ak budete mať problémy s ovládaným aplikácie.