Přejít k navigační liště

Zdroják » Mobilní vývoj » QR Box ze Slevomat hackathonu

QR Box ze Slevomat hackathonu

O víkendu 10.1.-11.1. pořádal Slevomat mobilní hackathon zaměřený na možnosti využití NFC, iBeacons a QR kódu v mobilních zařízení. Z cca 20 účastníků se většina vrhla na iBeacons. Technologie sice krásná, ale dle mého názoru je to zatím jen technologická hračka v mobilních telefonech, stejně jako NFC. Já se vrhnul na staré dobré QR kódy a postavil „inteligentní čtečku“ QR kódů.

Proč

Představte si, že jste si koupili voucher na pivo na hudební festival. U stánku je potřeba ověřit platnost voucheru a kolik piv vám zbývá. Potřebujete optimálně bezobslužné zařízení, která obsluze jen řekne, jestli voucher platí nebo ne. Stačí, když se rozsvítí zelené nebo červené světýlko.

Proč dělat něco jako „inteligentní čtečku“ QR kódů, když má každý mobil, který QR kódy zvládne? Opravdu každý? Zkuste jít mezi normální lidi, a možná budete velmi překvapeni, jaké mobily většina našich spoluobčanů používá. Šlo by samozřejmě na festivalu rozdat výčepákům mobily, ale asi by moc dlouho nevydržely. Navíc vzdáleně do mobilu natlačit za provozu novou verzi aplikace není až tak snadné.

Cílem mého projektu na hackathonu bylo udělat funkční prototyp zařízení, které se jen postaví na pult a ověří platnost voucheru. Takhle zařízení vypadalo po šesti hodinách vývoje v jednom člověku. Lidi se hardware děsně bojí, takže najít někoho do týmu je problém.

image1

Hardware

Srdcem celého zařízení je Raspberry Pi. Tento minipočítač není asi třeba více představovat. Na zamýšlený účel stačí i verze A+, která se u nás prodává za cca 600,-. K Raspberry Pi je také možné snadno připojit další hardware přes GPIO. Pro snímání QR kódu jsem použil kameru Creative Live! Cam Sync HD za cca 400,-, protože byla nejlevnější ze seznamu kompatibilního hardware pro Raspberry Pi. Jiný důvod jsem neměl a jinou kameru po ruce také ne. Pro zobrazení výsledku ověření QR kódu jsem použil maticový LED display 8×8 připojený přes sběrnici I2C. Přeci jenom je to zajímavější než zelená a červená LED. Další náklady pak budou samozřejmě na napájení (baterie, zdroj) a krabičku. Pokud bych takové zařízení provozoval, tak bych hledal krabičku s průhledným víčkem a krytím alespoň IP64. Lze tak vytvořit velmi kompaktní a voděodolné zařízení.

Čtení QR kódů

Pro čtení QR kódů jsem použil knihovnu zbar. Tato knihovna je velmi univerzální a má podporu pro různé programovací jazyky. Nám bude stačit její verze nainstalovaná z balíčku zbar-tools bez podpory pro konkrétní jazyk, i když pro ověření kódu budeme používat Python.

sudo apt-get install zbar-tools

Pro ověření funkčnosti spusťte nástroj zbarcam:

zbarcam -v --nodisplay

Přepínač –v zobrazuje ladící informace a chybové hlášky. Tento přepínač pak nebudeme potřebovat. Přepínač --nodisplay spustí aplikaci jen v příkazové řádce bez uživatelského rozhraní, které vyžaduje spuštěné X windows. Pokud dáte před kameru QR kód nebo podporovaný čárový kód, tak byste měli vidět jeho typ a hodnotu. Pokud chcete jen hodnotu kódu, tak přidejte parametr --raw.

pi@stepanb-raspberrypi-b:~$ zbarcam -v --nodisplay
_zbar_video_open: opened camera device /dev/video0 (fd=5)
_zbar_v4l2_probe: Live! Cam Sync HD VF0770 on usb-bcm2708_usb-1.5 driver uvcvideo (version 3.12.35)
_zbar_v4l2_probe:     capabilities: CAPTURE READWRITE STREAMING
v4l2_reset_crop: crop bounds: 640 x 360 @ (0, 0)
v4l2_reset_crop: current crop win: 640 x 360 @ (0, 0) aspect 1 / 1
ERROR: zbar video in v4l2_reset_crop():
    system error: setting default crop window (VIDIOC_S_CROP): Inappropriate ioctl for device (25)
v4l2_probe_formats: current format: YUYV(56595559) 640 x 360 (line=0x500 size=0x70800)
_zbar_v4l2_probe: using I/O mode: MMAP
v4l2_set_format: set new format: YU12(32315559) 640 x 360 (0x54600)
v4l2_v4l2_mmap_buffers: mapping 4 buffers (of 4 requested)
QR-Code:beer
EAN-13:0640522710362
EAN-13:9788000024318

