Stiskněte "Enter" pro přeskočení obsahu

Ošetření vstupů Arduina a jiných IO

4

Sice je v nadpise napsáno Arduina, ale to není zcela tak pravda. V tomto článku proberu návrh vstupních a výstupních obvodů nejen pro Arduino, ale pro veškeré obvody, jejichž vstup/výstup je např. 5V s výstupním proudem jen několik málo mA, ale my bychom potřebovali připojit něco výkonnějšího, nebo na jiné napětí.

Co se amatérského bastlířství týče, lze se setkat s několika málo napěťovými hladinami. Vedle nejobvyklejších 5 V je tu ještě 3,3, 9, 12 a 24 V. Pokud tedy chcete např. pomocí tolika omílaného Arduina (nebo jakéhokoliv jiného integrovaného obvodu) snímat výstup z 12V baterie a spínat třeba 12V čerpadlo, budete potřebovat Arduino napájet (zdroj 12 – 5 V), snímat napětí baterie (5V digitální/analogový vstup bude snímat 12 V) a spínat výkonový 12V spotřebič (malý proud z MCU je potřeba zesílit).

V článku proberu snímání napětí na vstupu, spínání tranzistoru a relé výstupem. Opakuji, že i když v článku budu opakovat slovo Arduino, lze tento postup zopakovat pro jakýkoliv integrovaný obvod, např. i pro známou 555ku. Napětí a proudy se budou vztahovat k Arduino Nano s procesorem Atmel atmega328/P. Hodnoty jsou u většiny obvodů podobné, ale stejně je potřeba si vždy nastudovat datasheet!

Článek Ošetření výstupů Arduina a jiných IO v přípravě… Kdo ví, kdy bude hotový. Toto jsem „psal“ asi 3/4 roku.

Napájení

Tato část není tak úplně předmětem článku. Jistě by na to šel popsat článek samostatný…ale když už jsem to zmínil v úvodu. Arduino samotné má na desce integrovaný stabilizátor (v případe Arduina Nano je to LM1117), takže je možné ho napájet většinou napětím od 5 V do řekněme 12 V. Ale je třeba dávat pozor na přílišné zahřívání stabilizátoru. Pokud se použije napájecí napětí příliš velké, může i menší proudový odběr z Arduina způsobovat značné zahřívání integrovaného stabilizátoru. Pokud je nezbytné k napájení použít zdroj s vyšším napětím než 5 V, doporučuji předřadit napájecímu pinu buď lineární stabilizátor (např. 7805), nebo použít nějaký spínaný DC-DC měnič.

Já sám mám dobré zkušenosti s Čínským zdrojem MINI-360. Za $0.3 je to fajn koupě. Stačí trimrem (není určen k častému přenastavování – „jednou a dost“) nastavit potřebné výstupní napětí, a pokud napájecí napětí nepřesáhne 23 V není co řešit. Maximální vstupní napětí je tedy celkem nevhodně zvoleno. Pokud se použije běžný 24V zdroj, může se DC-DC měnič odpálit. Asi nejjednodušší řešení je připojit do série k napájení tři, nebo čtyři diody 1N4007 v sérii. Na každé vznikne úbytek cca 0,7 V, takže se napájení dostane pod bezpečnou mez. Maximální vstupní proud je pak omezen maximálním proudem použitých diod (u 1N4007 je to 1 A), viz Náhrada lineárního stabilizátoru 78×x DC-DC měničem.

DC-DC snižující měnič sloužící pro napájení MCU

Napájení Arduina je provedeno buď připojením USB konektoru, nebo připojením pinů GND a Vin na napájecí zdroj. Oddělovací dioda zajistí, že se napětí ze zdroje nepřipojí k počítači.

Pozor, je spousta integrovaných obvodů, které mají napájecí napětí 3,3 V! Pokud budete používat jiné obvody (např. STM32) je třeba napájecí napětí přizpůsobit konkrétnímu obvodu.

Ošetření vstupů

Pokud je třeba připojit ke vstupním pinům napětí 5 V (případně 3,3 V) lze to provést přímo. Problém může nastat, pokud je napětí větší, menší, je potřeba jej oddělit, nebo jsou k MCU připojeny delší vodiče.

