Close

Arduino projekty: Keypad a robotická ruka

Robotické rameno, krok 12.

Dnešní díl bude věnován praktickým aplikacím Arduina. V první části si předvedeme, jak pracovat s keypadem s dvanácti tlačítky. Vytvoříme si velmi jednoduchý zabezpečovací systém a také si ukážeme, jak si při programování zkrátit čas – vytvoříme si klávesnici pro programátory. V druhé části se dostaneme k servomotorům. Ukážeme si, jak se ovládají a poté si sestavíme kreslící robotickou ruku.

Keypad

V tomto článku budeme pracovat s tímto dvanáctitlačítkovým keypadem. Můžete použít ale také jiný keypad, například maticovou klávesnici se 16 tlačítky. Jeho tlačítka jsou uspořádány do matice 3 x 4. Jistě si vzpomínáte, jak jsme ve dvanáctém článku ovládali maticový displej. Práce s keypadem je velmi podobná práci s displejem. Tlačítka jsou seřazena do třech sloupců a čtyř řádků, kdy každému je přiřazen jeden pin. Propojení je znázorněno na obrázku.

Vnitřní propojení keypadu

Vnitřní propojení keypadu

Je tedy zřejmé, že při stisknutí tlačítka [1] jsou propojeny piny 2 a 3. Pokud bychom si chtěli připojit toto tlačítko k Arduinu, na pin 2 by bylo připojeno +5V a na pin 2 přes 10k ohm resistor GND a také vstup (standardní připojení tlačítka). My ale potřebujeme zjistit stav všech dvanácti tlačítek. To provedeme tak, že si vybereme sloupce nebo řádky. Poté všechny piny jednoho typu připojíme na vstupy Arduina a přes 10k ohm resistor na GND. Druhou skupinu připojíme na výstupy. Do těch budeme stále dokola střídavě pouštět proud, který poté budeme detekovat na vstupech. K dispozici pak máme dvě informace: na jaký pin pouštíme proud a na kterém jsme ho detekovali. Z těchto informací už můžeme zjistit, jaké tlačítko je stisknuto.

Zapojení a programování

Jako první příklad si vytvoříme program, který po stisknutí tlačítka vypíše po sériové lince jemu odpovídající znak. Pokud tlačítko budeme držet stisknuté, znak se bude v určitém časovém intervalu opakovat. Můžeme si vybrat, jakým způsobem keypad zapojíme. Použijeme variantu, kdy řádky (2, 4, 6, 7) budou připojeny na výstupy Arduina a sloupce (1, 3, 5) na vstupy a také přes 10k resistor na GND. V této části použijeme Arduino Micro, které budeme potřebovat při tvorbě klávesnice (také bychom mohli využít Arduino Leonardo). Pokud nevíte, proč budeme muset při tvorbě klávesnice použít právě tyto dvě desky, můžete si to připomenout v osmém článku. Keypad s Arduinem je možné propojit různými způsoby. My si zvolíme zapojení, kdy je pin n keypadu připojen na pin n+1 Arduina. Pin 1 je tedy připojen na pin 2, pin 2 na pin 3 atd. Zapojení je k vidění na obrázku.

Připojení keypadu a Arduina Micro

Zapojení Keypadu

Na začátku musíme programu říct, jaké piny jsou připojeny na co. To budeme mít uloženo ve dvou polích – sloupce a radky. Navíc si sloupce a řádky seřadíme z leva doprava a odshora dolů. Vytvoříme si dvojrozměrné pole se znaky odpovídajícími klávesám. Poté si piny odpovídající řádkům nastavíme jako výstupy a sloupce jako vstupy. V těle funkce setup() si ještě nastavíme aktuální čas. Ve funkci loop() budeme neustále dokola pouštět proud do jednotlivých řádků a detekovat jeho průchod na sloupcích.

byte radky[4] = {3,8,7,5};
byte sloupce[3] = {4,2,6};

char znaky[4][3] = {{'1','2','3'},
                   {'4','5','6'},
                   {'7','8','9'},
                   {'*','0','#'}};

int cekej = 200;
long cas;

void setup(){
    for(int i = 0; i < 4; i++){
        pinMode(radky[i], OUTPUT);
    }  
    for(int i = 0; i < 3; i++){
        pinMode(sloupce[i], INPUT);
    }
    
    cas = millis();
}

