Velice rychle blikat

Jedna z nevýhod „našeho” čipu ESP8266 je, že na svých nožičkách umí nastavovat jen dvě hodnoty – 3,3 V a zem, jedničku a nulu. Dioda tak buď svítí, nebo nesvítí – nedá se nastavit poloviční intenzita, nedá se plynule rozsvěcet nebo zhasínat.

Tuhle nevýhodu ale můžeme obejít s využitím dvou faktů. Ten první je, že diodám – na rozdíl od žárovek nebo zářivek – nevadí časté vypínání a zapínání. Opotřebovávají se spíš svícením a časem. Druhý je, že lidské oko nestačí zaznamenat pohyby a změny, které probíhají rychleji než zhruba za setinu vteřiny.

Pojďme tedy velice rychle blikat – a oblafnout tak naše oči a mozky!

from machine import Pin
from time import sleep

pin_diody = Pin(14, Pin.OUT)
while True:
    pin_diody.value(0)  # vypnout LED
    sleep(2/100)  # počkat dvě setiny vteřiny
    pin_diody.value(1)  # zapnout LED
    sleep(1/100)  # počkat jednu setinu vteřiny

Zkus si pohrát s hodnotami pro time.sleep.

Takhle fungují prakticky všechna stmívatelná LED světla – rychlé blikání je ekonomičtější a přesnější než např. nastavování nižšího napětí.

Dokážeš napsat program, který diodu postupně, plynule rozsvítí?

Řešení

Protože je takovéhle rychlé blikání užitečné ve spoustě různých situací, obsahuje MicroPython speciální funkci: umí blikat samostatně. Nastavíš, jak rychle má blikat a jak dlouho má trvat každé bliknutí, a MicroPython pak bude blikat automaticky, zatímco tvůj program se může věnovat něčemu jinému.

Téhle funkci se říká pulzně šířková modulace – angl. Pulse Width Modulation, neboli PWM. Z MicroPythonu jde tahle funkce ovládat pomocí třídy machine.PWM. Každý objekt téhle třídy umí ovládat jednu nožičku a dají se u něj nastavit dva parametry:

  • freq – frekvence, tedy kolikrát za sekundu se LED rozsvítí a zase zhasne a
  • duty – anglicky duty cycle, česky střída, nastavuje „šířku pulzu”, tedy jak dlouho bude dioda při každém bliknutí svítit. Hodnota duty může být od 0, kdy LED nesvítí vůbec, do 1023, kdy svítí celou dobu. Nastavíš-li duty=512, bude dioda svítit s poloviční intenzitou (512 = 1024/2).

Nastavíš-li PWM(freq=50, duty=512), dioda bude blikat 50× za sekundu. Vždycky jednu setinu vteřiny bude svítit a na jednu setinu vteřiny zhasne.

from machine import Pin, PWM

pin_diody = Pin(14, Pin.OUT)
pwm = PWM(pin_diody, freq=50, duty=512)

Zkus nastavit i nižší frekvenci, třeba 3 nebo 1, ať blikání vidíš přímo!

PWM se dá zrušit metodou pwm.deinit(). Jako s otvíráním souborů, je dobré po sobě uklidit – i když zatím můžeš jednoduše restartovat celé zařízení.