Digitální vstupy na Arduinu mohou detekovat buď log. 1, nebo log. 0. Pokud se pin nenastaví, nebo nastaví pomocí příkazu pinMode(pin, INPUT); bude se chovat jako vstup s otevřeným kolektorem – toto je defaultní konfigurace. Odpor vstupu je velmi vysoký (řádově 100 MΩ) a tedy i odebíraný proud je velmi nízký. Pokud nebude na vstup nic připojeno, může se na pinu indukovat (případně kapacitní vazba) napětí, které náhodně mění log. hodnotu; viz obrázek níže.
Vstup je tedy vždy nutné připojit přes tzv. pull-down, nebo pull-up rezistor. Ten zajistí stálou nízkou, nebo vysokou logickou úroveň, i když nebude ke vstupu nic připojeno. Zároveň je odpor rezistoru tak vysoký, že po připojení opačné polarity se napětí na vstupu změní.

Náhodné hodnoty načítané na vstupu, který není k ničemu připojen.

Pull-down rezistor

Tento rezistor se připojí mezi svorku GND („zem“) a vstupní pin. Rezistor „stáhne“ případné rušivé signály na zem a tak bude na nepřipojeném vstupu stále log. 0. V případě připojení signálu na vstup (třeba tlačítka) však kvůli velkému odporu pull-down rezistoru stoupne napětí na takovou úroveň, že vstup bezpečně sepne. Často používaný rezistor pro tento účel je 10 kΩ. Při použití pull-down rezistoru je potřeba počítat se zvýšeným odběrem proudu (i když zanedbatelným) při sepnutím vstupu. Proud rezistorem 10 kΩ při napájení 5V je I = U / R = 5 / 10000 = 0,0005 A = 0,5 mA.

Při sepnutí tlačítka na obrázku níže bude procházet tlačítkem proud do pinu DI a přes rezistor R1 do GND. Proud do DI je zanedbatelný díky vysokému vstupnímu odporu MCU, proud rezistorem lze vypočítat podle vztahu IR = UN / R1 [A; V, Ω].

Pull-down rezistor připojený k digitálnímu vstupu. Log. 1 na vstup je sepnuta tlačítkem.

Pull-up rezistor

Funkce pull-up rezistoru je podobná, jako u pull-down rezistoru. Jediný rozdíl je, že se připojuje proti kladnému napájecímu napětí a vstupní signál do procesoru je tedy negovaný. V případě tlačítka je tedy třeba jednu stranu tlačítka připojit na pin GND a druhý na vstup. Použít lze rezistor, stejně jako výše o hodnotě cca 10 kΩ.
Procesory často mají již pull-up rezistory zabudované a lze je pouhým příkazem zapnout. Takže si lze ušetřit použití externí součástky. V případě Arduina se příkaz pinMode(pin, INPUT); nahradí příkazem pinMode(pin, INPUT_PULLUP);. Tím dojde k připojení vnitřního pull-up rezistoru ke vstupnímu pinu.Hodnota se liší v závislosti na typu procesoru, ale bývá od 20 kΩ do 150 kΩ. Tato hodnota někdy může být nedostatečná a je stejně nutné připojit ještě interní pull-up rezistor.

Vstupní obvod procesoru AtMega328P. Rpu je interní pull-up rezistor spínaný tranzistorem výše.

Nevýhodou tohoto způsobu je, že vstupní signál je negovaný! Pokud není k pinu nic připojeno, funkce digitalRead(pin); vrací hodnotu True. V případe např. sepnutého tlačítka se vstup změní na False. To však lze ošetřit programově, např. jako v programu níže.

//definice proměnných
bool vstup10;

void setup() {
 //nastavení vstupu a zapnutí interního pull-up rezistoru
 pinMode(10, INPUT_PULLUP); //pin 10

 //nastavení výstupu
 pinMode(13, OUTPUT); //pin 13
}

void loop() {
 //načtení vstupu
 vstup10 = !digitalRead(10); //načtení hodnoty vstupu z pinu 10, jeho negování (vykřičník) a uložení do proměnné vstup10

 //nastavení výstupu
digitalWrite(13, vstup10);
}
Vstup Arduina ošetřen interním pull-up rezistorem.

Pull-up rezistor připojený k digitálnímu vstupu. Log. 0 na vstup je sepnuta tlačítkem.