void loop(){
    for(int a = 0; a < 4; a++){
        digitalWrite(radky[a],HIGH);
        for(int b = 0; b < 3; b++){
            if(digitalRead(sloupce[b]) == HIGH && millis() - cekej > cas){
                Serial.println(znaky[a][b]);
                cas = millis();
            }
        }
        digitalWrite(radky[a],LOW);
    }        
}

Bezpečnostní systém

V této části bude naším úkolem naprogramovat jednoduché bezpečnostní zařízení. To bude vybaveno keypadem pro zadávání kódu a piezzo bzučákem, který začne pípat při zadání špatného kódu. Ten bude připojený na pin 10. Stisknuté znaky z keypadu se budou nahrávat do řetězce. Znak # bude sloužit k vynulování řetězce a * k potvrzení zadání kódu. Vše je vysvětleno v programu níže. Vyjdeme z kódu z předchozího příkladu. Předpokládejme, že náš kód nebude delší než 100 znaků.

Klávesnice pro zabezpečovací systém s Arduinem Micro

Keypad s bzučákem

byte radky[4] = {3,8,7,5};
byte sloupce[3] = {4,2,6};

char znaky[4][3] = {{'1','2','3'},
                   {'4','5','6'},
                   {'7','8','9'},
                   {'*','0','#'}};

int cekej = 200;
long cas;

byte pozice = 0; //pomocná proměnná udávající aktuální znak
byte chyby; //proměnná pro ukládání neshod kódů
char spravnyKod[100] = "12321";
char kod[100];

void setup(){
    for(int i = 0; i < 4; i++){
        pinMode(radky[i], OUTPUT);
    }  
    for(int i = 0; i < 3; i++){
        pinMode(sloupce[i], INPUT);
    }
    
    cas = millis();
}

void loop(){
    for(int a = 0; a < 4; a++){
        digitalWrite(radky[a],HIGH);
        for(int b = 0; b < 3; b++){
            if(digitalRead(sloupce[b]) == HIGH 
			&& millis() - cekej > cas){
                tone(10,440,100);
                cas = millis();
                
                if(znaky[a][b] == '#'){ 
				//pokud najde křížek, vymaže kod
                    vynuluj();
                }
                else if(znaky[a][b] == '*'){ 
				//když najde hvězdičku, zkontroluje shodu
                    for(int c = 0; c < 100; c++){
                        if(kod[c] != spravnyKod[c]){
                            chyby++;
                        }
                    }
                    if(chyby > 0){
                        vynuluj();
                        for(int d = 0; d < 10; d++){ //siréna
                            for(int c = 200; c < 2000; c++){
                                tone(10, c, 5);
                            }
                            for(int c = 2000; c > 200; c--){
                                tone(10, c, 5);
                            }
                        }
                    }    
                    else{
                        vynuluj();
                        tone(10, 1000, 100); //třikrát pípne
                        delay(200);
                        tone(10, 1000, 100);
                        delay(200);
                        tone(10, 1000, 100);
                    } 
                }
                else{
                    kod[pozice] = znaky[a][b];
                    pozice++;
                }
            }
        }
        digitalWrite(radky[a],LOW);
    }        
}

void vynuluj(){ //funkce pro vymazání řetězce kod
    for(int c = 0; c < 100; c++){
        kod[c] = 0;
    }
    pozice = 0; 
    chyby = 0;   
}

Programátorská klávesnice

Posledním příkladem využívajícím keypad je slibovaná programátorská klávesnice. Ta naše bude používat jenom osm kláves keypadu – pro každý typ závorek dvojici kláves (pravá a levá závorka). ASCII kódy jednotlivých znaků v desítkové soustavě vidíte v tabulce.

Znak ASCII kód
( 40
) 41
{ 123
} 125
[ 91
] 93
< 60
> 62

