Hlavní navigace

Ovládání Arduina v reálném čase z počítače

Martin Malý 25. 1. 2011

Tento článek vznikl, takříkajíc, na přání vás, čtenářů. Tématem dnes bude využití Arduina jako počítačem řízeného interfejsu k reálným perifériím – snímačům, relé, servům atd. Ukážeme si jak v reálném čase komunikovat po sériovém portu i vytvoření jednoduchého ovládacího programu v jazyku Processing.

V redakční poště se objevil e-mail, kde jeden z čtenářů seriálu o Arduinu prosil o radu. Ocituji podstatné části:

Chystam se vylepsit nasi aparaturu pro fyzikalni mereni (rozptylu svetla), konkretne pridat jednoduchy titrator pohaneny krokovym motorkem, servo se zaklopkou pro preruseni paprsku laseru a relatko pro zapinani/vypinani externiho prislusenstvi pripojeneho do zasuvky (michacka).
Zda se, ze Arduino by k tomu mohlo byt vhodne, ponevadz s programovanim sice mam nejake zkusenosti, ale se stavenim elektrotechnickych konstrukci – od zakladu – prakticky zadne. 

(…) Zatim jsem vsak nebyl schopen najit clanek o tom, jak ovladat Arduino jinak nez z IDE nebo z nahraneho firmware. Potrebuji totiz napsat samostatnou aplikaci s uzivatelskym rozhranim, ktera bude obstaravat obsluhu prislusneho hardware. Z duvodu kompatibility a spoluprace s ostatnim kontrolnim software bude pracovat pod Windows a reagovat na zpravy systemu
(psat to budu zrejme v Delphi). Prakticky kazda dokumentace se zminuje o tom, ze napsat
samostatny, nezavisly program lze. Bohuzel nejak nejsem schopen najit zdroj, od ktereho se odrazit. Je mi jasne, ze jsem zrejme neco prehledl… Nemel byste nahodou nejaky tip?

Jak komunikovat s Arduinem z PC?

Existuje vícero možností – např. pomocí Ethernet shieldu a zabudovaného webového rozhraní – ale tou nejjednodušší metodou je využít sériové rozhraní, stejné jako používáme pro programování. Pokud jste se na Arduino podívali podrobněji, zjistili jste, že se, když je připojené přes USB, tváří jako „virtuální sériový port“.

Tuto metodu jsme už jednou použili pro čtení hodnot z připojeného senzoru. Dnes tedy vše zopakujeme, ale v opačném směru – nebudeme data přijímat do PC, ale vysílat. Technicky samozřejmě nic nebrání tomu obě metody zkombinovat a data vysílat i přijímat zároveň.

Jako příklad „ovládaného zařízení“ si vybereme to nejjednodušší, co máme po ruce – LED. Připojíme je na výstupy s PWM a pomocí ovládacího programu z PC budeme regulovat jejich jas.

Co je to PWM?

PWM (Pulse Width Modulation) je metoda, při níž se simuluje řízení výkonu u digitálních výstupů. Na výstup se posílají impulsy o vysoké frekvenci, a poměr doby trvání logické jedničky a nuly udává relativní výkon. Pokud budeme např. LED napájet impulsy s dostatečně vysokou frekvencí, aby ji lidské oko nevnímalo jako blikání, pak změnou poměru doby, kdy LED svítí a kdy LED nesvítí, lze simulovat plynulou regulaci. Stejná metoda se používá např. pro plynulé stmívání lustrů, pro řízení otáček motorů a v mnoha dalších situacích. Většina mikrokontrolérů, včetně toho v Arduinu, má funkci PWM pro některé digitální výstupy zabudovanou.

Zapojení je jednoduché – připojíme si dvě LED, vždy mezi výstupy 9 a 10 (ty mají funkci PWM) a zem (GND). Vyjdeme z příkladu zvaného Dimmer.

const int ledPin = 9;

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

void loop() {
  byte brightness;

  if (Serial.available()) {
    brightness = Serial.read();
    analogWrite(ledPin, brightness);
  }
}

Program je velmi jednoduchý a přímočarý – inicializační část nastaví sériové rozhraní a patřičný pin jako výstupní. V nekonečné smyčce se pak čtou přijatá data ze sériového rozhraní a přijaté bajty jsou použity pro nastavení PWM na daném výstupu funkcí analogWrite. Parametr může nabývat hodnot 0–255, kde 0 znamená „stále vypnuto“ a 255 „stále zapnuto“.