Interní Pull-up rezistor zapnutý příkazem. Funkce stejná jako u schématu výše, není však třeba použít externí rezistor. Log. 0 na vstup je sepnuta tlačítkem.

Odporový dělič

Pokud je napětí vstupu příliš velké, ale jasně definované, je asi nejjednodušší variantou snížení většího napětí odporovým děličem. Ten jednoduše rozdělí napájecí napětí na dva díly (úbytky napětí na rezistorech), přičemž jedna část musí být kompatibilní se vstupem MCU (tedy většinou 3,3 V, nebo 5 V). U děliče níže počítám s nezatíženým děličem, neboť vstup MCU má vysoký vstupní odpor – jeho odběr je zanedbatelný. Pro větší přesnost by bylo potřeba vzít v úvahu proudový odběr vstupu MCU.

Napětí na výstupu děliče přesně reprezentuje napětí na vstupu. Takže při přepětí na vstupu dojde i k přepětí na výstupu – může dojít k poškození obvodu. Rezistory protéká proud Id, jednotlivé rezistory jsou tedy zatíženy procházejícím proudem. Vzniká na nich výkonová ztráta P = UR * Id [W; V, A]. Minimálně na tento výkon musí být rezistory stavěny.

Jednoduchý napěťový dělič pro snížení napětí na vstupu MCU

Zenerova dioda – parametrický stabilizátor napětí

K omezení/stabilizaci vstupního napětí je možné použít i jednoduchý parametrický stabilizátor se zenerovou diodou, jehož napětí bude nastavené na vstupní napětí MCU. Výhodou tohoto zapojení je možnost použití širšího rozsahu vstupního napětí.
Zenerovu diodu je samozřejmě možné použít i v případě odporového děliče – bude zde plnit úlohu ochrany proti přepětí na vstupu – viz níže Ochrana vstupů proti rušení a přepětí.

Stabilizátor použitý jako omezovač napětí na vstupu MCU

Optočlen

S pomocí optočlenu je možné oddělit vstup MCU od napětí na vstupu. Vhodnou konstrukcí DPS je pak zajištěna ochrana před napěťovými špičkami až v řádech kV. Při přepětí samozřejmě dojde k poškození optočlenu, ale samotné MCU zůstane nepoškozeno. Výhoda je možnost spínat vstup MCU menším napětím, než je minimální potřebné napětí vstupu. Minimální napětí kterým lze sepnout diodu je uvedeno v datasheetu.

K diodě v optočlenu je nutné spočítat sériový rezistor podle vstupního napětí podle vzorce R = (UIN – UD) * ID [Ω; V, V, A]. Často používaný NPN tranzistor spíná proti zemi. Takže je nutné použít pull-up rezistor (jeho odpor musí být takový, aby se nepřetížil tranzistor v optočlenu RMAX = UMCU / ITRmax), nebo použít vnitřní pull-up rezistor pomocí příkazu pinMode(pin, INPUT_PULLUP); (viz výše).

Spínání vstupu MCU optočlenem

Detekování střídavého napětí na vstupu

Samotnou kapitolou je detekce střídavého napětí na vstupu MCU. Samozřejmě záleží na jeho velikosti, ale platí, že na vstup procesoru lze přivést pouze kladné stejnosměrné napětí. Je tedy potřeba provést nějaký převod. Výhodné je použít optočlen, který zajistí optické oddělení MCU a tedy i ochranu před zavlečením ac napětí. Otázkou tedy zůstává jak udělat ze střídavého napětí stejnosměrné…

Nejprve je nutné zjistit si minimální a maximální hodnotu vstupního napětí. Pro detekci napětí 230 V je navíc nutné dodržet bezpečné vzdálenosti na DPS, aby nedocházelo k přeskokům. Pro snížení napětí je možné použít obyčejný transformátor, usměrňovač, kondenzátor (který slouží jako ochrana proti pulzování signálu) a parametrický stabilizátor se zenerovou diodou, nebo stabilizátor 78×x a optočlen.