Z pokusů, které jsem prováděl, tak načtení QR kódu, který je zobrazen na mobilním telefonu, na Raspberry Pi B+ s kamerou Creative Live! Cam Sync HD trvá 5 – 10 vteřin. To mi pro natočení piva přijde přijatelné.

Připojení maticového displeje

Maticový displej se připojuje přes sběrnici I2C. Pokud by vám stačilo jen jednoduché ano-ne, třeba pomocí zelené a červené LED, tak se celé zařízení zjednoduší zejména po softwarové stránce. Počet využitých pinů na GPIO se sníží jen o jeden, takže hardwarové zapojení bude skoro stejné.

U použitého maticového LED displeje stačí propojit zem (gnd) na zem, napájení 3,3 V (vcc) na napájení, SDA na SDA a SCL na SCL. Podívejte se na interaktivní pinout diagram. Všimněte si, že na jednotlivé piny se můžete odkazovat různými názvy, podle použitých knihoven. Pull-up rezistory 1k8 jsou již zapojeny na Raspberry Pi, takže je nemusíte řešit, pokud vašemu zařízení bude tato hodnota vyhovovat. Pro testování bude popsané zapojení stačit.

Pro reálný provoz bych doporučil připojit napájení maticového LED displeje na samostatný zdroj a nevyužívat napájení z desky Raspberry Pi. Nezapomínejte také, že Raspberry Pi vyžaduje na GPIO logiku 3,3 V. 5 V logika, která je třeba běžná na většině desek Arduino, Raspberry Pi zničí. Maticový LED displej, který jsem použil, bez problémů funguje s napájením 3,3 V.

Pro ovládání maticového LED displeje musíte na Raspberry Pi povolit I2C sběrnici. To uděláte zavedením příslušných modulů pro kernel. Nejdříve nainstalujte i2c-tools:

sudo apt-get -y install i2c-tools

Pak spusťte raspi-config a povolte I2C v Advanced options:

image2

Dále je třeba do souboru /etc/modules přidat automatické zavedení modulů i2c-bcm2708 a i2c-dev. V mém případě vypadá /etc/modules následovně:

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.

snd-bcm2835
i2c-bcm2708
i2c-dev

Pak musíte Raspberry Pi restartovat. Moduly můžete samozřejmě zavést ručně pomocí modprobe bez nutnosti restartu.

To, že I2C sběrnice funguje v pořádku, nejjednodušeji ověříte pomocí nástroje i2cdetect. Parametr -y určuje číslo sběrnice. Na původních Raspberry Pi je to 0 na nových, označovaných jako +, je to 1. Na nových verzích se na I2C sběrnici 0 připojuje EEPROM paměť rozšiřujících modulů (HAT), která obsahuje informaci o modulu.

image3

V tabulce pak vidíte adresy připojených I2C zařízení. V mém případě je maticový LED displej připojen na adrese 0x70. Tuto adresu je možné změnit, pokud potřebujete připojit více displejů. Komunikace s I2C sběrnicí je velmi jednoduchá. Každé zařízení má svou adresu a paměťové buňky, do kterých zapisujete nebo z nich čtete. Adresa je 7-bitová, osmý bit slouží pro poslání informace, zda budeme číst nebo zapisovat. O to se stará automaticky knihovna pro I2C komunikaci. Na sběrnici pak máte jedno zařízení „master“, které ovládá až 128 zařízení „slave“.

Práce s maticovým LED displejem je v základních rysech popsána v článku „Maticový displej 8×8 od Adafruitu s I2C interface“. Jediná věc, která není z článku moc jasná, je práce s příkazovými registry maticového LED displeje. Většinou je zvykem, že když chcete něco na takovémto modulu nastavit, tak do příslušné paměťové buňky zapíšete konkrétní hodnotu. To tady platí jen u sudých adres v rozsahu 0x00 – 0x0E, kam zapisujete data pro zobrazení na displeji. U řídících hodnot můžete zapsat do paměťové buňky libovolnou hodnotu v rozsahu 0x00-0xFF. Stačí se paměťové buňky jen „dotknout“. Vlastní hodnota nemá na nastavení vliv.

Protože nejsem grafik a mé estetické cítění není ani na úrovni člověka z paleolitu, který byl schopen vytvořit nádhernou sošku Věstonické venuše, tak doufám, že v tomto poznáte pivo s pěnou:

image4

Kolegové z paleolitu měli jen hlínu a své ruce, já mám, naštěstí, jedničky a nuly:

import smbus

