Ovládanie vláčikov s joystickom a mikroprocesorom ATtiny13

V prvom článku o ovládaní vláčikov som popísal nápady, myšlienky, ktoré som chcel použiť v hotovom zariadení. Boli tam 4 integrované obvody a 4 miestny displej. To som zredukoval na mikroprocesor ATtiny13 a 3 LED diódy.

Ako to funguje?

Mikroprocesor ATtiny13 sleduje joystick a podľa jeho polohy (dopredu, dozadu, vľavo, vpravo) riadi rýchlosť a smer jazdy lokomotívy. Rýchlosť je regulovaná pomocou PWM a smer jazdy prepínaním polarity napätia. Vo videu uvidíte, ako sa to ovláda.

Schéma zapojenia

Po kliknutí na obrázok sa schéma zobrazí vo väčšom rozlíšení.

Prvá časť schémy je napájací zdroj. Napájanie dodáva zdroj z notebooku, je to 19V jednosmerných.  Stačí to len stabilizovať cez LM317 (vyrába napätie 13V pre vláčiky) a 7805 (vyrába 5V pre napájanie mikroprocesora).

Druhá časť je výkonová. Relé K1 mení polaritu výstupného napätia a tým mení smer jazdy. Tranzistor Q3 spína výstup podla generovaného PWM a tým riadi rýchlosť vlaku. Oba prvky sú riadené mikroprocesorom cez príslušné tranzistory.

TIP : Namiesto BD243 (Q3), môžete použiť akýkoľvek výkonový NPN tranzistor.

Tretia časť je signalizačná. 2 LED diódy ukazujú smer jazdy a tretia výkon.

Štvrtá časť je riadenie.  IC3, mikroprocesor ATtiny13 generuje PWM a spína relé. PWM určuje ako rýchlo a relé ktorým smerom má vlak ísť. Tieto informácie si zistí od polohy joysticku.

Cez koncovky SV1 a SV2. sa dá mikroprocesor pripojiť na programátor  a v budúcnosti jednoducho upraviť program.

Skrinka, joystick a koncovky v nej

Na fotke je zariadenie odfotené zo zadnej strany, aby bolo vidno aj koncovky (aj s mojím náterom, čisto sivá krabička sa mi nepáčila). Joystick je štvorsmerový, dopredu a dozadu riadi výkon, vľavo alebo vpravo mení smer jazdy.  Koncovky prog+ovl slúžia na pripojenie programátora AVR ISP mkII, alebo externého ovládača.

Program pre mikroprocesor

Skladá sa z dvoch častí. Z hlavnej funkcie, ktorá nastaví všetko potrebné a funkcie obsluhy prerušenia, ktorá obsluhuje joystick.

#define F_CPU 9600000UL
#include <avr/io.h>
#include <avr/interrupt.h>

unsigned char delicka = 0x00;     // obsluha joysticku
unsigned char zmena_smeru = 0x00; // obsluha smeru

ISR(TIM0_OVF_vect) // Prerusenie - pretecenie timer0
 {
  TCNT0 = 0x7F;       // nastavenie intervalu casovaca
  if(delicka == 0x03) // spomalenie obsluhy joysticku
  {
  delicka = 0x00;
  switch((PINB & 0x02) | (PINB & 0x04)) // stav joysticku
   {
    case 0x02 : // znizenie vykonu, paka joysticku "DOLE"
        if(OCR0A != 255) OCR0A++;
        break;
    case 0x04 : // zvysenie vykonu, paka joysticku "HORE"
        if(OCR0A != 0x80) OCR0A--;
        break;
    case 0x00 : // zmena smeru, paka joysticku "VLAVO/VRAVO"
        if(OCR0A == 255) // zmena smeru len ak vykon = 0%
         {
          if(zmena_smeru == 0x40)
           {
            zmena_smeru = 0x00;
            PORTB ^= 0x10;
           }
           else zmena_smeru++;
         }
         break;
    default : break;
   }
  }
  else delicka++;
 }

int main (void)
{
 DDRB |= 0x01;   // PB0 vystupny, je tam generovane PWM
 DDRB |= 0x10;   // PB4 vystupny, spina rele a meni smer
 PORTB &= ~0x01; // Vynulovanie PB0
 PORTB &= ~0x10; // Vynulovanie PB4
 DDRB &= ~0x06;  // PB1 a PB2 ako vstupne, pre tlacidla;
 PORTB |= 0x06;  // Aktivacia PULL-UP na PB1 a PB2
 TCNT0 = 0x7F;   // Casovac mas rozsah od 7F po FF
 TIMSK0 |= 0x02; // Povolenie preruseni od pretecenia timer0
 TCCR0B |= 0x03; // Prescaller na 64
 OCR0A = 0xFF;   // Pociatocna hodnota PWM
 TCCR0A |= 0xC3; // Nastavi PB0 pri zhode a FAST PWM mod 
 sei();          // Povolenie preruseni

 while(1) // nekonecny cyklus
  {
  }
}