Další možností je diodu v optočlenu napájet přes usměrňovací diodu (ochrana proti velkému závěrnému napětí) a předřadný rezistor. Ten se potom počítá jako rezistor u běžného optočlenu. Je však třeba počítat s tím, že na něm bude velká výkonová ztráta P= UR * IR. LEDka potom bude „blikat“ v rytmu napájecího napětí, je tedy nutné tento signál buď ošetřit programově, nebo připojit před optočlen kondenzátor, který po dobu záporné půlvlny udrží tranzistor v optočlenu v sepnutém stavu. Při použití síťového napětí je efektivní hodnota sice 230 V, ale maximální amplituda je cca 325 V! Rezistor je tedy nutné počítat pro toto napětí.

Třetí možností je použít reaktance kondenzátoru a použít ho jako náhradu za rezistor v odporovém děliči. Výhoda použití kondenzátoru je jeho malý ztrátový výkon – nedochází k jeho zahřívání jako u předřadného rezistoru. Kapacitní reaktance se vypočítá podle vzorce XC = 1 / (2 * π * f * C) [Ω; Hz, F]. Hodnota vyjde v Ohmech – použití je pak stejné jako u běžného rezistoru. Nutné je však počítat s frekvenční závislostí (pro každou frekvencí je nutné použít jinou hodnotu kondenzátoru) a maximálním přípustným napětím kondenzátoru. Výstup z děliče je samozřejmě stále střídavý, je tedy nutné ho usměrnit, stabilizovat, nejlépe napětí omezit zenerovou diodou, vyfiltrovat a poté detekovat LEDkou v optočlenu.

Obvod pro detekci síťového napětí

Na obrázku výše je obvod pro kontrolu síťového napětí. Rezistor R2 a kondenzátor C1 tvoří obvod, který omezuje procházející proud. rezistor R1 slouží jako vybíjecí odpor pro C1, aby nezůstal dlouho nabitý síťovým napětím. Rezistor R2 omezuje proudovou špičku po zapnutí, kdy jsou C1 a C2 vybity.

Na kondenzátoru vzniká reaktance podle vzorce XC = 1 / (2 * π * f * C) [Ω; Hz, F], při použití kondenzátoru 100 nF (0,0000001 F) a síťovém kmitočtu 50 Hz bude mít reaktanci 1 / (2 * 3,14 * 50 * 0,0000001) = 31847 Ω. S rezistorem R2 to je dohromady 32407 Ω. Proud procházející obvodem bude I = U/ R = (U – Ud) / (Xc + R2) = (230 – 1,4 – 2) / 32407 = 0,007 A. Odpor R1 jsem zanedbal, Ud je úbytek na diodě v optočlenu a usměrňovači.

Zenerova dioda D1 slouží jako ochrana před přepětím a kondenzátor C2 jako filtrační kondenzátor, aby tranzistor v optočlenu nespínal v rytmu síťové frekvence. Téměř celý obvod je galvanicky spojen se sítí, je tedy nutné dodržovat bezpečné vzdálenosti, zacházení s obvodem atd.

Čtvrtou možností je použití běžného relátka. Jednoduše se použije relé s cívkou na požadované napětí. Na kontakty se poté připojí vstup MCU. Je ovšem třeba dávat pozor na to, aby mělo relé pozlacené kontakty. Jiná povrchová úprava nezaručuje správné převedení signálu v řádu mA – relé může po čase přestat převádět. Kontakt se pak chová jako běžný spínač, viz výše.

Ochrana vstupů proti rušení a přepětí

Vstupy MCU je třeba chránit proti přepětí. Pokud je obvod pouze na jedné desce bez vnějších obvodů a v nezarušeném prostředí, není většinou třeba dělat nějaká opatření. Často se lze setkat s tím, že jsou přímo vstupy procesoru použity jako datová sběrnice (i2C, OneWire, …) po půlce domu např. pro teplotní čidla. Navíc často bez stíněného kabelu. Pro tento účel nejsou vstupy MCU vhodné. Vodiče slouží jako anténa a může se na nich naindukovat napětí, které vstup, případně celý procesor odpálí. Nehledě na to, že 5 V proti vodiči GND je malé napětí pro provoz sběrnice na větší vzdálenosti (parazitní kapacity vedení, úbytek na vedení apod.).

Pro účel delší datové sběrnice je lepší použít sběrnici RS485 s příslušným převodníkem, případně proudovou smyčku. 485ka má v zarušeném prostředí větší spolehlivost a případnému přepětí je vystaven levný převodník a ne procesor s programem.

