Aplikace D1 Dálkový ovladač

Při vytváření složitějších projektů s micro:bitem se nám bude hodit si postavit dálkový ovladač dle svých potřeb a představ. Tato lekce je ukázkou, jaké máme možnosti si ovladač postavit s micro:bitem.

název: D1 Dálkový ovladač
kategorie: D zkušení programátoři
ref.číslo: D1
projekt: kurz micro:bit
verze: 01, 2017-11-07
autor: Ivo Obr, Lanškroun


Předpokládáme, že máme zařízení s micro:bitem, které chceme dálkově ovládat. V dalším budeme tomuto zařízení říkat přijímač, vlastnímu ovladači pak ovladač. Komunikace bude pomocí rádiového přenosu. Tato lekce je sice konkrétním návodem, ale umožní Vám porozumět tématu a upravit si svůj vlastní ovladač podle Vašich potřeb.

Nejdříve si řekneme, co od ovladače budeme očekávat. (v dalších lekcích připravuji návod na stavbu vozítka ovládaného micro:bitem, s ovladačem, který je v této lekci)

  • komunikace mezi ovladačem a přijímačem bezdrátově
  • klávesnice 4×4 (16 tlačítek: 1,2,3,4,5,6,7,8,9,0,A,B,C,D,*,#), odesílání stisknutého znaku
  • odesílání hodnoty náklonu micro:bitu v ose X a oseY
  • možnost přepínat mezi 4 nastavenými kanály (pro eliminaci rušení)
  • odesílání signálu HEART BEAT (že ovladač je připojen)
  • indikace připojení přijímače (pomocí signálu HEART BEAT z přijímače)

Co budeme ke stavbě ovladače potřebovat :

  1. 2 ks micro:bit  (ovladač,  přijímač)
  2. 1 ks EDGE konektor s kolíky
  3. 1 ks membránová klávesnice 4×4
  4. 1 ks žlutá LED dioda
  5. 1 ks RGB LED dioda
  6. spojovací dráty (male-female)
  7. 4 ks odpor 160 ohmů 0,25W
  8. nainstalovaný sériový monitor Tera Term (viz lekce B18) na PC

 

Začneme tím, že si vyzkoušíme funkčnost našeho rádiového přenosu mezi micro:bity a funkčnost sériového monitoru. Pokud máte realizovanou lekci B18, tak by to mělo fungovat na první zapojení.

Program pro ovladač :

from microbit import *
import radio

display.scroll("A")
radio.config(length=32, group=48, power=7)
radio.on()
radio.send("OVLADAC")
while True:
    radio.send("HEART BEAT")
    sleep(1000)

Abychom si nepopletli micro:bity, na začátku se na displeji micro:bitu ovladače vypíše “A”, na displeji micro:bitu přijímače “B”.  Oproti standardním hodnotám rádia je nastaveno group=48 a power=7 a délka přenosu 32. Každou vteřinu bude ovladač odesílat text “HEART BEAT”.

Program pro přijímač :

from microbit import *
import radio

display.scroll("B")
uart.init(9600)
uart.write("PRIJIMAC \n \r")
prijem = ""
radio.config(length=32, group=48, power=7)
radio.on()
uart.write("RADIO ON \n \r")
while True:
    prijem = radio.receive()
    if not(prijem is None):
        uart.write(prijem)
        uart.write("\n \r")

 Po zapnutí micro:bitů a správném nastavení sériového monitoru by se měl na sériovém monitoru opakovat text “HEART BEAT”. (pokud ne, zkuste na ovladači i na přijímači tlačítko reset).

Pro ovladač použijeme membránovou klávesnici 4×4, která pro ovládání dostatečný počet tlačítek a je jednoduchá. Skládá se ze dvou vrstev, jedna vrstva má spojena tlačítka v řádcích, druhá vrstva ve sloupcích. Jestliže stiskneme některé tlačítko, pak se v průsečíku řádku a sloupce vytvoří vodivé spojení (dojde ke kontaktu vrstev).

Obrázek ukazuje princip této klávesnice. Jak program zjistí, která klávesa je stisknutá? Budeme postupně nastavovat v jednotlivých sloupcích digitálně hodnotu 1 (3V). Pokud v prvním sloupci nastavíme digitálně 1 (v ostatních sloupcích je digitálně 0), pak budeme číst hodnotu v jednotlivých řádcích. Pokud máme stisknutou například klávesu “7”, pak je ve třetím řádku na vodiči z klávesnice digitálně 1, v ostatních řádcích je 0. Ze souřadnice sloupce a řádku určíme, jaká klávesa je stisknuta.

(Náš program je postaven na vyhodnocení stisku jen jedné klávesy současně, pokud stiskne klávesy dvě najednou, pak bude vyhodnocena klávesa s vyšším pořadím.)

Pokud nebude žádná klávesa stisknuta, pak jsme nenašli žádný řádek s logickou hodnotou 1. Testování stisknuté klávesy je v programu nastaveno na interval 200ms, to je 5x za vteřinu. Držíme-li klávesu trvale, pak je znak vyhodnocen, jako bychom stiskli klávesu 5x za vteřinu.

Na obrázku jsou uvedeny čísla pinů na micro:bitu, ke kterým připojíme vývody z klávesnice. Sloupce jsou postupně od pinu 16 do pinu 13, řádky pak od pinu 9 do pinu 6. Kód pro test klávesnice je :

# OSAZENI KLAVESNICE
klavesnice = ['1', '2', '3', 'A',
              '4', '5', '6', 'B',
              '7', '8', '9', 'C',
              '*', '0', '#', 'D']
iznak = None


def klavesa():
    global iznak
    iznak = None
    i = 0
    for sloupec in [pin16, pin15, pin14, pin13]:
        sloupec.write_digital(1)
        j = 0
        for radek in [pin9, pin8, pin7, pin6]:
            if radek.read_digital():
                iznak = (i * 4) + j
            j += 1
        sloupec.write_digital(0)
        i += 1

 Každý znak, který je zjištěn je pak odesílán rádiem. Klávesy “A”, “B”, “C” a “D” jsem vyhradil pro přepínání kmitočtů a skupin rádiového přenosu. Na ovladači, pokud bychom se rušili s nějakým jiným rádiovým vysíláním, můžeme přepnout na jiný kanál a jinou skupinu. Také můžeme ovládat nezávisle dvě (tři nebo čtyři) zařízení jedním ovladačem. Znaky (“A”, “B”, “C” a “D”) se také odesílají ještě než dojde k přepnutí kanálu, aby se přijímač na druhé straně přepnul také na správné parametry vysílání (pokud ovládáme jedno zařízení).

V programu je sledován čas a po uplynutí 200ms dojde k testu klávesnice :

def klavesy44():
    global CAS_KLAVESY
    global INT_KLAVESY
    global iznak
    if (running_time() - CAS_KLAVESY) >= INT_KLAVESY:
        klavesa()
        if not(iznak is None):
            znak = klavesnice[iznak]
            radio.send(znak)
            if (znak in ['A', 'B', 'C', 'D']):
                zap_radio(znak)
            CAS_KLAVESY = running_time()
            iznak = None

Zapínání rádia se provede funkcí “zap_radio(znak)”, kde znak je hodnota “A” nebo “B” nebo “C” nebo “D” přečtená z klávesnice.

# PARAMETRY RADIA
A_CHANNEL = 51
A_GROUP = 201
B_CHANNEL = 61
B_GROUP = 211
C_CHANNEL = 71
C_GROUP = 221
D_CHANNEL = 81
D_GROUP = 231

def zap_radio(kanal):
    pin11.write_digital(0)
    pin12.write_digital(0)
    radio.off()
    if (kanal == 'A'):
        radio.config(length=32, channel=A_CHANNEL, group=A_GROUP, power=7)
    if (kanal == 'B'):
        radio.config(length=32, channel=B_CHANNEL, group=B_GROUP, power=7)
        pin11.write_digital(1)
    if (kanal == 'C'):
        radio.config(length=32, channel=C_CHANNEL, group=C_GROUP, power=7)
        pin12.write_digital(1)
    if (kanal == 'D'):
        radio.config(length=32, channel=D_CHANNEL, group=D_GROUP, power=7)
        pin11.write_digital(1)
        pin12.write_digital(1)
    radio.on()

 Vysílací kanály a skupiny je možno upravit, vždy je ale třeba, aby stejné hodnoty byly i na přijímači. RGB LED diodu (červená- pin11, zelená – pin12) zapojíme do pinů 11 a 12 na microbitu přes omezovací odpor 160 ohmů. LED dioda svítí dle nastaveného kanálu takto :

A – nesvítí

B – červená

C – zelená

D – žlutá

Všechny časové intervaly jsou uvedeny v kódu :

# CASOVE INTERVALY
CAS_KLAVESY = running_time()
INT_KLAVESY = 200
CAS_GYRO = running_time()
INT_GYRO = 97
CAS_HBS = running_time()
INT_HBS = 1000
CAS_HBR = running_time()
INT_HBR = 3000

Hodnoty z gyroskopu jsou přenášeny v časovém intervalu INT_GYRO = 97. Jedná se o souřadnice v ose X (náklon micro:bitu vpravo-vlevo) a v ose Y(náklon micro:bitu dopředu-dozadu). Hodnoty jsou přenášeny samostatně jako dva řetězce znaků. Před těmito řetězci je poslán znak “S”, aby přijímač měl informaci, že budou následovat dva řetězce znaků (X a Y).

def gyro():
    global CAS_GYRO
    global INT_GYRO
    if (running_time() - CAS_GYRO) >= INT_GYRO:
        radio.send('S')
        radio.send(str(accelerometer.get_x()))
        radio.send(str(accelerometer.get_y()))
        CAS_GYRO = running_time()

Zbývá nám ještě signál HEART BEAT, který nám monitoruje spojení mezi ovladačem a přijímačem. Ovladač každou vteřinou vysílá na rádio znak “H”, který může být identifikován na přijímači jako že je spojení v pořádku. Také naopak přijímá signál z přijímače (ovládaného zařízení). Pokud signál z přijímače chodí, je toto indikováno LED diodou připojenou přes omezovací odpor na pin5. Takže pokud tato dioda svítí, je spojení ovladače a přijímače OK. Pokud po dobu 3 vteřin nepřijde signál (znak “H”) z přijímače, pak je tento stav vyhodnocen jako ztráta spojení a LED dioda zhasne. (Na pin5 je digital 0).

def HB():
    global CAS_HBR
    global INT_HBR
    global CAS_HBS
    global INT_HBS
    # HEART BEAT SEND
    if (running_time() - CAS_HBS) >= INT_HBS:
        radio.send('H')
        if (running_time() - CAS_HBR) >= INT_HBR:
            radio.send('?')
            pin5.write_digital(0)  # indikace LED HB off
        CAS_HBS = running_time()
    # HEART BEAT RECEIVE
    prijem = radio.receive()
    if not(prijem is None):
        if (prijem == 'H'):
            CAS_HBR = running_time()
            pin5.write_digital(1)  # indikace LED HB on

 

Poznámka:

Pokud připojíte piny klávesnice a LED diod jinak než podle tohoto návodu, je možné, že Vám program ovladače nebude fungovat.

Celý program ovladače a přijímače najdete na konci této lekce. Nejdříve si vyzkoušíme, jak to funguje. Nahrajeme oba programy do micro:bitů. Pokud jsme pracovali pozorně, funguje vše na první zapojení.

K vlastní mechanické realizaci jsem použil elektrikářskou krabičku  80x80x28mm.  Tato lekce není návodem na konkrétní mechanickou stavbu. Někdo si vytiskne krabičku na 3D tiskárně, někdo slepí z tvrdého kartonu.

 

LED diody a omezovací odpory a spojové dráty jsem připájel k destičce pro jednorázovou montáž viz obrázek. Celkový pohled na ovladač takto zhotovený je na posledním obrázku.

 

 

 

 

 

 

Pokud budete chtít experimentovat a měnit  funkce ovladače, doporučuji nastavit si delší časy pro “X” a “Y”, aby jste dokázali sledovat komunikaci mezi ovladačem a přijímačem na sériovém monitoru.

A  nakonec oba programy.

Program pro ovladač:

from microbit import *
import radio

# PARAMETRY RADIA
A_CHANNEL = 51
A_GROUP = 201
B_CHANNEL = 61
B_GROUP = 211
C_CHANNEL = 71
C_GROUP = 221
D_CHANNEL = 81
D_GROUP = 231

# CASOVE INTERVALY
CAS_KLAVESY = running_time()
INT_KLAVESY = 200
CAS_GYRO = running_time()
INT_GYRO = 97
CAS_HBS = running_time()
INT_HBS = 1000
CAS_HBR = running_time()
INT_HBR = 3000

# OSAZENI KLAVESNICE
klavesnice = ['1', '2', '3', 'A',
              '4', '5', '6', 'B',
              '7', '8', '9', 'C',
              '*', '0', '#', 'D']
iznak = None


def klavesa():
    global iznak
    iznak = None
    i = 0
    for radek in [pin16, pin15, pin14, pin13]:
        radek.write_digital(1)
        j = 0
        for sloupec in [pin9, pin8, pin7, pin6]:
            if sloupec.read_digital():
                iznak = (i * 4) + j
            j += 1
        radek.write_digital(0)
        i += 1


def zap_radio(kanal):
    pin11.write_digital(0)
    pin12.write_digital(0)
    radio.off()
    if (kanal == 'A'):
        radio.config(length=32, channel=A_CHANNEL, group=A_GROUP, power=7)
    if (kanal == 'B'):
        radio.config(length=32, channel=B_CHANNEL, group=B_GROUP, power=7)
        pin11.write_digital(1)
    if (kanal == 'C'):
        radio.config(length=32, channel=C_CHANNEL, group=C_GROUP, power=7)
        pin12.write_digital(1)
    if (kanal == 'D'):
        radio.config(length=32, channel=D_CHANNEL, group=D_GROUP, power=7)
        pin11.write_digital(1)
        pin12.write_digital(1)
    radio.on()


display.scroll("A")
zap_radio('A')
while True:
    # KLAVESY
    if (running_time() - CAS_KLAVESY) >= INT_KLAVESY:
        klavesa()
        if not(iznak is None):
            znak = klavesnice[iznak]
            radio.send(znak)
            if (znak in ['A', 'B', 'C', 'D']):
                zap_radio(znak)
            CAS_KLAVESY = running_time()
            iznak = None
    # GYRO
    if (running_time() - CAS_GYRO) >= INT_GYRO:
        radio.send('S')
        radio.send(str(accelerometer.get_x()))
        radio.send(str(accelerometer.get_y()))
        CAS_GYRO = running_time()
    # HEART BEAT SEND
    if (running_time() - CAS_HBS) >= INT_HBS:
        radio.send('H')
        if (running_time() - CAS_HBR) >= INT_HBR:
            radio.send('?')
            pin5.write_digital(0)  # indikace LED HB off
        CAS_HBS = running_time()
    # HEART BEAT RECEIVE
    prijem = radio.receive()
    if not(prijem is None):
        if (prijem == 'H'):
            CAS_HBR = running_time()
            pin5.write_digital(1)  # indikace LED HB on

Program pro přijímač (je na Vás, jak s tím naložíte, asi by něco podobného mělo být součástí Vašeho ovládaného zařízení):

from microbit import *
import radio

# PARAMETRY RADIA
A_CHANNEL = 51
A_GROUP = 201
B_CHANNEL = 61
B_GROUP = 211
C_CHANNEL = 71
C_GROUP = 221
D_CHANNEL = 81
D_GROUP = 231

# CASOVE INTERVALY
CAS_HBS = running_time()
INT_HBS = 1000
CAS_HBR = running_time()
INT_HBR = 3000

def zap_radio(kanal):
    radio.off()
    if (kanal == 'A'):
        radio.config(length=16, channel=A_CHANNEL, group=A_GROUP, power=7)
    if (kanal == 'B'):
        radio.config(length=16, channel=B_CHANNEL, group=B_GROUP, power=7)
    if (kanal == 'C'):
        radio.config(length=16, channel=C_CHANNEL, group=C_GROUP, power=7)
    if (kanal == 'D'):
        radio.config(length=16, channel=D_CHANNEL, group=D_GROUP, power=7)
    radio.on()


display.scroll("B")
uart.init(115200)
uart.write("PRIJIMAC \n \r")
prijem = ""
radio.config(length=32, channel=A_CHANNEL, group=A_GROUP, power=7)
zap_radio('A')
uart.write("RADIO ON \n \r")
while True:
    prijem = radio.receive()
    if not(prijem is None):
        uart.write(prijem)
        uart.write("\n \r")
        if (prijem == 'S'):
            X = radio.receive()
            while (X is None):
                X = radio.receive()
            uart.write(X)
            uart.write(' ')
            Y = radio.receive()
            while (Y is None):
                Y = radio.receive()
            uart.write(Y)
            uart.write("\n \r")
        if (prijem in ['A', 'B', 'C', 'D']):
            uart.write("KANAL ")
            uart.write(prijem)
            uart.write("\n \r")
            zap_radio(prijem)
        if (prijem == 'H'):    # prisel signal HEART BEAT od prijimace
            CAS_HBR = running_time()
    # HEART BEAT SEND
    if (running_time() - CAS_HBS) >= INT_HBS:
        radio.send('H')
        if (running_time() - CAS_HBR) >= INT_HBR:
            uart.write("NENI OVLADAC \n \r")
        CAS_HBS = running_time()
Posted in aplikace, kat D - zkušení programátoři.