Program v mikroprocesore a súvislosť so schémou

Začnem hlavnou funkciou. Prvý šesť riadkov nastavuje piny mikroprocesora podľa ich požadovanej funkcie.

DDRB |= 0x01;   // PB0 vystupny, je tam generovane PWM
DDRB |= 0x10;   // PB4 vystupny, spina rele a meni smer
PORTB &= ~0x01; // Vynulovanie PB0
PORTB &= ~0x10; // Vynulovanie PB4
DDRB &= ~0x06;  // PB1 a PB2 ako vstupne, pre tlacidla;
PORTB |= 0x06;  // Aktivacia PULL-UP na PB1 a PB2

Na pine PB0 (vývod č. 5.) je cez rezistor R9 spínaný tranzistor Q4, ktorý cez rezistor R10 spína tranzistor Q3. Tento pin generuje PWM a riadi rýchlosť vlaku. Mikroprocesor nedokáže poskytnúť dostatočný prúd, aby tranzistor Q3 vybudil, preto je zosilnený cez Q4. Pin PB4 (vývod č. 3.) spína cez rezistor R6 tranzistor Q1 a relé K1. Tým sa mení smer jazdy vlaku.

Ak nie je tranzistor Q1 zopnutý (pin PB4 = 0), cez relé prechádza veľmi malý prúd, ktorý cez rezistor R7, tranzistor Q2 rozsvieti diódu LED2. Tým je indikovaná jazda do jednej strany. Keď pin PB4 zopne tranzistor  Q1, zopne relé K1. Vtedy je na kolektore tranzistora Q1 asi 0.7V, preto LED2 zhasne, ale rozsvieti sa LED1. Takto signalizuje opačný smer jazdy.

Piny PB1 (vývod č. 6.)  a PB2 (vývod č. 7.) sú nastavené ako vstupné, pretože cez je zisťovaná poloha joysticka. Mikroprocesor registruje 4 stavy: páka hore, páka dole, páka vľavo/vpravo, páka v strede.

Druhá polovica hlavnej funkcie súvisí s časovačom

TCNT0 = 0x7F;   // Casovac ma rozsah od 7F po FF
TIMSK0 |= 0x02; // Povolenie preruseni od pretecenia timer0
TCCR0B |= 0x03; // Prescaller na 64
OCR0A = 0xFF;   // Pociatocna hodnota PWM
TCCR0A |= 0xC3; // Nastavi PB0 pri zhode a FAST PWM mod 
sei();          // Povolenie preruseni

Časovač má rozsah 0×00 až 0xFF (255 krokov), ja ho znižujem na polovicu ( TCNT0 = 0x7F; ). Tým sa frekvencia PWM zdvojnásobí. Potom povolím prerušenia od časovača ( TIMSK0 |= 0×02; ). Zase skončím na nastavovanie časovača, pretože prescallerom znížim jeho frekvenciu ( TCCR0B |= 0×03; ). Zostáva už len PWM, register OCR0A nastavím na 0xFF, čím zaručím, že začínam s 0% PWM. Už len zostáva nastaviť správny PWM mód ( TCCR0A |= 0xC3; ). Týmito nastaveniami dosiahnem frekvenciu generovaného PWM približne 150Hz.

Register OCR0A a súvislosť s PWM

Kód TCCR0A |= 0xC3; nastavuje na pine č. 5., PB0/OC0A mód FAST PWM. Register TCNT0 časovača TIMER0 stále púčíta v rozsahu 0x7F až 0xFF, kedy sa resetne na 0x7F. Tento register je porovnávaný s OCR0A. Keď nastane zhoda, pin č. 5. je zopnutý a vypne sa až keď TCNT0 = 0xFF. Nižšie hodnoty OCR0A znamenajú vyšší výkon na výstupe.

Pretečenie a TIMER0

Prerušenie od pretečenia časovača TIMER0 je povolené a nastáva, keď register TCNT0 = 0xFF. V tomto prerušení sa sníma poloha páky joysticku.