{
  "data": {
    "sessionMaterial": {
      "id": "session-material:2019/brno-jaro-2019-pondeli:micropython:6",
      "title": "Velice rychle blikat",
      "html": "\n          \n    \n\n    <h2>Velice rychle blikat</h2>\n<p>Jedna z nev&#xFD;hod &#x201E;na&#x161;eho&#x201D; &#x10D;ipu ESP8266 je, &#x17E;e na sv&#xFD;ch\nno&#x17E;i&#x10D;k&#xE1;ch um&#xED; nastavovat jen dv&#x11B; hodnoty &#x2013; 3,3 V a zem, jedni&#x10D;ku a nulu.\nDioda tak bu&#x10F; sv&#xED;t&#xED;, nebo nesv&#xED;t&#xED; &#x2013; ned&#xE1; se\nnastavit polovi&#x10D;n&#xED; intenzita, ned&#xE1; se plynule rozsv&#x11B;cet nebo zhas&#xED;nat.</p>\n<p>Tuhle nev&#xFD;hodu ale m&#x16F;&#x17E;eme obej&#xED;t s vyu&#x17E;it&#xED;m dvou fakt&#x16F;.\nTen prvn&#xED; je, &#x17E;e diod&#xE1;m &#x2013; na rozd&#xED;l od &#x17E;&#xE1;rovek nebo\nz&#xE1;&#x159;ivek &#x2013; nevad&#xED; &#x10D;ast&#xE9; vyp&#xED;n&#xE1;n&#xED; a zap&#xED;n&#xE1;n&#xED;.\nOpot&#x159;ebov&#xE1;vaj&#xED; se sp&#xED;&#x161; sv&#xED;cen&#xED;m a &#x10D;asem.\nDruh&#xFD; je, &#x17E;e lidsk&#xE9; oko nesta&#x10D;&#xED; zaznamenat pohyby a\nzm&#x11B;ny, kter&#xE9; prob&#xED;haj&#xED; rychleji ne&#x17E; zhruba za\nsetinu vte&#x159;iny.</p>\n<p>Poj&#x10F;me tedy velice rychle blikat &#x2013; a oblafnout tak na&#x161;e o&#x10D;i a mozky!</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">machine</span> <span class=\"kn\">import</span> <span class=\"n\">Pin</span>\n<span class=\"kn\">from</span> <span class=\"nn\">time</span> <span class=\"kn\">import</span> <span class=\"n\">sleep</span>\n\n<span class=\"n\">pin_diody</span> <span class=\"o\">=</span> <span class=\"n\">Pin</span><span class=\"p\">(</span><span class=\"mi\">14</span><span class=\"p\">,</span> <span class=\"n\">Pin</span><span class=\"o\">.</span><span class=\"n\">OUT</span><span class=\"p\">)</span>\n<span class=\"k\">while</span> <span class=\"bp\">True</span><span class=\"p\">:</span>\n    <span class=\"n\">pin_diody</span><span class=\"o\">.</span><span class=\"n\">value</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"p\">)</span>  <span class=\"c1\"># vypnout LED</span>\n    <span class=\"n\">sleep</span><span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"o\">/</span><span class=\"mi\">100</span><span class=\"p\">)</span>  <span class=\"c1\"># po&#x10D;kat dv&#x11B; setiny vte&#x159;iny</span>\n    <span class=\"n\">pin_diody</span><span class=\"o\">.</span><span class=\"n\">value</span><span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">)</span>  <span class=\"c1\"># zapnout LED</span>\n    <span class=\"n\">sleep</span><span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"o\">/</span><span class=\"mi\">100</span><span class=\"p\">)</span>  <span class=\"c1\"># po&#x10D;kat jednu setinu vte&#x159;iny</span>\n</pre></div><p>Zkus si pohr&#xE1;t s hodnotami pro <code>time.sleep</code>.</p>\n<div class=\"admonition note\"><p>Takhle funguj&#xED; prakticky v&#x161;echna stm&#xED;vateln&#xE1; LED\nsv&#x11B;tla &#x2013; rychl&#xE9; blik&#xE1;n&#xED; je ekonomi&#x10D;t&#x11B;j&#x161;&#xED; a p&#x159;esn&#x11B;j&#x161;&#xED;\nne&#x17E; nap&#x159;. nastavov&#xE1;n&#xED; ni&#x17E;&#x161;&#xED;ho nap&#x11B;t&#xED;.</p>\n</div><p>Dok&#xE1;&#x17E;e&#x161; napsat program, kter&#xFD; diodu postupn&#x11B;, plynule rozsv&#xED;t&#xED;?</p>\n<div class=\"solution\" id=\"solution-0\">\n    <h3>&#x158;e&#x161;en&#xED;</h3>\n    <div class=\"solution-cover\">\n        <a href=\"/2019/brno-jaro-2019-pondeli/micropython/pwm/index/solutions/0/\"><span class=\"link-text\">Uk&#xE1;zat &#x159;e&#x161;en&#xED;</span></a>\n    </div>\n    <div class=\"solution-body\" aria-hidden=\"true\">\n        <div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">machine</span> <span class=\"kn\">import</span> <span class=\"n\">Pin</span>\n<span class=\"kn\">from</span> <span class=\"nn\">time</span> <span class=\"kn\">import</span> <span class=\"n\">sleep</span>\n\n<span class=\"n\">pin_diody</span> <span class=\"o\">=</span> <span class=\"n\">Pin</span><span class=\"p\">(</span><span class=\"mi\">14</span><span class=\"p\">,</span> <span class=\"n\">Pin</span><span class=\"o\">.</span><span class=\"n\">OUT</span><span class=\"p\">)</span>\n\n<span class=\"k\">while</span> <span class=\"bp\">True</span><span class=\"p\">:</span>\n    <span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"mi\">0</span>\n    <span class=\"k\">while</span> <span class=\"bp\">True</span><span class=\"p\">:</span>\n        <span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n        <span class=\"n\">pin_diody</span><span class=\"o\">.</span><span class=\"n\">value</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n        <span class=\"n\">sleep</span><span class=\"p\">((</span><span class=\"mi\">100</span><span class=\"o\">-</span><span class=\"n\">x</span><span class=\"p\">)</span><span class=\"o\">/</span><span class=\"mi\">10000</span><span class=\"p\">)</span>\n        <span class=\"n\">pin_diody</span><span class=\"o\">.</span><span class=\"n\">value</span><span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n        <span class=\"n\">sleep</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"o\">/</span><span class=\"mi\">10000</span><span class=\"p\">)</span>\n\n        <span class=\"k\">if</span> <span class=\"n\">x</span> <span class=\"o\">&gt;</span> <span class=\"mi\">100</span><span class=\"p\">:</span>\n            <span class=\"k\">break</span>\n</pre></div><p>Princip je &#xFA;pln&#x11B; stejn&#xFD;, jen prom&#x11B;nn&#xE1; <code>x</code> se neust&#xE1;le m&#x11B;n&#xED; a t&#xED;m ovliv&#x148;uje\nintenzitu sv&#xED;cen&#xED;.</p>\n    </div>\n</div><p>Proto&#x17E;e je takov&#xE9;hle rychl&#xE9; blik&#xE1;n&#xED; u&#x17E;ite&#x10D;n&#xE9; ve spoust&#x11B;\nr&#x16F;zn&#xFD;ch situac&#xED;, obsahuje MicroPython speci&#xE1;ln&#xED; funkci: um&#xED; blikat samostatn&#x11B;.\nNastav&#xED;&#x161;, jak rychle m&#xE1; blikat a jak dlouho m&#xE1; trvat\nka&#x17E;d&#xE9; bliknut&#xED;, a MicroPython pak bude blikat automaticky,\nzat&#xED;mco tv&#x16F;j program se m&#x16F;&#x17E;e v&#x11B;novat n&#x11B;&#x10D;emu jin&#xE9;mu.</p>\n<p>T&#xE9;hle funkci se &#x159;&#xED;k&#xE1; <em>pulzn&#x11B; &#x161;&#xED;&#x159;kov&#xE1; modulace</em> &#x2013;\nangl. <em>Pulse Width Modulation</em>, neboli <em>PWM</em>.\nZ&#xA0;MicroPythonu jde tahle funkce ovl&#xE1;dat pomoc&#xED; t&#x159;&#xED;dy\n<code>machine.PWM</code>.\nKa&#x17E;d&#xFD; objekt t&#xE9;hle t&#x159;&#xED;dy um&#xED; ovl&#xE1;dat jednu no&#x17E;i&#x10D;ku\na daj&#xED; se u n&#x11B;j nastavit dva parametry:</p>\n<ul>\n<li><code>freq</code> &#x2013; frekvence, tedy kolikr&#xE1;t za sekundu se LED rozsv&#xED;t&#xED; a zase zhasne a</li>\n<li><code>duty</code> &#x2013; anglicky <em>duty cycle</em>, &#x10D;esky <em>st&#x159;&#xED;da</em>, nastavuje &#x201E;&#x161;&#xED;&#x159;ku pulzu&#x201D;,\ntedy jak dlouho bude dioda p&#x159;i ka&#x17E;d&#xE9;m bliknut&#xED; sv&#xED;tit.\nHodnota <code>duty</code> m&#x16F;&#x17E;e b&#xFD;t od 0, kdy LED\nnesv&#xED;t&#xED; v&#x16F;bec, do 1023, kdy sv&#xED;t&#xED; celou dobu.\nNastav&#xED;&#x161;-li <code>duty=512</code>, bude dioda\nsv&#xED;tit s polovi&#x10D;n&#xED; intenzitou (512 = 1024/2).</li>\n</ul>\n<p>Nastav&#xED;&#x161;-li <code>PWM(freq=50, duty=512)</code>, dioda bude blikat 50&#xD7; za sekundu.\nV&#x17E;dycky jednu setinu vte&#x159;iny bude sv&#xED;tit a na jednu\nsetinu vte&#x159;iny zhasne.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">machine</span> <span class=\"kn\">import</span> <span class=\"n\">Pin</span><span class=\"p\">,</span> <span class=\"n\">PWM</span>\n\n<span class=\"n\">pin_diody</span> <span class=\"o\">=</span> <span class=\"n\">Pin</span><span class=\"p\">(</span><span class=\"mi\">14</span><span class=\"p\">,</span> <span class=\"n\">Pin</span><span class=\"o\">.</span><span class=\"n\">OUT</span><span class=\"p\">)</span>\n<span class=\"n\">pwm</span> <span class=\"o\">=</span> <span class=\"n\">PWM</span><span class=\"p\">(</span><span class=\"n\">pin_diody</span><span class=\"p\">,</span> <span class=\"n\">freq</span><span class=\"o\">=</span><span class=\"mi\">50</span><span class=\"p\">,</span> <span class=\"n\">duty</span><span class=\"o\">=</span><span class=\"mi\">512</span><span class=\"p\">)</span>\n</pre></div><p>Zkus nastavit i ni&#x17E;&#x161;&#xED; frekvenci, t&#x159;eba 3 nebo 1, a&#x165; blik&#xE1;n&#xED; vid&#xED;&#x161; p&#x159;&#xED;mo!</p>\n<p>PWM se d&#xE1; zru&#x161;it metodou <code>pwm.deinit()</code>.\nJako s otv&#xED;r&#xE1;n&#xED;m soubor&#x16F;, je dobr&#xE9; po sob&#x11B; uklidit &#x2013;\ni kdy&#x17E; zat&#xED;m m&#x16F;&#x17E;e&#x161; jednodu&#x161;e restartovat cel&#xE9; za&#x159;&#xED;zen&#xED;.</p>\n\n\n        "
    }
  }
}