workshop-micropython0

Poznámka: pokud máte náš systém octopus() z minulého kurzu (2019/07), je lepší ho aktualizovat, protože tam máme opět dost úprav a novinek: 
buď přes 
setup() > connect wifi >  system download (stable)  

nebo z terminálu: 
>>> octopus()  
>>> w()  
>>> from util.setup import deploy   
>>> deploy("https://octopusengine.org/download/micropython/stable.tar") 

a od verze 0.85 už postačí jenom: 
>>> octopus()  
>>> u() 
 >>>                
">>>" toto je takzvaný "prompt",  terminálová výzva, abychom tam něco napsali: příkaz nebo "posloupnost příkazů" 

>>> a = 123      do proměnné se uložila hodnota (číslo 123) 
>>> a           
123              
vytiskne / zobrazí hodnotu proměnné  
nebo print(a) pokud to chcete použít v programu                   

>>> a + 10 
133        
zobrazí vypočtenou hodnotu (jako kalkulačka) 

někdy chceme složitější matematické výrazy, než je  + sčítání - odčítání * násobení / dělení 
>>> import math          
importujeme knihovnu, až když jí potřebujeme, jinak nám zbytečně blokuje operační paměť 

>>> math.log10(1000) 3.0    
>>> math.pi 3.141593                  
počet desetinných míst je omezený                  


*) pouze v této úvodní části jsme naznačili, co píše systém (tučně) a co píšete vy (normálně) - poznámky pak píšeme šikmo 

>>> šipky nahoru nebo dolů  -> historie příkazů 

>>> metoda + tečka > TAB doplnění / nápověda zkuste například: 

>>> import math >>> math.  
a po tečce stisknout TAB > vypíše vám: 
__class__ __name__   pow      acos  acosh     asin      asinh    atan  atan2     atanh     ceil     copysign  cos       cosh      degrees  e  erf       erfc      exp      expm1  fabs      floor     fmod     frexp  gamma     isfinite  isinf    isnan  ldexp     lgamma    log      log10  log2      modf      pi       radians  sin       sinh      sqrt     tan  tanh      trunc 

Micropython má obrovskou výhodu v tom, že běží jako interpret: když uživatel napíše název proměnné, třídy nebo instance objektu, skoro všechno se o nich můžeme dozvědět. Právě proto máme k dispozici všechny metody, po  "tečka TAB".  TAB tedy slouží i jako "nápověda" nebo pro efektivní našeptávač pro dokončování příkazů, což s jistou praxí může znatelně urychlit práci z "komand-lajny" (podobně jako v Linuxu)

Více řádkové "dočasné definice vlastních funkcí": 
def název(parametry): nezapomenout na dvojtečku!  
>>> def suma(x, y):   
...  return x + y 

Pozor na odsazení druhého řádku a důsledné zarovnávání logických bloků. Ukončení definice lze nejrychleji "uENTRováním" (lépe po BACKSPACE). 
... 
... 

>>> 
a zkusíme, jak nám nová funkce funguje:  
>>> suma (1, 2) 
3   

Lambda - pro jednoduché funkce: 
>>> sumaL = lambda a, b: a + b 
>>> sumaL(1, 2) 
3  
Jsou situace, kde je potřeba funkce na jedno použití někde uvnitř jiné funkce. Převážně k tomu se lambda funkce používá. Nám se to ale může hodit pro rychlé jednořádkové definice z konzole.

 
některé základní funkce z standardní knihovny čekací prodlevy:   
program bude pokračovat až po uplynutí dané doby 
from time import sleep > již je v octopus()  
sleep(1)           > 1 sekunda pauza 
sleep_ms(100)      > 100 mili sec  
sleep_us(500)      > 500 micro sec 

teplota u procesoru: 
>>> import esp32 
>>> esp32.raw_temperature() 
127 
hallova sonda - magnetického pole: 
>>> import esp32 
>>> esp32.hall_sensor() 
129                            
cca standard hodnota 
>>> esp32.hall_sensor()  
976                            
po přiložení magnetu     



octopus() + HW

octopus()
nezapomínejte spustit hlavní modul knihoven
po každém novém zapnutí a po resetu

Ukážeme si tři základní třídy: Led, Buzzer a Rgb
včetně odkazů na zdrojové kódy

třída Led > zdrojový kód
led = Led(2)              
instance objektu Led s defaultním nastavením na pinu 2
(což je BUILT_IN_LED - vestavěná modrá LEDka)

led.value(1)             
nastavení hodnoty na "1" - dioda svítí

led.value(0)             
nastavení hodnoty na "0" - dioda nesvítí

blikání poprvé:
while True:
...  led.value(1) 
...  sleep(1)
...  led.value(0) 
...  sleep(1) 

led.value()              
bez parametru vrátí hodnotu nastavení - nyní tedy: 0

led.toggle()
"přepnout" > změní stav - nyní tedy z 0 na 1