Tyto kódy přepíšeme do pole znaky. Stisknutí klávesy do počítače odešleme pomocí funkce Keyboard.print() (viz osmý článek). Dále je kód stejný jako v předchozích příkladech. Když odešleme tyto znaky do PC, budou správně fungovat, jen pokud máme nastavenou anglickou klávesnici. Pokud tomu tak je použijeme pro odeslání znaku funkci zmackniAnglicky – ta odešle pouze hodnotu znaku. Pokud ale máme nastavenou českou klávesnici, musíme před odesláním znaku přepnout na anglickou a po odeslání zase zpět. K přepínání jazyků slouží klávesová zkratka L_ALT + L_SHIFT. Pro speciální klávesy má Arduino vyhrazené konstanty, o nichž nalezneme podrobnější informace zde. Kód klávesnice vypadá následovně.

byte radky[4] = {3,8,7,5};
byte sloupce[3] = {4,2,6};

char znaky[4][3] = {{40,41,' '},
                   {123,125,' '},
                   {91,93,' '},
                   {60,62,' '}};

int cekej = 200;
long cas;

void setup(){
    for(int i = 0; i < 4; i++){
        pinMode(radky[i], OUTPUT);
    }  
    for(int i = 0; i < 3; i++){
        pinMode(sloupce[i], INPUT);
    }
    
    cas = millis();
}

void loop(){
    for(int a = 0; a < 4; a++){
        digitalWrite(radky[a],HIGH);
        for(int b = 0; b < 3; b++){
            if(digitalRead(sloupce[b]) == HIGH 
			&& (millis() - cekej) >= cas){
                zmackniCesky(znaky[a][b]);
                cas = millis();
            }
        }
        digitalWrite(radky[a],LOW);
    }        
}

void zmackniCesky(char znak){
    Keyboard.press(KEY_LEFT_ALT);
    delay(10);
    Keyboard.press(KEY_LEFT_SHIFT);
    delay(10);
    Keyboard.releaseAll();
    delay(10);
    Keyboard.print(znak);
    delay(10);
    Keyboard.press(KEY_LEFT_ALT);
    delay(10);
    Keyboard.press(KEY_LEFT_SHIFT);
    delay(10);
    Keyboard.releaseAll();
    delay(10);
}

void zmackniAnglicky(char znak){
    Keyboard.print(znak);
}

Uvedené kódy mohou sloužit jako základ pro další tvorbu – jednoduchou úpravou se dá vytvořit například smajlíková klávesnice.

Servomotory

Pro účely práce se servomotory je Arduino vybaveno knihovnou Servo.h. Tu do kódu vložíme příkazem #include <Servo.h>. Knihovna obsahuje několik funkcí a příkazů, z nichž nejpoužívanější jsou:

  • Servo motor – vytvoří objekt Servo se jménem motor (jméno je volitelné)
  • motor.attach(pin) – řekne programu, na kterém pinu je servo připojeno
  • motor.write(hodnota) – nastaví pozici serva, hodnota je většinou v rozmezí 0 až 180 (občas i méně)

Ze serva vychází tři vodiče – žlutý/oranžový, hnědý a červený, odpovídající postupně signálu (připojuje se k Arduinu), GND a +5V. Jednoduchý program, který vezme hodnotu naměřenou na pinu A0, upraví její rozsah a odešle ji jako pozici serva, vypadá takto.

#include <Servo.h>
 
Servo motor;
int h; //hodnota měření

 
void setup(){ 
    motor.attach(10); //připojíme servo na pin 10
} 
 
 
void loop(){ 
    h = map(analogRead(A5),0,1024,0,180); 
    
    motor.write(h);
}  

To je k teorii řízení serv vše. Jednoduché že? Nyní se tedy můžeme pustit do projektu robotické ruky.

Robotická ruka

Cílem tohoto příkladu bude vytvořit jednoduchou robotickou ruku, která bude mít na konci fixu. Tou budeme moct vytvářet kresby na papíru. Budeme potřebovat:

  1. Dřevo na mechanické konstrukce – v našem případě dřevěná laťka s průřezem 20x5mm.
  2. Tavná pistole (nebo šrouby a herkules či jiné lepidlo – v závislosti na provedení)
  3. Vodiče
  4. Piny
  5. Dutinkovou lištu – třípinovou
  6. Kousek prototypovacího plošného spoje
  7. 2x 10k potenciometr s lineárním průběhem
  8. velké servo s konstrukcí
  9. střední servo
  10. Klip na papíry o velikosti pera, se kterým budeme kreslit
  11. Dřevěnou desku o rozměrech alespoň 30x40cm