Když program přeložíme a spustíme, můžeme si vyzkoušet posílání příkazů přímo z terminálu. Když pošleme, řekněme, mezeru (její kód má hodnotu 32), bude LED svítit jen slabě, když pošleme znak ~ (s kódem 126), bude LED svítit viditelně silněji.

Rozhraní pro počítač

Posílání hodnot přes terminál může sice někomu připadat jako dostatečně luxusní, ale pohodlnější bude vytvořit si jednoduchý ovládací program. Jeho funkce bude jednoduchá: pomocí nějakého vhodného vstupního prvku bude moci uživatel měnit hodnotu, a ta bude posílána po sériovém rozhraní do Arduina.

Můžete využít svůj Oblíbený Programovací Jazyk. Já použil, pro tento účel dostatečný, nástroj Processing (i ten jsme tu už zmiňovali). Použil jsem knihovnu Gui Components 4 Processing, která nabízí základní prvky pro vytváření uživatelského rozhraní, jako jsou tlačítka, posuvníky, checkboxy atd. 

import guicomponents.*;
import processing.serial.*;

Serial port;
GWSlider sdr;

void setup() {
  size(300, 140); 
  port = new Serial(this, Serial.list()[1], 9600); 

  sdr = new GWSlider(this,20,80,260);
     
  sdr.setValueType(GWSlider.DECIMAL);
  sdr.setLimits(0f, 0f, 1.0f);
  sdr.setRenderValueLabel(false);
 
 
  PFont font;
  font = loadFont("Ubuntu-Regular-48.vlw");
  textFont(font, 44);
}

void draw() {
  background(200,200,255);
  fill(0, 102, 153);
  text("Jas LED", 150, 50);
}

void handleSliderEvents(GSlider slider) {
  int n = floor(slider.getValuef() * 256);
  port.write(n);
}

Font je vytvořen z .ttf souboru pomocí IDE Processing (Tools – Create Font). Program samotný je opět velmi jednoduchý a přímočarý. Je nastavena sériová komunikace na určitém portu PC (v mém případě je to druhý) a vytvořen posuvník v základním nastavení s hodnotami od 0 do 1. Pokud uživatel změní pozici posuvníku, je vyvolána obsluha události – funkce handleSliderEvents. V obsluze je načtena hodnota posuvníku, převedena na číslo 0–255 a to je posláno na sériový port.

Výhoda použitého prostředí Processing je v tom, že je napsáno v Javě a kód překládá rovněž do Javy, takže výsledek lze provozovat i mimo Processing IDE – stačí použít funkci Export, a získáme standalone aplikace pro Mac, Linux i Windows.

Protokol

Jednoduchá aplikace s jednou LED si vystačí s prostým protokolem „pošlu hodnotu, a ta je použita“. Co ale když zapojíme dvě diody? Nebo ještě víc? V takovém případě nelze prostě posílat hodnoty, protože by Arduino nemuselo bezpečně poznat, jaká hodnota je určena pro jaký výstup. Musíme si navrhnout komunikační protokol.

Pro naši ukázku se dvěma LED použijeme jednoduchý protokol, založený na textu. Každá změna bude poslána jako dvojice čísel, oddělených čárkou, a ukončena znakem CR, LF nebo @ (kvůli terminálu v IDE Arduino, které neumí správně poslat znak konce řádku). Třeba takto: „ 127,66\n “.

Pokud by bylo potřeba posílat vždy jen jednu hodnotu, mohli bychom protokol navrhnout např. tak, že první znak každého řádku by udával LED, kterou chceme měnit, a za ním by byla nová hodnota. Např. „ A127\nB66\n “.

V podstatě nejsme při návrhu protokolu nijak omezeni a měli bychom jej navrhnout tak, aby se do budoucna dal snadno rozšířit a aby bylo snadné jeho zpracování. Pokud máme protokol, ale už nějak definovaný, např. průmyslovým standardem, není o čem diskutovat a implementujeme ten.

Náš příklad nebude využívat žádný průmyslový standard a vystačí si s prostým protokolem, jaký jsme si popsali výše.

Realizace

Program pro Arduino se lehce rozroste – kromě potřebné inicializace druhého portu pak především o funkce, spojené s parsováním vstupních dat. Nejprve musíme načítat data ze sériového rozhraní, a pokud přijde znak konce řádku, rozdělíme došlý řetězec na dvě čísla, a ta si převedeme na hodnoty typu byte.