blikání podruhé:
while True:
... led.toggle()
... sleep(1)
   
led.blink()              
metoda pro jedno bliknutí blink()  
default parametry: 1s svítí a 1s nesvítí
(což si sami najdete ve zdrojových kódech) 

led.blink(1000,500)      
metoda blink (s parametry: 1s svítí a 0.5s nesvítí) 
parametr se zadává v milisekundách

blikání potřetí:
while True:
... led.blink()

a právě tento příklad máme jako základní ukázku ve složce "examples":
https://github.com/octopusengine/octopuslab/blob/master/esp32-micropython/examples/blink.py 



led2 = Led(33)           
instance objektu Led na pinu 33 
...

shrnutí a další podrobmosti:
led = Led()    
vytvoření instance objektu Led

led.value(1) 
instance objektu "tečka" metoda "( parametry )"
zde: 
hodnota (value) s parametrem  1 znamená, že se LEDka rozsvítí.

. >TAB nabídka metod 

Napište "led" . (tečka) a stiskněte TAB
led.
class       init        module      qualname
value           dict        pin             blink
toggle          state
led. 

dir(led)
['class', 'init', 'module', 'qualname', 'value', 'dict', 'pin', 'blink', 'toggle', 'state']

>>> led.pin
> Pin(2)                 přednastaveno, na ESP32 modulu je BUILT_IN_LED 
                         na pinu 2
>>> led.state
> False

>>> led.value(1)
>>> led.state
1  

 
-----------------------------


třída Buzzer > zdrojový kód
piezzo = Buzzer(18)
piezzo.beep()
 
napřímo přes octopus():
beep()                   
základní pípnutí (1000,50) > 1kHz na 50ms

beep(440,500)            
komorní a 440Hz na 0.5s 

from util.buzzer import notes 
Notes.A4                
440    
k dispozici jsou tóny C3-C7 
tone(440) =>  buzzer.play_tone(Notes.A4)   


from util.buzzer import melody
piezzo.play_melody(melody.mario) 

---------------------------

třída Rgb > zdrojový kód 
ws = Rgb()
deklarace základu je provedena už spuštěním octopus()

ws = Rgb(32,8)
na pinu 32 máme 8 ws LEDek

ws.num
8
nám vrátí property (vlastnost, proměnnou: počet LEDek), 
a vrátí 8, protože jsme nastavili 8 (systém to jinak nepozná)

ws.simpletest()
jednoduchý test, na první LED postupně R > G > B

ws.color(RED)
ws.color((128,64,0))
možnosti zadání barvy RED, GREEN, BLUE, ORANGE, VIOLET, BLACK ....

from util.rgb import wheel
metoda wheel konvertuje číslo na posouvané RGB
>>> wheel(10)
(225, 30, 0)   
>>> wheel(50)
(105, 150, 0) 
 

chceme blikat náhodnými barvami?
from util.rgb import random_color
while True:
... ws.color(random_color())
... sleep(0.3)
....

 
Pokud jste si stáhli octopus-verzi Micropythonu a nastavovali WiFi podle návodu, využijeme skvělé vlastnosti robustnějšího systému (oproti C).
Micropython umí pracovat se soubory, a přímo pracovat nejen se řetězci znaků, ale i s json formátem nebo jednoduchou databází. Všechny nastavené WiFi jsou tedy strukturovaně uložené ve vašem ESP v json-souboru:
config/wifi.json
chcete vidět co tam je? Zadejte: 
(octopus() nemusíte pokaždé, stačí jen po restartu, ale start navíc ničemu neublíží, RAM se průběžně optimalizuje automaticky)

octopus()
f("config/wifi.json")
f jako file vám obsah souboru vypíše

Pro připojení k wifi nám stačí:
octopus()
w()

Na závěr dnešního dílu si ukážeme využití "api třetích stran" - webovou aplikaci, která aktualizuje RGB nastavení podle twitteru:
http://api.thingspeak.com/channels/1417/field/2/last.txt 

Když publikujete například zprávu:
#octopusLAB and #micropython example
#cheerlights orange

výše uvedený odkaz zaktualizuje svůj stav na poslední publikovanou barvu 
za hashtagem #cheerlights 

do knihoven octopus (ve složce ukázek examples) jsme implementovali jednoduchou metodu twitter_rgb(), takže vám stačí zadat pouze pár řádků:

>>> octopus()
>>> w()
>>> from examples.twitter_rgb import twitter_rgb
>>> ws.color(twitter_rgb())

inicializace octopus, připojení k wifi, natažení knihovny a jednorázové spuštění příkazu 
a RGB LEDka vám svítí podle posledního tweetu


Pokud chcete průběžnou aktualizaci, nedávejte to v nekonečné smyčce bez prodlevy, server umlátíte nereálným http dotazováním několikrát za vteřinu, což je krok regulernímu DDoS útoku (Distributed  Denial of Service) takže vás záhy nejspíš odpojí :-)
Ptal bych se nejrychleji jednou za 10 vteřin, lépe tak jednou za minutu.