Nicméně i tak je vhodné zabezpečit vstupy před přepětím. Jednoduše lze použít paralelně ke vstupu diodu (ta je více než vhodná při použití optočlenu), která v ideálním případě ochrání vstup před napětím opačné polarity, případně vhodně dimenzovaný transil, nebo zenerovu diodu (je pomalejší než transil). Do obvodu je zařazen sériový odpor, na kterém v případě přepětí vznikne příslušný úbytek napětí – při velkém přepětí dojde k jeho poškození (v podstatě použit jako pojistka). Dále je možné vstupy na desku protáhnout feritovým kroužkem, který by měl odstínit vyšší frekvence. Vždy záleží, proti čemu chcete vstup odstínit. Různé typy ochran jsou zobrazeny na obrázku níže.

Různé ochrany MCU proti přepětí na vstupu

Ošetření zákmitů mechanických spínačů

Mechanický kontakt není samozřejmě úplně ideální. Zejména při sepnutí vznikají mechanické zákmity – kontakt tedy nemusí sepnout jednou, ale klidně vícekrát po sobě, dokud není trvale sepnut. Na to je potřeba při vytváření programu myslet. Něco se dá odstranit vhodným zapojením kondenzátoru na vstup, zbytek je potřeba odladit softwarove. Existují knihovny, které toto řeší. Většinou mají v názvu „debounce“, nebo „button debounce“. Fungují tak, že snímají stav tlačítka a kontrolují minimální čas, kdy může dojít ke změně. Takže např. při sepnutí kontaktu je vyvoláno první sepnutí v čase 0 a další načtení vstupu je třeba až za 50 ms. Do té doby už je kontakt ustálený a je opět načten stav log. 1. Samozřejmě je možné si funkci napsat vlastní.

  1. Bohouš Bohouš
    6.12.2018 - 17:54:04

    K obrázku „Obvod pro detekci síťového napětí“: Pokud použijeme optron se dvěma antiparalelními LED (PC814 a pod.) můžeme ve schematu vynechat usměrňovací můstek. Zenerovu diodu v tom případě bude lépe nahradit dvěma sériovými ZD na 3V proti sobě.

  2. Buchar Buchar
    24.3.2019 - 19:32:57

    lZE TAKTO OTESTOVAT ARDUINO NANO V3 – JE TO SPRÁVNĚ A NEBO V KÓDU NĚCO CHYBÍ např další PINy? Děkuju.

    // TESTER Arduino NANO 3.0
    // program pro postupné rozsvětcování a zhasínání led zleva doprava. Po doběhnutí se celý cyklus opakuje („běžící had“). Každá led svítí vždy 0,5s.
    // ZAPOJENÍ – LED anodu připojit na PIN Arduino a katodu na ODPOR 330 Ohmů a na mínus (GND – ZEM)

    #define PRODLEVA 500

    void setup()
    {
    pinMode(1, OUTPUT); // nastaveni pinu 1 jako vystup
    pinMode(2, OUTPUT); // nastaveni pinu 2 jako vystup
    pinMode(3, OUTPUT); // nastaveni pinu 3 jako vystup
    pinMode(4, OUTPUT); // nastaveni pinu 4 jako vystup
    pinMode(5, OUTPUT); // nastaveni pinu 5 jako vystup
    pinMode(6, OUTPUT); // nastaveni pinu 6 jako vystup
    pinMode(7, OUTPUT); // nastaveni pinu 7 jako vystup
    pinMode(8, OUTPUT); // nastaveni pinu 8 jako vystup
    pinMode(9, OUTPUT); // nastaveni pinu 9 jako vystup
    pinMode(10, OUTPUT); // nastaveni pinu 10 jako vystup
    pinMode(11, OUTPUT); // nastaveni pinu 11 jako vystup
    pinMode(12, OUTPUT); // nastaveni pinu 12 jako vystup
    pinMode(13, OUTPUT); // nastaveni pinu 13 jako vystup
    }

    void loop()
    {
    digitalWrite(1, HIGH); // rozsviceni led na pinu 1
    delay(PRODLEVA); // casova prodleva
    digitalWrite(1, LOW); // zhasnuti led na pinu 1

    digitalWrite(2, HIGH); // rozsviceni led na pinu 2
    delay(PRODLEVA); // casova prodleva
    digitalWrite(2, LOW); // zhasnuti led na pinu 2

    digitalWrite(3, HIGH); // rozsviceni led na pinu 3
    delay(PRODLEVA); // casova prodleva
    digitalWrite(3, LOW); // zhasnuti led na pinu 3

    digitalWrite(4, HIGH); // rozsviceni led na pinu 4
    delay(PRODLEVA); // casova prodleva
    digitalWrite(4, LOW); // zhasnuti led na pinu 4

    digitalWrite(5, HIGH); // rozsviceni led na pinu 5
    delay(PRODLEVA); // casova prodleva
    digitalWrite(5, LOW); // zhasnuti led na pinu 5

    digitalWrite(6, HIGH); // rozsviceni led na pinu 6
    delay(PRODLEVA); // casova prodleva
    digitalWrite(6, LOW); // zhasnuti led na pinu 6

    digitalWrite(7, HIGH); // rozsviceni led na pinu 7
    delay(PRODLEVA); // casova prodleva
    digitalWrite(7, LOW); // zhasnuti led na pinu 7

    digitalWrite(8, HIGH); // rozsviceni led na pinu 8
    delay(PRODLEVA); // casova prodleva
    digitalWrite(8, LOW); // zhasnuti led na pinu 8

    digitalWrite(9, HIGH); // rozsviceni led na pinu 9
    delay(PRODLEVA); // casova prodleva
    digitalWrite(9, LOW); // zhasnuti led na pinu 9

    digitalWrite(10, HIGH); // rozsviceni led na pinu 10
    delay(PRODLEVA); // casova prodleva
    digitalWrite(10, LOW); // zhasnuti led na pinu 10

    digitalWrite(11, HIGH); // rozsviceni led na pinu 11
    delay(PRODLEVA); // casova prodleva
    digitalWrite(11, LOW); // zhasnuti led na pinu 11

    digitalWrite(12, HIGH); // rozsviceni led na pinu 12
    delay(PRODLEVA); // casova prodleva
    digitalWrite(12, LOW); // zhasnuti led na pinu 12

    digitalWrite(13, HIGH); // rozsviceni led na pinu 13
    delay(PRODLEVA); // casova prodleva
    digitalWrite(13, LOW); // zhasnuti led na pinu 13
    }

  3. Peťan: Jde o to, co všechno přesně chceš. Ještě můžeš použít analogový piny jako výstupy. Můžeš buď použít označení pinu číslem, jak to máš v ukázce, nebo symbolicky (viz názvy pinů na modulu) třeba D10, D11, A1, atd.
    Jinak, pokud řešíš nějaký kód, tak doporučuji Arduino fórum
  4. Buchar Buchar
    26.3.2019 - 21:50:31

    Potřebuju zasunout Arduino NANO v3 do patice a rychle zkontrolovat všechny PINy co se dají zkontrolovat. Zajímalo by mě, zda pokud odejde tzv. pin, tak se dá takto zkontrolovat zda je odpálen jen výstupu, ale asi ne na vstupu a nebo je to jinak?

  5. Peťan: Záleží na tom, jak „odejde“. Muže se prorazit tranzistor na výstupu, tak bude na výstupu stále log. 1. Nastuduj si datasheet procesoru, jak jsou tvořeny výstupní obvody.
  6. Adam Adam
    1.11.2019 - 21:51:48

    Zdravím, stále som nepochopil nutnosť pozlatenych kontaktov relé. Veď snímam zopnutie na NC alebo NO , aku ulohu v tom zohrava zlato ak si vystup na arduino za rele osetrim ako vstup tlacidla.

    Peťan: Jde o to, že povrchová úprava pozlacením umožňuje stabilní přenos slabých proudových signálů. Dejme tomu, že povrch bez pozlacení může časem zoxidovat, nebo se jinak poškodit. Potom má pro signály v řádu voltů a miliampér velký odpor. Pozlacený kontakt je stabilnější.
    Jednou jsem řešil u lisu dvouruční spouštění, kde byly k bezpečnostnímu modulu připojeny spínací jednotky T6. Spouštění přestalo vždy po nějaké době fungovat. Po nahrazení jednotek novými (myslím, že s pozlacenými kontakty) nebylo o lise už slyšet.

Napsat komentář

Vaše emailová adresa nebude zveřejněna.