ISR(TIM0_OVF_vect) // Prerusenie - pretecenie timer0
 {
  TCNT0 = 0x7F;       // nastavenie intervalu casovaca
  if(delicka == 0x03) // spomalenie obsluhy joysticku
  {
  delicka = 0x00;
  switch((PINB & 0x02) | (PINB & 0x04)) // stav joysticku
   {
    case 0x02 : // znizenie vykonu, paka joysticku "DOLE"
        if(OCR0A != 255) OCR0A++;
        break;
    case 0x04 : // zvysenie vykonu, paka joysticku "HORE"
        if(OCR0A != 0x80) OCR0A--;
        break;
    case 0x00 : // zmena smeru, paka joysticku "VLAVO/VRAVO"
        if(OCR0A == 255) // zmena smeru len ak vykon = 0%
         {
          if(zmena_smeru == 0x40)
           {
            zmena_smeru = 0x00;
            PORTB ^= 0x10;
           }
           else zmena_smeru++;
         }
         break;
    default : break;
   }
  }
  else delicka++;
 }

Akonáhle vznikne prerušenie, zavolá sa funkcia ISR(TIM0_OVF_vect), ktorá ho obslúži. V prvom kroku obslúži časovač, nastaví ho na 0x7F. Potom sa už len venuje obsluhe joysticku. Teraz je dobré, ukázať trochu matematiky, aby ste celú funkciu pochopili.

  • Vďaka mojím nastaveniam časovača beží PWM na frekvencii 150Hz.
  • Čo tiež znamená, že prerušenie je vyvolané 150x za sekundu.
  • PWM je regulovateľné v 128 krokoch
  • Ak by bol joystick obsluhovaný pri každom prerušení, bolo by to veľmi rýchle
  • Výkon by z 0% na 100% stúpol za 0.85s
  • Čo je nepoužiteľné pre ovládanie
  • Preto joystick obsluhujem len pri každom 3 prerušení
  • Slúži na to premenná “delicka”
  • Musia prejsť 3 prerušenia, aby sa obsluhoval joystick
  • Z 0% na 100% stúpnem za 2.6 sekundy
  • To je už použiteľné aj pre jemnejšiu reguláciu

To isté robí premenná “zmena_smeru”, ktorá delí počet prerušení až 64, aby sa dal pohodlne prepnúť smer.

Sledovanie joysticku a diódová logika

Piny PB1 a PB2 slúžia pre pripojenie joysticka, sú nastavené ako vstupné a majú aktivované PULL-UP rezistory. Je na nich trvale +5V. Tento stav, môžem nazvať aj kľudový, nastáva vždy, keď je páka joysticku v strede, nie je vychýlená do žiadnej strany.

V každej obsluhe joysticku sa mikroprocesor pozerá práve na stav týchto dvoch pinov a podľa nich zisťuje čo má robiť. Má na to príkaz  switch((PINB & 0×02) | (PINB & 0×04)) a celý postup vyzerá takto:

  • Vychýlim páku joysticka dohora
  • Spínač S1 v joysticku zopne a cez diódu D5 uzemní pin PB1 (vývod č. 6.)
  • Na pine PB1 sa objaví úroveň log. 0
  • Časom vzniká prerušenie…
  • Príkaz switch((PINB & 0×02) | (PINB & 0×04)) vyhodnocuje stav…
  • zistí, že PB1 = log. 0 a preto PINB & 0×02 vyhodnotí ako 0×00
  • zistí, že PB2 = log. 1 a preto PINB & 0×04 vyhodnotí ako 0×04
  • Výsledkom logického súčtu je 0×04 (0 | 0×04 = 0×04)
  • Pre mikroprocesor to znamená prípad, že zvyšuje výkon
  • Samozrejme, pokiaľ už výkon nie je 100%

Ak páku vychýlim dodola, udeje sa zhruba to isté, len cez inú diódu a na inom pine. Skončí to znížením výkonu. Trochu rozdielny prípad je, keď páku  vychýlim doľava, alebo doprava. Vtedy už uzemním oba piny (kvôli tomu tie diódy) a to znamená zmenu smeru. Je tam ale podmienka if(OCR0A == 255), aby sa nestalo, že smer jazdy sa prepne, keď je vlak v pohybe .

Niečo na záver

Zariadenie splnilo všetko čo chcem. Jednoducho sa dá ovládať vláčik, dá sa ovládať aj externe a nie je problém pripojiť aj programátor a kedykoľvek upraviť jeho chovanie. Zjednodušil som ho preto, že človek chce sledovať vláčiky, nie displej a podobné hlúposti. Tie dorobím ako modul a budú predmetom ďalšieho článku.

Autorom článku je : Lukáš

Lukáš je človek, venujúci sa všetkému možnému, ktorý sa dosť často niekde poflakuje s foťákom, alebo bicyklom. Profesionálne sa venuje silnoprúdovej elektrotechnike, amatérsky slaboprúdovej.