# pivo
data = [
        0b00001111,
        0b10011111,
        0b10111111,
        0b11010000,
        0b11010000,
        0b10110000,
        0b10010000,
        0b00001111
        ]

bus = smbus.SMBus(1)
address = 0x70


# start oscilatoru
bus.write_byte_data(address, 0x21, 1)
# zapnuti displeje
bus.write_byte_data(address, 0x81, 1)

row = 0

for b in data:
        bus.write_byte_data(address, row, b)
        row = row + 2

Aplikace

Aplikace pro ověření konceptu (Proof Of Concept – POC) je velmi jednoduchá. Na pozadí je spuštěna aplikace zbarcam, která zapisuje výsledky na stdout. Ze stdout čte hodnoty Python skript. Určitě existuje lepší řešení, ale jde jen o POC, na který jsem měl kolem 6 hodin, protože jsem se účastnil jen prvního dne hackathonu.

import os
import smbus
import time

address = 0x70

beer_symbol = [
        0b00001111,
        0b10011111,
        0b10111111,
        0b11010000,
        0b11010000,
        0b10110000,
        0b10010000,
        0b00001111
        ]

sad_symbol = [
        0b00111111,
        0b11000000,
        0b11010010,
        0b11000000,
        0b11001100,
        0b11010010,
        0b11000000,
        0b00111111,
        ]

qr_symbol = [
        0b11111011,
        0b11010010,
        0b11110111,
        0b10000001,
        0b00011010,
        0b10110011,
        0b10110010,
        0b10001011,
        ]

def show(data):
        row = 0
        for b in data:
                bus.write_byte_data(address, row, b)
                row = row + 2

bus = smbus.SMBus(1)

bus.write_byte_data(address, 0x21, 1)
bus.write_byte_data(address, 0x81, 1)

p = os.popen('/usr/bin/zbarcam --raw --nodisplay','r')

show(qr_symbol)

while True:
    output = p.readline()
    output = output.strip()
    if len(output) < 1:
                continue

    if output == 'beer':
        show(beer_symbol)
    else:
        show(sad_symbol)

    time.sleep(5)

    show(qr_symbol)

Jak vidíte, tak je zde jen primitivní testování QR kódu, pro ověření možností. V reálném provozu by to vypadalo naprosto jinak.

Pokud bychom se drželi našeho příkladu, že ověřujeme vouchery na pivo na hudebním festivalu, tak mě napadají tři možnosti ověřování platnosti voucheru.

  1. Pivo prodává jen jeden stánek – databáze platných voucherů je přímo v zařízení. SQLite, která by víc než stačila, na Raspberry Pi funguje bez problémů.
  2. Pivo prodává více stánků, ale není k dispozici internet – zařízení jsou zapojena do lokální sítě s jedním ověřovacím serverem. Připojení může být řešeno více způsoby (Ethernet, Wifi, ZigBee, …).
  3. Pivo prodává více stánků a internet je k dispozici – nuda, která naprosto kazí skvělou hračku.

Krabička

I POC musí trochu vypadat, takže jsem si k zařízení vyrobil i krabičku, na kterou se smělo koukat jen zepředu :-). Tentokrát jsem nepoužil 3D tiskárnu, ale jen Kapa desku. Kapa deska se používá zejména pro výrobu reklamních panelů nebo pro podlepování fotografií. Jsou to vlastně dva tvrzené papíry a mezi nimi je polyuretan. Vyrábí se v tloušťkách 3, 5 a 10 mm v základním rozměru 700 x 1000 mm a je extrémně lehká. Na výrobu POC je to skvělý materiál, který se dobře řeže a lepí.

image5

Závěr

Slevomat hackathon pro mě byla skvělá příležitost nakouknout, jaké problémy slevové servery řeší a naučit se něco nového kolem hardware. Doufám, že hackathonů, kde se bude dát dělat hardware, bude čím dál tím víc. Jen mě mrzí, že jsem tentokrát nepotřeboval páječku, osciloskop a 3D tiskárnu.

Komentáře

Subscribe
Upozornit na
guest
10 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Robert

5-10 vteřin na načtení kódu je moc.

Nedává mi to smysl – video o krásném rozlišení, rychlé zpracování obrazu, co tam je ten zásadní faktor, který to tak zpomaluje?

Josef

Asi bude problem v tom, ze se displej leskne. Stejny problem nastava pri cteni bar kodu z mobilu.

Josef

Zkusil bych jit cestou NFC, je levne a vetsina mobilu ji uz ma. Neni zavisle na svetle a reaguje jen do cca 10cm.

Vodník

Ten hardware jsi měl s sebou, nebo jsi to nějak sehnal v průběhu akce? Tedy RPI, kamerku, displej, krabici …

Vodník

Aha, takže to chce ale i myšlenku na produkt dopředu :-)

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.