while True:
...  ws.color(twitter_rgb()) 
...  sleep(30)

kompromis, každých 30 vteřin, stejně rychleji tweetovat nebudete 

zdrojový kód > https://github.com/octopusengine/octopuslab/blob/master/esp32-micropython/examples/twitter_rgb.py 

displej – 7segment x 8 – maxx

8 x 7-mi segmetový displ7: 
>>> d7 = disp7_init()       
nezbytná inicializace: mikrokontroléru se "sdělí", který displej používáme, ten si ho připojí a vyzkouší a předá nám instanci objektu > d7 

>>> d7.show(123.456)        
zobrazení čísla 

>>> d7.show("ahoj")         
omezené zobrazení řetězce  
 ------64-----
| 2            |32
-------1------
|4             | 16
-------8------

blikající pomlčka na nízké úrovni

while True:
  d7.set_register(5,1)
  sleep(1)
  d7.set_register(5,0) 
  sleep(1)

tlačítko

buttons:
>>> B0 = button_init(0)  
B je tlačítko "boot" na pinu 0, je to tlačítko, které má modul již vestavěn a každá ESP deska by ho měla mít, pro výchozí možnost přeprogramování
 
>>> button(B0)
(10, 0)  výchozí hodnota, poměr načtených hodnot logická 0 a log. 1  
(0, 10)  při stisknutém boot 

>>> if button(B0)[0] > 8:
podmínka je splněna i při jednom náhodném zakmitání, stačí nám 9 shodných hodnot, index [0] určuje "první pozici" v poli vrácených hodnot
(pole [] má indexy 0, 1, 2, ...)

například pro ovládání L-R hry: 
h = 100                     
# temporary "global" variable horizontal > center 
def horizontal():
      global h
      if button(L)[0] > 8: h -= 1   |
      # [0] 0 = press to GND [1] not       
      if button(R)[0] > 8: h += 1   
      # debounce 0-10, 9 is ok 
      return h


A trochu pokročilejší verze, kdy stisk tlačítka vyvolá přerušení, které "obsloužíme" podle potřeby:
https://github.com/octopusengine/octopuslab/blob/master/esp32-micropython/examples/button_irq.py 

základ tvoří dva řádky:
button0 = Pin(0, Pin.IN)
button0.irq(trigger=Pin.IRQ_FALLING, handler=irq_handler)
a pak funkce irq_handler() 

ukázky – examples

octopus()
w()
web_server()

> IP je adresa, kterou napíšeme do prohlížeče
blikání po startu:
file_copy("examples/blink.py")
zkopíruje příklad z examples do main.py (ten se spouší po jako hlavní, po startu)

hodiny:
>>>import examples.clock
import napotvé provádí celý blok, toho využijem a jednou hodiny spustíme
po ctrl+C už nenaskočí

stopky podobně

doplnění a shrnutí

octopus help:
h()
podrobněji:  https://www.octopuslab.cz/micropython-octopus-help/ 


co znamená:
setup()  > w, a > cw, sd   > ds, ios

v prvním díle w, a cw, sd 
ve druhém ds, ios
příprava ESP:  https://www.octopuslab.cz/micropython-octopus/

vytváření souborů a spustitelných programů:
(zatím jsme jeli v interaktivním řádkovém modu, možnost ampy run file, ampy pu file, wifi webrepl, blockly...) ale zatím to lze pro jednoduché pokusy obejít: 

>>> with open('examples/pokus.py', 'w') as f:   
>>> f.write(".....")

>>> with open('main.py', 'w') as f:
...  f.write("octopus()\n")
...  f.write("while True:\n")
...  f.write("   led.blink()\n")
...  f.write("   sleep(1)\n")
...        


>>> import os
>>> os.listdir() > soubory a adresáře na flash

nebo:
octopus()
ls("examples")
provede výpis souborů (*.py) a podadresářů (bez přípony)

ap a webserver:
ap = ap_init()
from examples.webserver1 import *
s = webserver_init() 
webserver_run(s) 
         



upgrade z cloudu (musí existovat soubor.tar na url)
>>> from util.setup import deploy
>>> deploy("vaše cesta k url/soubor.tar")
...
deploy("https://octopusengine.org/download/web-ide.tar") 
nebo přímo_
u()        


timer:
timer_init() > tim1
tim1.deinit()
Env.timerLed = 0

button IRQ ...
více vláken (multitask / thread)
(v examnples) 


časovač běhu:
Env.start = ticks_ms() 
start = ticks_diff(ticks_ms(), Env.start)
Env.start = start  > "nulování"

import dht
import machine
d = dht.DHT11(machine.Pin(33))
d.temperature()
0
d.humidity()         

https://www.octopuslab.cz/workshop-micropython2/