Začneme tím, že si nařežeme dřevěné části. Uřízneme jednu 17 cm dlouhou, jednu 15 cm dlouhou a dvě třícentimetrové části. Na jeden konec patnácticentimetrové laťky navrtáme dvě dírky se stejnou roztečí, jako ty na konstrukci u velkého serva. Na druhý konec vyřežeme obdélníkovou díru velikosti menšího serva. Sem servo vložíme a zalepíme nebo přišroubujeme.

Robotické rameno, krok 2.

Menší rameno

V dalším kroku přišroubujeme vytvořené rameno ke konstrukci většího serva.

Budeme pokračovat úpravou delší laťky. Na jeden konec nalepíme plastový kulatý převod menšího serva plochou stranou ke dřevu. Slepíme dva nejmenší kousky dřeva největší stranou k sobě a přilepíme je v pravém úhlu na druhý konec laťky. Na takto vzniklou podpěru přilepíme klip na papíry.

Robotické rameno, krok 4.

Na dřevěnou desku přilepíme, nebo přišroubujeme část konstrukce velkého serva (plastovou částí nahoru). Rozměry můžete vidět na obrázku.

Robotické rameno, krok 6.
Robotické rameno, krok 7.

Velké servo připojíme k Arduinu a funkcí .write() ho nastavíme na polohu 105. Poté nasadíme první rameno rovnoběžně s delším okrajem.

Robotické rameno, krok 8.

Připojíme malé servo a nastavíme ho na hodnotu 60. Poté připojíme druhé rameno kolmo k prvnímu.

Robotické rameno, krok 9.

Jelikož má menší servo krátký kabel, musíme si vyrobit „prodlužku“. Budeme potřebovat třížilový kabel, na jehož jednom konci budou piny a na druhém zdířky.

Robotické rameno, krok 10.

Nyní přichází na řadu zapojení. V tomto příkladu je použito následující: Velké servo je připojeno na pin A3, malé na A2. Také využijeme dva potenciometry, kterými budeme nastavovat polohu serv. Ty jsou připojeny k pinům A5 a A4. Výběr pinů však záleží čistě na nás. Na obrázku níže vidíte příklad konstrukce ovládání.

Robotické rameno, krok 11.
#include <Servo.h>
 
Servo sv, sm; 
int h1, h2; //hodnoty měření

 
void setup(){ 
    sv.attach(A3); 
    sm.attach(A2); 
} 
 
 
void loop(){ 
    h1 = map(analogRead(A5),0,1024,0,170); 
    h2 = map(analogRead(A4),0,1024,0,170); 
    
    sv.write(h1);
    sm.write(h2);
    
    Serial.println(h2);
}  

Už máme vše sestaveno a zapojeno i naprogramováno. Na desku si izolepou upevníme papír A4 (má přibližně stejnou velikost jako naše deska), připevníme tužku, nebo fixu do klipu a můžeme začít malovat.

Robotické rameno, krok 12.

Pokud se vám zdá ovládání, kdy se potenciometry nastavují úhly serv neohrabané, máte jistě pravdu. Poměrně jednoduše se dá ale vytvořit algoritmus, ve kterém budete mít možnost nastavit přímo souřadnice požadovaného bodu. Stačí k tomu jenom pár goniometrických funkcí – to už ale nechám na vás.

Zdroje obrázků

[Obr. 1: Datasheet keypadu]

V případě jakýchkoliv dotazů či nejasností se na mě neváhejte obrátit v komentářích.

Zbyšek Voda

2 Comments on “Arduino projekty: Keypad a robotická ruka

Josef Sýkora
12.11.2016 at 11:43

dobrý den
Smím s zeptat kde najdu popis jednotlivých knihoven např „servo.h“?
Referenční příručku k jednotlivým knihovnám?
Děkuji

Zbyšek Voda
13.11.2016 at 19:26

Dobrý den, nejaktuálnější je tato příručka: https://www.arduino.cc/en/Reference/Servo
Pokud byste se chtěl podívat i na kód, najdete ho na GitHub: https://github.com/arduino/Arduino/tree/master/libraries/Servo

Napsat komentář