const int ledPin1 = 9;
const int ledPin2 = 10;

String line;

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

void doCommand(String s)
{
  char val[5];
  byte brightness;
  int comma = s.indexOf(',');
  if (!comma) {
    Serial.println("Invalid format\n");
    return;
  }
  String work = s.substring(0,comma);
  work.toCharArray(val,4);
  brightness = atoi(val);
  analogWrite(ledPin1, brightness);

  work = s.substring(comma+1);
  work.toCharArray(val,4);
  brightness = atoi(val); 
  analogWrite(ledPin2, brightness);
}

void loop() {
  byte c;

  if (Serial.available()) {
    c = Serial.read();
    if (c == 10 || c == 13 || c==64) {
      doCommand(line);
      line="";
      return;
    }
    line+=(c);
  }
}

Hlavní obsluha se přesunula do funkce doCommand(). Ta je vyvolána v okamžiku, kdy je přijatý znak 10, 13 či 64. Je nalezena pozice čárky, jsou vyseknuty dva řetězce a převedeny na celé číslo pomocí funkce atoi. Ta bohužel neumí pracovat s objektem String, proto je řetězec nejprve převeden na ASCIIZ (pole znaků ukončené znakem 0), známý z jazyka C.

Na protější straně bude rozšířený program v Processing – přidáme druhý slider a převod hodnot 0–255 na řetězec.

import guicomponents.*;
import processing.serial.*;

Serial port;
GWSlider sdr1, sdr2;

void setup() {
  size(300, 140); 
  port = new Serial(this, Serial.list()[1], 9600); 

  sdr1 = new GWSlider(this,20,60,260);
  sdr1.setValueType(GWSlider.DECIMAL);
  sdr1.setLimits(0f, 0f, 1.0f);
  sdr1.setRenderValueLabel(false);
 
  sdr2 = new GWSlider(this,20,100,260);
  sdr2.setValueType(GWSlider.DECIMAL);
  sdr2.setLimits(0f, 0f, 1.0f);
  sdr2.setRenderValueLabel(false);
 
  PFont font;
  font = loadFont("Ubuntu-Regular-48.vlw");
  textFont(font, 44);
}

void draw() {
  background(200,200,255);
  fill(0, 102, 153);
  text("Jas LED", 150, 50);
}

void printstring(Serial port, int n) {
  String s = str(n);
  for(int i=0;i<s.length();i++) {
    port.write(s.charAt(i));
  }
}

void handleSliderEvents(GSlider slider) {
  int n = floor(sdr1.getValuef() * 255);
  printstring(port, n);
  port.write(',');
  n = floor(sdr2.getValuef() * 255);
  printstring(port, n);
  port.write(13);
}

Výsledek si můžete prohlédnout na videu:

Závěr

Pro složitější aplikace, například jako je výše zmíněné ovládání několika zařízení, budeme muset nadefinovat o něco komplexnější či obecnější komunikační protokol, ale princip zůstane stejný – obslužný program v PC bude posílat data po sériové lince a Arduino bude přijatá data zpracovávat a podle nich reagovat.

Desky Arduino Uno a Arduino Mega 2560 k redakci zapůjčil obchod HW Kitchen, Arduino a Ethernet Shield obchod Czechduino. Děkujeme za laskavé zapůjčení.

Našli jste v článku chybu?

25. 1. 2011 15:59

MarSik (neregistrovaný)

Doporučil bych použít jako firmware do Arduina Firmata (http://firmata.org/wiki/Main_Page). Implementuje přesně tuto variantu ovládání a nemusíte se s tím psát sami.

1. 7. 2013 13:24

Niko (neregistrovaný)

1) Relé existují i pro menší napětí (nebývají levnější), ale vždy by tam měl být tranzistor, který bude relé řídit.
2) Daleko lepší je použít přímo tranzistor pro řízení telefonu. Je ale problém, že musíš mít vše na stejném potenciálu. Emitor tranzistoru (NPN) bude na stejném záporném napětí, které je v telefonu.
3) Ještě existují optočleny, kterými to také můžeš řídit. Co si matně pamatuji, tak by měly existovat optočleny přímo na TTL logiku. To znamená přímo na výstupy desky.

Pokud bud…

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

DigiZone.cz: ČRo rozšiřuje DAB do Berouna

ČRo rozšiřuje DAB do Berouna

Podnikatel.cz: EET zvládneme, budou horší zákony

EET zvládneme, budou horší zákony

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!